<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ASP.NET Core 6 的性能改進(jìn),這些你應(yīng)該知道!

          共 14609字,需瀏覽 30分鐘

           ·

          2022-03-16 10:10

          受到 由Stephen Toub 發(fā)布的關(guān)于 .NET 性能的博客的啟發(fā),我們正在寫(xiě)一篇類似的文章來(lái)強(qiáng)調(diào)ASP.NET Core 在6.0 中所做的性能改進(jìn)。



          基準(zhǔn)設(shè)置

          我們整個(gè)過(guò)程中大部分的實(shí)例使用的是BenchmarkDotNet。在此鏈接上提供了repo,其中包括本文中使用的大多數(shù)基準(zhǔn)。

          BenchmarkDotNet

          https://github.com/dotnet/benchmarkdotnet

          在此鏈接

          https://github.com/BrennanConroy/BlogPost60Bench


          本文中的大多數(shù)基準(zhǔn)測(cè)試結(jié)果都是通過(guò)以下命令行生成的:


          然后從列表中選擇要運(yùn)行的特定基準(zhǔn)。

          這命令行給BenchmarkDotNet指令:

          • 在發(fā)布配置中構(gòu)建所有內(nèi)容。

          • 針對(duì) .NET Framework 4.8 外圍區(qū)域構(gòu)建它。

          • 在 .NET Framework 4.8、.NET Core 3.1、.NET 5 和 .NET 6 上運(yùn)行每個(gè)基準(zhǔn)測(cè)試。

          • 對(duì)于某些基準(zhǔn)測(cè)試,它們僅在 .NET 6 上運(yùn)行(例如,如果比較同一版本上的編碼的兩種方式):

          dotnet run -c Release -f net6.0 --runtimes net6.0
          對(duì)于其他人,只運(yùn)行了版本的一個(gè)子集,例如
          dotnet run -c Release -f net5.0 --runtimes net5.0 net6.0
          我將包括用于運(yùn)行每個(gè)基準(zhǔn)測(cè)試的命令。


          本文中的大多數(shù)結(jié)果都是在Windows上運(yùn)行上述基準(zhǔn)測(cè)試生成的,主要是為了將. NET Framework 4.8包含在結(jié)果集中。但是,除非另有說(shuō)明,一般來(lái)說(shuō),所有這些基準(zhǔn)測(cè)試在Linux或macOS上運(yùn)行時(shí)都顯示出相當(dāng)顯著的改進(jìn)。只需確保您已經(jīng)安裝了想要測(cè)量的每個(gè)運(yùn)行時(shí)。這些基準(zhǔn)測(cè)試使用的是.NET 6 RC1的構(gòu)建,以及最新發(fā)布的.NET 5和.NET Core 3.1下載。

          .NET 6 RC1的構(gòu)建

          https://github.com/dotnet/installer/blob/main/README.md#installers-and-binaries

          最新發(fā)布

          https://dotnet.microsoft.com/en-us/download


          span< T >

          自從在.NET 2.1中增加了Span,之后的每一個(gè)版本我們都轉(zhuǎn)換了更多的代碼以在內(nèi)部和作為公共API的一部分使用Span來(lái)提高性能。這次發(fā)布也不例外。


          PR?dotnet/aspnetcore#28855?在添加兩個(gè) PathString 實(shí)例時(shí)刪除了來(lái)自 string.SubString的 PathString 中的臨時(shí)字符串分配,而是使用 Span作為臨時(shí)字符串。在下面的基準(zhǔn)測(cè)試中,我們使用一個(gè)短字符串和一個(gè)長(zhǎng)字符串來(lái)顯示避免使用臨時(shí)字符串的性能差異。

          dotnet run -c Release -f net48 --runtimes net48 net5.0 net6.0 --filter *PathStringBenchmark*
          private PathString _first = new PathString("/first/");private PathString _second = new PathString("/second/");private PathString _long = new PathString("/longerpathstringtoshowsubstring/");
          [Benchmark]public PathString AddShortString(){ return _first.Add(_second);}
          [Benchmark]public PathString AddLongString(){ return _first.Add(_long);}

          dotnet/aspnetcore#34001引入了一個(gè)新的基于Span的API,用于枚舉查詢字符串,在沒(méi)有編碼字符的常見(jiàn)情況下,該查詢字符串是分配空閑的,當(dāng)查詢字符串包含編碼字符時(shí),分配更低。

          dotnet run -c Release -f net6.0 --runtimes net6.0 --filter *QueryEnumerableBenchmark*
          #if NET6_0_OR_GREATER public enum QueryEnum { Simple = 1, Encoded, } [ParamsAllValues] public QueryEnum QueryParam { get; set; }
          private string SimpleQueryString = "?key1=value1&key2=value2"; private string QueryStringWithEncoding = "?key1=valu%20&key2=value%20"; [Benchmark(Baseline = true)] public void QueryHelper() { var queryString = QueryParam == QueryEnum.Simple ? SimpleQueryString : QueryStringWithEncoding; foreach (var queryParam in QueryHelpers.ParseQuery(queryString)) { _ = queryParam.Key; _ = queryParam.Value; } } [Benchmark] public void QueryEnumerable() { var queryString = QueryParam == QueryEnum.Simple ? SimpleQueryString : QueryStringWithEncoding; foreach (var queryParam in new QueryStringEnumerable(queryString)) { _ = queryParam.DecodeName(); _ = queryParam.DecodeValue(); } }#endif

          需要注意的是,天下沒(méi)有免費(fèi)的午餐。在新的QueryStringEnumerable API的情況下,如果您計(jì)劃多次枚舉查詢字符串值,它實(shí)際上可能比使用 QueryHelpers.ParseQuery 并存儲(chǔ)已解析查詢字符串值的字典更昂貴。


          @paulomorgado?的?dotnet/aspnetcore#29448?使用?string.Create?方法,如果您知道字符串的最終大小,則該方法允許在創(chuàng)建字符串后對(duì)其進(jìn)行初始化。這是用來(lái)移除UriHelper.BuildAbsolute中的一些臨時(shí)字符串分配。

          dotnet run -c Release -f netcoreapp3.1 --runtimes netcoreapp3.1 net6.0 --filter *UriHelperBenchmark*
          #if NETCOREAPP [Benchmark] public void BuildAbsolute() { _ = UriHelper.BuildAbsolute("https", new HostString("localhost")); }#endif
          PR?dotnet/aspnetcore#31267將 ContentDispositionHeaderValue 中的一些解析邏輯轉(zhuǎn)換為使用基于 Span 的 API,以避免在常見(jiàn)情況下出現(xiàn)臨時(shí)字符串和臨時(shí) byte[]。
          dotnet run -c Release -f net48 --runtimes net48 netcoreapp3.1 net5.0 net6.0 --filter *ContentDispositionBenchmark*[Benchmark]public void ParseContentDispositionHeader(){    var contentDisposition = new ContentDispositionHeaderValue("inline");    contentDisposition.FileName = "File?Name.bat";?}

          dotnet/aspnetcore#28855?

          https://github.com/dotnet/aspnetcore/pull/28855

          dotnet/aspnetcore#34001

          https://github.com/dotnet/aspnetcore/pull/34001

          天下沒(méi)有免費(fèi)的午餐

          https://en.wikipedia.org/wiki/There_ain%27t_no_such_thing_as_a_free_lunch

          paulomorgado

          https://github.com/paulomorgado

          dotnet/aspnetcore#29448

          https://github.com/dotnet/aspnetcore/pull/29448

          string.Create

          https://docs.microsoft.com/en-us/dotnet/api/system.string.create?view=net-6.0



          空閑連接

          ASP.NET Core 的主要組件之一是托管服務(wù)器,它帶來(lái)了許多不同的問(wèn)題需要去優(yōu)化。我們將重點(diǎn)關(guān)注6.0中空閑連接的改進(jìn),在其中我們做了許多更改,以減少連接等待數(shù)據(jù)時(shí)所使用的內(nèi)存量。


          我們進(jìn)行了三種不同類型的更改,一種是減少連接使用的對(duì)象的大小,這包括System.IO.Pipelines、SocketConnections 和 SocketSenders。第二種類型的更改是將常用訪問(wèn)的對(duì)象池化,這樣我們就可以重用舊實(shí)例并節(jié)省分配。第三種類型的改變是利用所謂的“零字節(jié)讀取”。在這里,我們嘗試用一個(gè)零字節(jié)緩沖區(qū)從連接中讀取數(shù)據(jù),如果有可用的數(shù)據(jù),,讀取將返回沒(méi)有數(shù)據(jù),但我們知道現(xiàn)在有可用的數(shù)據(jù),可以提供一個(gè)緩沖區(qū)來(lái)立即讀取該數(shù)據(jù)。這避免了為將來(lái)可能完成的讀取預(yù)先分配一個(gè)緩沖區(qū),所以在知道數(shù)據(jù)可用之前,我們可以避免大量的分配。


          dotnet/runtime#49270將 System.IO.Pipelines 的大小從 ~560 字節(jié)減少到 ~368 字節(jié),減少了34%,每個(gè)連接至少有2個(gè)管道,所以這是一個(gè)巨大的勝利。


          dotnet/aspnetcore#31308重構(gòu)了Kestrel的Socket層,以避免一些異步狀態(tài)機(jī),并減少剩余狀態(tài)機(jī)的大小,從而為每個(gè)連接節(jié)省33%的分配。


          dotnet/aspnetcore#30769刪除了每個(gè)連接的PipeOptions分配,并將該分配移動(dòng)到連接工廠,因此我們只分配一個(gè)服務(wù)器的整個(gè)生命周期,并為每個(gè)連接重用相同的選項(xiàng)。來(lái)自@benaadams?的?dotnet/aspnetcore#31311將 WebSocket 請(qǐng)求中眾所周知的標(biāo)頭值替換為內(nèi)部字符串,這允許在頭解析過(guò)程中分配的字符串被垃圾回收,減少了長(zhǎng)期存在的WebSocket連接的內(nèi)存使用。dotnet/aspnetcore#30771重構(gòu)了 Kestrel 中的 Sockets 層,首先避免分配SocketReceiver對(duì)象+ SocketAwaitableEventArgs,并將其合并為單個(gè)對(duì)象,這節(jié)省了幾個(gè)字節(jié),并導(dǎo)致每個(gè)連接分配的對(duì)象較少。該 PR 還匯集了 SocketSender 類,因此您現(xiàn)在平均擁有多個(gè)核心 SocketSender,而不是為每個(gè)連接創(chuàng)建一個(gè)。因此,在下面的基準(zhǔn)測(cè)試中,當(dāng)我們有10,000個(gè)連接時(shí),在我的機(jī)器上只分配了16個(gè)連接,而不是10,000個(gè),這節(jié)省了~ 46mb !


          另一個(gè)類似的大小變化是dotnet/runtime#49123,它增加了對(duì)SslStream中零字節(jié)讀取的支持,這樣我們的10,000個(gè)空閑連接從SslStream分配的~ 46mb到~2.3 MB。dotnet/runtime#49117在 StreamPipeReader 上添加了對(duì)零字節(jié)讀取的支持,然后 Kestrel 在?dotnet/aspnetcore#30863中使用它開(kāi)始在 SslStream 中使用零字節(jié)讀取。


          所有這些變化的最終結(jié)果是大量減少空閑連接的內(nèi)存使用。


          下面的數(shù)字不是來(lái)自于BenchmarkDotNet應(yīng)用程序,因?yàn)樗鼫y(cè)量空閑連接,而且更容易用客戶機(jī)和服務(wù)器應(yīng)用程序進(jìn)行設(shè)置。


          控制臺(tái)和 WebApplication 代碼粘貼在以下要點(diǎn)中:

          https://gist.github.com/BrennanConroy/02e8459d63305b4acaa0a021686f54c7


          下面是10000個(gè)空閑的安全WebSocket連接(WSS)在不同框架上占用服務(wù)器的內(nèi)存。

          這比 net5 減少了近 4 倍的內(nèi)存。

          dotnet/runtime#49270

          https://github.com/dotnet/runtime/pull/49270

          dotnet/aspnetcore#31308

          https://github.com/dotnet/aspnetcore/pull/31308

          dotnet/aspnetcore#30769

          https://github.com/dotnet/aspnetcore/pull/30769

          benaadams

          https://github.com/benaadams

          dotnet/aspnetcore#31311?

          https://github.com/dotnet/aspnetcore/pull/31311

          內(nèi)部字符串

          https://en.wikipedia.org/wiki/String_interning

          dotnet/aspnetcore#30771

          https://github.com/dotnet/aspnetcore/pull/30771

          dotnet/runtime#49123

          https://github.com/dotnet/runtime/pull/49123

          dotnet/runtime#49117

          https://github.com/dotnet/runtime/pull/49117

          dotnet/aspnetcore#30863

          https://github.com/dotnet/aspnetcore/pull/30863



          實(shí)體框架核心

          EF Core在6.0版本中做了大量的改進(jìn),查詢執(zhí)行速度提高了31%,TechEmpower fortune的基準(zhǔn)運(yùn)行時(shí)間更新、優(yōu)化基準(zhǔn)和EF的改進(jìn)提高了70%。


          這些改進(jìn)來(lái)自于對(duì)象池的改進(jìn),智能檢查是否啟用了遙測(cè)技術(shù),以及添加一個(gè)選項(xiàng),當(dāng)你知道你的應(yīng)用程序安全地使用DbContext時(shí),可以選擇退出線程安全檢查。


          請(qǐng)參閱發(fā)布實(shí)體框架核心6.0預(yù)覽版4:性能版的博客文章,其中詳細(xì)強(qiáng)調(diào)了許多改進(jìn)。

          TechEmpower fortune

          https://www.techempower.com/benchmarks/#section=data-r20

          請(qǐng)參閱發(fā)布實(shí)體框架核心6.0預(yù)覽版4:性能版的博客文章

          https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-6-0-preview-4-performance-edition/


          Blazor

          本機(jī)byte[]互操作

          Blazor現(xiàn)在在執(zhí)行JavaScript互操作時(shí)對(duì)字節(jié)數(shù)組有了有效的支持。以前,發(fā)送到和從JavaScript的字節(jié)數(shù)組是Base64編碼的,因此它們可以被序列化為JSON,這增加了傳輸大小和CPU負(fù)載。Base64編碼現(xiàn)在已經(jīng)在.NET6中進(jìn)行了優(yōu)化,允許用戶透明地使用.NET中的byte[]和JavaScript中的Uint8Array。說(shuō)明如何將此特性用于JavaScript到.NET.NET到JavaScript。


          讓我們看一個(gè)快速的基準(zhǔn)測(cè)試,看看byte[]互操作在.NET 5和.NET 6中的區(qū)別。以下Razor代碼創(chuàng)建了一個(gè)22 kB的字節(jié)[],并將其發(fā)送給JavaScript的receiveAndReturnBytes函數(shù),該函數(shù)立即返回字節(jié)[]。這種數(shù)據(jù)往返重復(fù)了10,000次,時(shí)間數(shù)據(jù)被打印到屏幕上。這段代碼對(duì)于.NET 5和.NET 6是相同的。


          @Message@code { public string Message { get; set; } = "Press button to benchmark"; private async Task RoundtripData() { var bytes = new byte[1024*22]; List<double> timeForInterop = new List<double>(); var testTime = DateTime.Now; for (var i = 0; i < 10_000; i++) { var interopTime = DateTime.Now; var result = await JSRuntime.InvokeAsync<byte[]>("receiveAndReturnBytes", bytes);
          timeForInterop.Add(DateTime.Now.Subtract(interopTime).TotalMilliseconds); } Message = $"Round-tripped: {bytes.Length / 1024d} kB 10,000 times and it took on average {timeForInterop.Average():F3}ms, and in total {DateTime.Now.Subtract(testTime).TotalMilliseconds:F1}ms"; }}


          接下來(lái)我們來(lái)看一下receiveAndReturnBytes JavaScript函數(shù)。在.NET 5。我們必須首先將Base64編碼的字節(jié)數(shù)組解碼為Uint8Array,以便它可以在應(yīng)用程序代碼中使用。然后,在將數(shù)據(jù)返回給服務(wù)器之前,我們必須將其重新編碼為Base64。

          function receiveAndReturnBytes(bytesReceivedBase64Encoded) {    const bytesReceived = base64ToArrayBuffer(bytesReceivedBase64Encoded);    // Use Uint8Array data in application    const bytesToSendBase64Encoded = base64EncodeByteArray(bytesReceived);    if (bytesReceivedBase64Encoded != bytesToSendBase64Encoded) {        throw new Error("Expected input/output to match.")    }    return bytesToSendBase64Encoded;}// https://stackoverflow.com/a/21797381function base64ToArrayBuffer(base64) {    const binaryString = atob(base64);    const length = binaryString.length;    const result = new Uint8Array(length);    for (let i = 0; i < length; i++) {        result[i] = binaryString.charCodeAt(i);    }    return result;}function base64EncodeByteArray(data) {    const charBytes = new Array(data.length);    for (var i = 0; i < data.length; i++) {        charBytes[i] = String.fromCharCode(data[i]);    }    const dataBase64Encoded = btoa(charBytes.join(''));    return dataBase64Encoded;}


          編碼/解碼在客戶機(jī)和服務(wù)器上都增加了巨大的開(kāi)銷,同時(shí)還需要大量的樣板代碼。那么在.NET 6中如何實(shí)現(xiàn)呢? 嗯,它相當(dāng)簡(jiǎn)單:

          function receiveAndReturnBytes(bytesReceived) {    // bytesReceived comes as a Uint8Array ready for use    // and can be used by the application or immediately returned.    return bytesReceived;}


          因此,編寫(xiě)它肯定更容易,但它的性能如何呢?分別在.NET 5和.NET 6的blazorserver模板中運(yùn)行這些代碼片段,在Release配置下,我們看到.NET 6在byte[]互操作方面有78%的性能提升!


          請(qǐng)注意,流式互操作支持還可以有效下載(大)文件,有關(guān)更多詳細(xì)信息,請(qǐng)參閱文檔。


          InputFile 組件已升級(jí)為通過(guò) dotnet/aspnetcore#33900 使用流式傳輸。

          此外,這個(gè)字節(jié)數(shù)組互操作支持在框架中被用來(lái)支持JavaScript和.NET之間的雙向流互操作。用戶現(xiàn)在能夠傳輸任意二進(jìn)制數(shù)據(jù)。有關(guān)從?.NET 流式傳輸?shù)?JavaScript?的文檔可在此處獲得,JavaScript 到 .NET 文檔可在此處獲得。

          JavaScript到.NET

          https://docs.microsoft.com/dotnet/csharp/language-reference/keywords/using-directive#global-modifier

          .NET到JavaScript

          https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript?view=aspnetcore-6.0#byte-array-support

          .NET 流式傳輸?shù)?JavaScript

          https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet?view=aspnetcore-6.0#stream-from-net-to-javascript

          JavaScript 到 .NET 文檔

          https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript?view=aspnetcore-6.0#stream-from-javascript-to-net



          輸入文件

          使用上面提到的Blazor Streaming Interop,我們現(xiàn)在支持通過(guò)InputFile組件上傳大文件(以前的上傳限制在2GB左右)。由于使用了本地byte[]流,而不是使用Base64編碼,該組件的速度也有了顯著提高。例如,例如,與.NET 5相比,一個(gè)100mb文件的上傳速度要快77%。

          請(qǐng)注意,流式互操作支持還可以有效下載(大)文件,有關(guān)更多詳細(xì)信息,請(qǐng)參閱文檔。


          InputFile 組件已升級(jí)為通過(guò)dotnet/aspnetcore#33900使用流式傳輸。

          上傳大文件

          https://docs.microsoft.com/en-us/aspnet/core/blazor/file-uploads?view=aspnetcore-6.0&pivots=server

          文檔

          https://docs.microsoft.com/en-us/aspnet/core/blazor/file-downloads?view=aspnetcore-6.0

          dotnet/aspnetcore#33900

          https://github.com/dotnet/aspnetcore/pull/33900



          大雜燴

          來(lái)自@benaadams?的?dotnet/aspnetcore#30320?對(duì)我們的 Typescript 庫(kù)進(jìn)行了現(xiàn)代化改造并對(duì)其進(jìn)行了優(yōu)化,因此網(wǎng)站加載速度更快。signalr.min.js 文件從 36.8 kB 壓縮和 132 kB 未壓縮變?yōu)?16.1 kB 壓縮和 42.2 kB 未壓縮。blazor.server.js 文件壓縮后為 86.7 kB,未壓縮時(shí)為 276 kB,壓縮后為 43.9 kB,未壓縮時(shí)為 130 kB。


          @benaadams?的?dotnet/aspnetcore#31322在從連接功能集合中獲取常用功能時(shí)刪除了一些不必要的強(qiáng)制轉(zhuǎn)換。這在訪問(wèn)集合中的常見(jiàn)特征時(shí)提供了約 50% 的改進(jìn)。不幸的是,在基準(zhǔn)測(cè)試中看到性能改進(jìn)是不可能的,因?yàn)樗枰欢褍?nèi)部類型,所以我將在此處包含來(lái)自 PR 的數(shù)字,如果您有興趣運(yùn)行它們,PR 包括可以運(yùn)行的基準(zhǔn)反對(duì)內(nèi)部代碼。


          dotnet/aspnetcore#31519?也來(lái)自@benaadams,將默認(rèn)接口方法添加到 IHeaderDictionary 類型,以通過(guò)以標(biāo)頭名稱命名的屬性訪問(wèn)公共標(biāo)頭。訪問(wèn)標(biāo)題字典時(shí)不再輸入錯(cuò)誤的常見(jiàn)標(biāo)題!這篇博客文章中更有趣的是,這個(gè)改變?cè)试S服務(wù)器實(shí)現(xiàn)返回一個(gè)自定義標(biāo)頭字典,以更優(yōu)化地實(shí)現(xiàn)這些新的接口方法。例如,服務(wù)器可能會(huì)將標(biāo)頭值直接存儲(chǔ)在一個(gè)字段中,并直接返回該字段,而不是在內(nèi)部字典中查詢標(biāo)頭值,這需要對(duì)鍵進(jìn)行哈希并查找條目。在某些情況下,當(dāng)獲取或設(shè)置標(biāo)頭值時(shí),此更改可帶來(lái)高達(dá)480%的改進(jìn)。再一次,為了正確地對(duì)這個(gè)變化進(jìn)行基準(zhǔn)測(cè)試,以顯示它需要使用內(nèi)部類型進(jìn)行設(shè)置,所以我將包括來(lái)自PR的數(shù)字,對(duì)于那些有興趣嘗試它的人來(lái)說(shuō),PR包含在內(nèi)部代碼上運(yùn)行的基準(zhǔn)測(cè)試。


          dotnet/aspnetcore#31466使用 .NET 6 中引入的新 CancellationTokenSource.TryReset() 方法在連接關(guān)閉但未取消的情況下重用 CancellationTokenSource。下面的數(shù)字是通過(guò)運(yùn)行bombardier對(duì)Kestrel的125個(gè)連接收集的,它運(yùn)行了大約10萬(wàn)個(gè)請(qǐng)求。


          dotnet/aspnetcore#31528dotnet/aspnetcore#34075分別對(duì)重用HTTPS握手和HTTP3流的CancellationTokenSource做了類似的更改。


          dotnet/aspnetcore#31660通過(guò)在SignalR中為整個(gè)流重用分配的StreamItem對(duì)象,而不是為每個(gè)流項(xiàng)分配一個(gè),提高了服務(wù)器對(duì)客戶端流的性能。而dotnet/aspnetcore#31661將HubCallerClients對(duì)象存儲(chǔ)在SignalR連接上,而不是為每個(gè)Hub方法調(diào)用分配它。


          @ShreyasJejurkar的?dotnet/aspnetcore#31506重構(gòu)了WebSocket握手的內(nèi)部結(jié)構(gòu),以避免臨時(shí)List分配。@gfoidl?中的?dotnet/aspnetcore#32829重構(gòu)QueryCollection以減少分配和向量化一些代碼。@benaadams?的?dotnet/aspnetcore#32234?刪除了 HttpRequestHeaders 枚舉中未使用的字段,該字段通過(guò)不再為每個(gè)枚舉的標(biāo)頭分配字段來(lái)提高性能。


          來(lái)自?martincostello?的?dotnet/aspnetcore#31333?將 Http.Sys 轉(zhuǎn)換為使用?LoggerMessage.Define,這是高性能日志記錄 API。這避免了不必要的值類型裝箱、日志格式字符串的解析,并且在某些情況下避免了在日志級(jí)別未啟用時(shí)分配字符串或?qū)ο蟆?/p>


          dotnet/aspnetcore#31784添加了一個(gè)新的 IApplicationBuilder。使用重載來(lái)注冊(cè)中間件,以避免在運(yùn)行中間件時(shí)進(jìn)行一些不必要的按請(qǐng)求分配。舊代碼如下所示:

          app.Use(async (context, next) =>{    await next();});新代碼如下:app.Use(async (context, next) =>{    await next(context);});

          下面的基準(zhǔn)測(cè)試模擬中間件管道,而不需要設(shè)置服務(wù)器來(lái)展示改進(jìn)。使用int代替HttpContext用于請(qǐng)求,中間件返回一個(gè)完成的任務(wù)。

          dotnet run -c Release -f net6.0 --runtimes net6.0 --filter *UseMiddlewareBenchmark*static private Func, Func> UseOld(Func, Task> middleware){    return next =>    {        return context =>        {            Func simpleNext = () => next(context);            return middleware(context, simpleNext);        };    };}static private Func, Func> UseNew(Func, Task> middleware){    return next => context => middleware(context, next);}Func Middleware = UseOld((c, n) => n())(i => Task.CompletedTask);Func NewMiddleware = UseNew((c, n) => n(c))(i => Task.CompletedTask);[Benchmark(Baseline = true)]public Task Use(){    return Middleware(10);}[Benchmark]public Task UseNew(){    return NewMiddleware(10);}

          dotnet/aspnetcore#30320

          https://github.com/dotnet/aspnetcore/pull/30320

          dotnet/aspnetcore#31322

          https://github.com/dotnet/aspnetcore/pull/31322

          dotnet/aspnetcore#31519

          https://github.com/dotnet/aspnetcore/pull/31519

          默認(rèn)接口方法

          https://devblogs.microsoft.com/dotnet/default-implementations-in-interfaces/

          dotnet/aspnetcore#31466

          https://github.com/dotnet/aspnetcore/pull/31466

          bombardier

          https://github.com/codesenberg/bombardier

          dotnet/aspnetcore#31528

          https://github.com/dotnet/aspnetcore/pull/31528

          dotnet/aspnetcore#34075

          https://github.com/dotnet/aspnetcore/pull/34075

          dotnet/aspnetcore#31660

          https://github.com/dotnet/aspnetcore/pull/31660

          服務(wù)器對(duì)客戶端流

          https://docs.microsoft.com/en-us/aspnet/core/signalr/streaming?view=aspnetcore-5.0#server-to-client-streaming

          dotnet/aspnetcore#31661

          https://github.com/dotnet/aspnetcore/pull/31661

          ShreyasJejurkar

          https://github.com/ShreyasJejurkar

          dotnet/aspnetcore#32234

          https://github.com/dotnet/aspnetcore/pull/32234

          martincostello

          https://github.com/martincostello

          dotnet/aspnetcore#31333

          https://github.com/dotnet/aspnetcore/pull/31333

          LoggerMessage.Define

          https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/loggermessage?view=aspnetcore-5.0

          dotnet/aspnetcore#31784

          https://github.com/dotnet/aspnetcore/pull/31784



          總結(jié)

          希望您喜歡閱讀 ASP.NET Core 6.0 中的一些改進(jìn)!我鼓勵(lì)你去看看.NET 6博客中關(guān)于運(yùn)行時(shí)性能改進(jìn)的文章

          https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/



          瀏覽 89
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久綜合很很很 | 小骚逼操死你视频 | 久久精品国产亚洲AV成人婷婷 | 操B久久 操屄av | 久久久久麻豆V国产 |