欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.NET9中異常處理性能提升分析

 更新時(shí)間:2025年06月05日 10:20:28   作者:InCerry  
隨著現(xiàn)代云原生、高并發(fā)、分布式場(chǎng)景的大量普及,異常處理(Exception Handling)早已不再只是一個(gè)冷僻的代碼路徑,下面我們就來看看.NET9中異常處理性能如何提升吧

一、為什么要關(guān)注.NET異常處理的性能

隨著現(xiàn)代云原生、高并發(fā)、分布式場(chǎng)景的大量普及,異常處理(Exception Handling)早已不再只是一個(gè)冷僻的代碼路徑。在高復(fù)雜度的微服務(wù)、網(wǎng)絡(luò)服務(wù)、異步編程環(huán)境下,服務(wù)依賴的外部資源往往不可靠,偶發(fā)失效或小概率的“雪崩”場(chǎng)景已經(jīng)十分常見。實(shí)際系統(tǒng)常常在高頻率地拋出、傳遞、捕獲異常,異常處理性能直接影響著系統(tǒng)的恢復(fù)速度、吞吐量,甚至是穩(wěn)定性與容錯(cuò)邊界。

.NET平臺(tái)在異常處理性能方面長期落后于C++、Java等同類主流平臺(tái)——業(yè)內(nèi)社區(qū)多次對(duì)比公開跑分就證實(shí)了這一點(diǎn),.NET 8時(shí)代雖然差距有所縮小,但在某些高并發(fā)/異步等極端場(chǎng)景下,異常高開銷持續(xù)困擾社區(qū)和大廠工程師。于是到了.NET 9,終于迎來了一次代際變革式的性能飛躍,拋出/捕獲異常的耗時(shí)基本追平C++,成為技術(shù)圈最關(guān)注的.NET runtime底層事件之一。

二、實(shí)測(cè):.NET 9異常處理提速直觀對(duì)比

1. 測(cè)試代碼

最經(jīng)典的異常性能測(cè)試如下——C# 和 Java的實(shí)現(xiàn)基本一致

C#:

class ExceptionPerformanceTest
{
    public void Test()
    {
        var stopwatch = Stopwatch.StartNew();
        ExceptionTest(100_000);
        stopwatch.Stop();
        Console.WriteLine(stopwatch.ElapsedMilliseconds);
    }
    private void ExceptionTest(long times)
    {
        for (int i = 0; i < times; i++)
        {
            try
            {
                throw new Exception();
            }
            catch (Exception ex)
            {
                // Ignore
            }
        }
    }
}

Java:

public class ExceptionPerformanceTest {
    public void Test() {
        Instant start = Instant.now();
        ExceptionTest(100_000);
        Instant end = Instant.now();
        Duration duration = Duration.between(start, end);
        System.out.println(duration.toMillis());
    }

    private void ExceptionTest(long times) {
        for (int i = 0; i < times; i++) {
            try {
                throw new Exception();
            } catch (Exception ex) {
                // Ignore
            }
        }
    }
}

2. 早期測(cè)試結(jié)果

以.NET Core 2.2時(shí)代為例

  • .NET: 2151ms
  • Java: 175ms

.NET 的異常拋出/捕獲速度相較慢得多。但到了.NET 8后期和.NET 9,基準(zhǔn)成績已翻天覆地:

3. 新時(shí)代基準(zhǔn)結(jié)果(.NET 8 vs .NET 9)

借助 BenchmarkDotNet 可以更科學(xué)對(duì)比:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Reports;
using BenchmarkDotNet.Environments;

namespace ExceptionBenchmark
{
    [Config(typeof(Config))]
    [HideColumns(Column.Job, Column.RatioSD, Column.AllocRatio, Column.Gen0, Column.Gen1)]
    [MemoryDiagnoser]
    public class ExceptionBenchmark
    {
        private const int NumberOfIterations = 1000;

        [Benchmark]
        public void ThrowAndCatchException()
        {
            for (int i = 0; i < NumberOfIterations; i++)
            {
                try
                {
                    ThrowException();
                }
                catch
                {
                    // Exception caught - the cost of this is what we're measuring
                }
            }
        }

        private void ThrowException()
        {
            throw new System.Exception("This is a test exception.");
        }

        private class Config : ManualConfig
        {
            public Config()
            {
                AddJob(Job.Default.WithId(".NET 8").WithRuntime(CoreRuntime.Core80).AsBaseline());
                AddJob(Job.Default.WithId(".NET 9").WithRuntime(CoreRuntime.Core90));

                SummaryStyle =
                    SummaryStyle.Default.WithRatioStyle(RatioStyle.Percentage);
            }
        }
    }
}

如下圖結(jié)果,拋出+捕獲1000次異常:

  • .NET 8:每次約 12μs
  • .NET 9:每次減少至約 2.8μs (約76~80%提升)

.NET 9的性能提升幾乎讓EH成本降到C++/Java同量級(jí),成為托管平臺(tái)的性能標(biāo)桿之一。

三、.NET早期異常處理為何如此之慢?

1. 策略層面的歷史誤區(qū)

傳統(tǒng)觀點(diǎn)認(rèn)為:“異常只為異常流程準(zhǔn)備,主業(yè)務(wù)應(yīng)以if/else或TryXXX等方式避免極端異常分支”。社區(qū)和官方因此忽視了EH系統(tǒng)的極限性能,無論架構(gòu)設(shè)計(jì)還是細(xì)節(jié)實(shí)現(xiàn)都欠缺優(yōu)化,反映在:

  • 內(nèi)部優(yōu)先保證兼容性和健壯性,而不是高性能
  • 代碼中凡是熱路徑,都讓開發(fā)者“自覺避開異常”

近年來,現(xiàn)代服務(wù)常常:

  • 依賴于“不可靠資源” (如網(wǎng)絡(luò)、外部API、云存儲(chǔ)),短暫失效隨時(shí)發(fā)生
  • 借助基于async/await的異步編程,異常常常跨棧、跨線程重拋
  • 在微服務(wù)系統(tǒng)中,單點(diǎn)故障可能導(dǎo)致“異常風(fēng)暴”,大量請(qǐng)求因依賴故障極短時(shí)間內(nèi)批量失敗

這些場(chǎng)景下,異常處理已極易成為性能瓶頸,應(yīng)用的可用性與SLA依賴于異?;謴?fù)速度。

2. CoreCLR/Mono 異常實(shí)現(xiàn)機(jī)制的先天劣勢(shì)

Windows實(shí)現(xiàn)

采用Windows的Structured Exception Handling (SEH),異常拋出后,OS內(nèi)核統(tǒng)一回溯堆棧、查找/觸發(fā)catch和finally,且需要“雙遍遍歷”棧幀(第一次查catch、第二次觸發(fā)catch/finally,源數(shù)據(jù)由Windows維護(hù))

Structured Exception Handling(結(jié)構(gòu)化異常處理,簡(jiǎn)稱 SEH)是微軟 Windows 操作系統(tǒng)上一種異常處理機(jī)制,主要用于捕獲和處理程序運(yùn)行過程中產(chǎn)生的異常,如訪問違規(guī)(Access Violation)、除零錯(cuò)誤、非法指令等。在 Windows 平臺(tái)上,SEH 被底層編譯器和系統(tǒng)廣泛支持。

用戶層主要通過回調(diào)介入,絕大多數(shù)性能消耗“鎖死”在OS堆棧查找、回調(diào)和上下文切換中,優(yōu)化空間很小

NameExc %ExcInc %Inc
ntdll!RtlpxLookupFunctionTable11.44,52511.44,525
ntdll!RtlpUnwindPrologue11.24,44111.24,441
ntdll!RtlLookupFunctionEntry7.22,85728.411,271
ntdll!RtlpxVirtualUnwind6.52,57917.77,020
ntdll!RtlpLookupDynamicFunctionEntry3.61,4259.83,889
coreclr!EEJitManager::JitCodeToMethodInfo2.91,1672.91,167
ntdll!RtlVirtualUnwind2.91,13717.97,099
ntoskrnl!EtwpWriteUserEvent2.59904.31,708
coreclr!ExceptionTracker::ProcessManagedCallFrame2.494118.77,405
coreclr!ProcessCLRException2.493893.336,969
ntdll!LdrpDispatchUserCallTarget2.28712.2871
coreclr!ExecutionManager::FindCodeRangeWithLock2.28682.2868
coreclr!memset2.07932.0793
coreclr!ExceptionTracker::ProcessOSExceptionNotification1.974231.912,622
coreclr!SString::Replace1.87201.8720
ntoskrnl!EtwpReserveTraceBuffer1.87181.8718
coreclr!FillRegDisplay1.87091.8709
ntdll!NtTraceEvent1.76737.12,803

Unix/Linux實(shí)現(xiàn)

沒有SEH,只能自己模擬

采用C++異常,異常拋出后靠libgcc/libunwind的_C++機(jī)制回溯托管棧,但需“橋接”托管/本地的邊界,異常對(duì)象需反復(fù)throw/catch,初始化/過濾時(shí)會(huì)有多次C++異常嵌套傳遞

libunwind 是一個(gè)開源的?;厮輲?,主要用于在運(yùn)行時(shí)獲取和操作調(diào)用棧,從而支持異常處理、調(diào)試和崩潰分析等功能。

托管運(yùn)行時(shí)(如ExecutionManager) 需要頻繁做函數(shù)表和異常元數(shù)據(jù)線性遍歷(鏈表查找),并發(fā)場(chǎng)景下會(huì)有大量鎖競(jìng)爭(zhēng),極易成為瓶頸

實(shí)際CPU性能熱點(diǎn)采樣發(fā)現(xiàn):

  • libgcc_s.so.1/_Unwind_Find_FDE等C++異常系統(tǒng)函數(shù)占用近13%的熱點(diǎn)
  • 托管代碼層大量鏈表遍歷/鎖(ExecutionManager::FindCodeRangeWithLock等)
  • 多線程/多異常場(chǎng)景下lock惡性競(jìng)爭(zhēng),棧查找速度極慢
OverheadShared ObjectSymbol
+ 8,29%libgcc_s.so.1[.] _Unwind_Find_FDE
+ 2,51%libc.so.6[.] __memmove_sse2_unaligned_erms
+ 2,14%ld-linux-x86-64.so.2[.] _dl_find_object
+ 1,94%libstdc++.so.6.0.30[.] __gxx_personality_v0
+ 1,85%libgcc_s.so.1[.] 0x00000000000157eb
+ 1,77%libc.so.6[.] __memset_sse2_unaligned_erms
+ 1,36%ld-linux-x86-64.so.2[.] __tls_get_addr
+ 1,28%libcoreclr.so[.] ExceptionTracker::ProcessManagedCallFrame
+ 1,26%libcoreclr.so[.] apply_reg_state
+ 1,12%libcoreclr.so[.] OOPStackUnwinderAMD64::UnwindPrologue
+ 1,08%libgcc_s.so.1[.] 0x0000000000016990
+ 1,08%libcoreclr.so[.] ExceptionTracker::ProcessOSExceptionNotification

額外開銷

  • 每次拋出異常需清空/復(fù)制完整CONTEXT結(jié)構(gòu)(Windows上下文),單次就近1KB數(shù)據(jù)
  • 捕獲棧信息、生成調(diào)試輔助、捕獲完整stacktrace等都增加明顯延遲

3. Async/多線程場(chǎng)景放大性能損耗

現(xiàn)代C#的async/await廣泛出現(xiàn)。每遇到await斷點(diǎn),異常需在async狀態(tài)機(jī)多次catch/throw重入口,即使只有1層異常,實(shí)際走了多倍catch分支。多線程下,本地堆?;ゲ魂P(guān)聯(lián),所有?;厮?、元數(shù)據(jù)查找都需走OS或本地鎖/鏈表,進(jìn)一步拉低性能擴(kuò)展性。

4. 跨平臺(tái)和歷史兼容包袱

因Windows/Unix兩套機(jī)制并存,大量platform abstraction和邊界容錯(cuò)邏輯,極大增加了維護(hù)成本和bug風(fēng)險(xiǎn)。每一次異??缃缍夹枰厥馓幚?,開發(fā)運(yùn)維和調(diào)優(yōu)都十分困難。

以下是.NET9以前多線程和單線程異常拋出耗時(shí),可以看到隨著堆棧深度的增加,拋出異常要花費(fèi)的世界越來越長。

四、技術(shù)極客視角:.NET 9徹底變革的細(xì)節(jié)原理

.NET 9之所以實(shí)現(xiàn)了異常處理的性能“質(zhì)變”,核心思路是吸收NativeAOT的極簡(jiǎn)托管實(shí)現(xiàn),將主力流程自托管直接管理,核心只依賴native stack walker完成功能邊界,避免一切反復(fù)嵌套或冗余環(huán)節(jié)。

(一)NativeAOT異常處理架構(gòu)剖析

1. 設(shè)計(jì)變革

  • 完全托管驅(qū)動(dòng)主流程異常的捕獲、catch分派、finally查找、異常對(duì)象/類型的元數(shù)據(jù)查找等主環(huán)節(jié),全部寫成托管代碼(C#邏輯)。
  • native code僅負(fù)責(zé)棧幀展開(stack walking)需要時(shí)才調(diào)用本地API(libunwind/Windows API)由native/cross平臺(tái)實(shí)現(xiàn)stack frame的move next/遍歷,極簡(jiǎn)無其他依賴。
  • 無C++異常橋接,這樣省去了_os-unwind、double catch-rethrow等所有歷史冗余。
  • 功能單純、易于調(diào)優(yōu)和定制,不到300行關(guān)鍵路徑代碼。

2. 優(yōu)勢(shì)分析

  • 代碼極簡(jiǎn),熱路徑關(guān)鍵點(diǎn)完全可控
  • 不存在異步場(chǎng)景下的“狀態(tài)機(jī)分支回溯”性能急劇下滑
  • 托管邏輯易于內(nèi)聯(lián)、緩存
  • Native代碼只做最小功能、極易換實(shí)現(xiàn)/裁剪
  • 性能調(diào)優(yōu)點(diǎn)固定且標(biāo)志性突出(大部分耗時(shí)都在stack walker/元數(shù)據(jù)cache里)
  • 兼容可擴(kuò)展,后續(xù)想做特殊異常/自定義類型極為簡(jiǎn)便

3. 技術(shù)細(xì)節(jié)

  • 異常對(duì)象的stacktrace/元數(shù)據(jù)在托管代碼按需附加
  • 若已知異常只在本地代碼路徑,完全可繞開“不需要的”full stacktrace/callstack/diagnostic等場(chǎng)景
  • 可以整合cache優(yōu)化,如將每個(gè)托管JIT幀的元數(shù)據(jù)查找結(jié)果放本地線程緩存(甚至開啟pgo熱點(diǎn)分支識(shí)別,見后續(xù))。

(二).NET 9實(shí)現(xiàn)與補(bǔ)全 —— 同步NativeAOT設(shè)計(jì)到CoreCLR

在.NET 9,團(tuán)隊(duì)把NativeAOT的異常處理模式移植到了CoreCLR上。主要技術(shù)變更包括:

  • 將異常展開、catch/finally分派等環(huán)節(jié)全部搬到托管主流程
  • native helper只做最小的stack frame展開,與垃圾回收棧遍歷接口復(fù)用(易于維護(hù))
  • 強(qiáng)化托管級(jí)緩存與元數(shù)據(jù)管理。關(guān)鍵鏈表遍歷全部升級(jí)成緩存/高速哈希表,一舉解決了多線程、深棧、頻繁異常場(chǎng)景下的scalability困境
  • 釘死所有多余的C++ throw/catch——對(duì)Unix/Windows都生效
  • 為Async/Await生成優(yōu)化代碼路徑,避免多次重復(fù)拋出/捕獲

工程落地與效果

  • 性能測(cè)試實(shí)測(cè),異常處理耗時(shí)降幅約76%~80%,多線程/高并發(fā)效果更好
  • 性能剖析熱點(diǎn):主要耗時(shí)已縮小到stack walker和關(guān)鍵數(shù)據(jù)結(jié)構(gòu)哈希效率上,其他已近極致
  • 全平臺(tái)統(tǒng)一,無歷史特殊兼容路徑、包袱

真實(shí)圖片示例

1.單線程性能提升圖:

2.多線程性能提升圖:

(三)可進(jìn)一步優(yōu)化的場(chǎng)景與細(xì)節(jié)

熱點(diǎn)分支profile(PGO)

  • 異常的“常用路徑”可被profile,按pgo機(jī)制熱路徑內(nèi)聯(lián)/重編排邏輯
  • 比如async await狀態(tài)機(jī)里常拋異常的分支inline獲得最佳cache局部性

Unwind Section緩存/優(yōu)化

雙檢省棧trace與細(xì)粒度采集

支持僅按需采集stacktrace(避免捕獲所有調(diào)試信息)

特殊場(chǎng)景快速捕獲(業(yè)務(wù)異常/操作性異常)

通過拓展托管catch塊類型,可以極簡(jiǎn)分為業(yè)務(wù)異常與系統(tǒng)異常,實(shí)現(xiàn)“無棧捕獲”,加速高頻捕獲型異常(如EndOfData、ParseError等流控制型異常)

異步異常統(tǒng)一延遲捕獲傳遞

在沒有用戶自定義try塊的async方法中,捕獲異常僅保存,真正拋出延遲到非異常主流程結(jié)束前即可。這將極大降低狀態(tài)機(jī)驅(qū)動(dòng)的拋出/捕獲次數(shù)。

六、總結(jié)展望

.NET 9通過徹底擁抱NativeAOT極簡(jiǎn)式的托管異常處理體系,把歷史包袱(OS-Specific/C++ Exception Bridge/冗余鏈表&鎖/多次catch-rethrow)一舉清除,大幅釋放了異常路徑的性能潛力。這一變革支撐了.NET在微服務(wù)、云原生、異步并發(fā)等新主流場(chǎng)景下的頂級(jí)運(yùn)行時(shí)表現(xiàn)。未來,隨著堆棧展開、元數(shù)據(jù)cache自適應(yīng)等不斷迭代,.NET有望成為托管平臺(tái)的異常處理性能“天花板”。

到此這篇關(guān)于.NET9中異常處理性能提升分析的文章就介紹到這了,更多相關(guān).NET9異常處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用.NET命令行編譯器編譯項(xiàng)目(如ASP.NET、C#等)

    使用.NET命令行編譯器編譯項(xiàng)目(如ASP.NET、C#等)

    很多情況你從網(wǎng)上下載了源程序,卻苦于本機(jī)沒裝開發(fā)環(huán)境而不能編譯查看,下面我簡(jiǎn)單說一下解決辦法。
    2009-03-03
  • asp.net根據(jù)計(jì)算機(jī)MAC地址限定每臺(tái)機(jī)子只能領(lǐng)取一次賬號(hào)

    asp.net根據(jù)計(jì)算機(jī)MAC地址限定每臺(tái)機(jī)子只能領(lǐng)取一次賬號(hào)

    這里只做簡(jiǎn)單演示過程,請(qǐng)根據(jù)您的實(shí)際情況作適當(dāng)修改!另外我的博客只做自己參考查詢方便用,請(qǐng)各位大神不要沒事噴我,知道您的技術(shù)高,我是新手正在努力學(xué)習(xí)當(dāng)中,謝謝
    2012-06-06
  • asp.net AJAX注冊(cè)類

    asp.net AJAX注冊(cè)類

    單純用JavaScript,不需要注冊(cè),但是就是用不了AJAX的某些機(jī)制。
    2010-02-02
  • .Net Core內(nèi)存回收模式及性能測(cè)試對(duì)比分析

    .Net Core內(nèi)存回收模式及性能測(cè)試對(duì)比分析

    下面小編就為大家分享一篇.Net Core內(nèi)存回收模式及性能測(cè)試對(duì)比分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • ASP.NET Core中自定義路由約束的實(shí)現(xiàn)

    ASP.NET Core中自定義路由約束的實(shí)現(xiàn)

    這篇文章主要介紹了ASP.NET Core中自定義路由約束的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • ASP.NET?Core基于現(xiàn)有數(shù)據(jù)庫創(chuàng)建EF模型

    ASP.NET?Core基于現(xiàn)有數(shù)據(jù)庫創(chuàng)建EF模型

    這篇文章介紹了ASP.NET?Core基于現(xiàn)有數(shù)據(jù)庫創(chuàng)建EF模型的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • ASP.NET Core 3.0遷移的完美避坑指南

    ASP.NET Core 3.0遷移的完美避坑指南

    這篇文章主要給大家介紹了關(guān)于ASP.NET Core 3.0遷移的完美避坑指南,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用ASP.NET Core 3.0具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • .NET NativeAOT 用法指南

    .NET NativeAOT 用法指南

    NativeAOT是.NET 8中引入的一種編譯方式,它將代碼編譯成原生代碼,提高性能并節(jié)省資源,然而,NativeAOT也帶來了一些問題,如反射依賴、泛型實(shí)例化等,本文詳細(xì)介紹了如何使用NativeAOT以及如何解決這些常見問題,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • ASP.NET微信公眾號(hào)客服接口

    ASP.NET微信公眾號(hào)客服接口

    這篇文章主要為大家詳細(xì)介紹了ASP.NET微信公眾號(hào)客服接口的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 詳解免費(fèi)高效實(shí)用的.NET操作Excel組件NPOI(.NET組件介紹之六)

    詳解免費(fèi)高效實(shí)用的.NET操作Excel組件NPOI(.NET組件介紹之六)

    這篇文章主要介紹了詳解免費(fèi)高效實(shí)用的.NET操作Excel組件NPOI(.NET組件介紹之六),具有一定的參考價(jià)值,有興趣的可以了解一下。
    2016-12-12

最新評(píng)論