最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

編寫高性能.net代碼-JIT

2023-03-19 14:29 作者:79732017138_bili  | 我要投稿

? ? ?哈哈,本章就當了解吧,底層的內容需要自己去單獨學習了


托管程序在運行時會加載CLR,CLR會先執(zhí)行一些封裝代碼,都是匯編代碼。程序集的托管代碼在第一次運行時,都會執(zhí)行一小段調用即時編譯器(Just-in-Time,JIT)的“樁”代碼(Stub),JIT會把方法的IL轉換為硬件匯編指令

大部分時候,每個方法只需要經(jīng)過一次JIT編譯。但如果方法帶有泛型(Generic Type)參數(shù)則不一定,這時有可能會對每一種不同類型的參數(shù)都調用一次JIT

如果你的應用程序或者用戶很在意第一次JIT編譯造成的延時,那么你就需要特別關注一下。大部分應用程序只是關心穩(wěn)定運行期間的性能,但如果你需要很高的可用性,那么JIT可能會成為一個需要優(yōu)化的問題

3.1 JIT編譯的好處

引用的就近訪問可能性很高——一起調用的代碼常常會存放在同一個內存頁中,避免了缺頁中斷的開銷

內存占用降低——只會對真正用到的方法進行編譯

交叉匯編內聯(lián)化(Cross-assembly Inlining)——可以把其他DLL中的方法(包括 .NET Framework中的)內嵌到你的應用程序中,以顯著提升性能

可以針對硬件特性進行優(yōu)化,但在實踐中針對特定平臺的優(yōu)化十分有限

.NET中的大部分代碼優(yōu)化都不是在語言的編譯器中實現(xiàn)的(從C#/VB.NETIL),而是發(fā)生在JIT編譯器的即時編譯過程中

3.2 JIT編譯的開銷

JIT在幕后的處理過程

3.3 JIT編譯器優(yōu)化

JIT編譯器會進行一些標準的代碼優(yōu)化工作,比如方法內聯(lián)和去除數(shù)組范圍檢查代碼

JIT最大的優(yōu)化工作就是方法內聯(lián)

就是把方法體內的代碼嵌入調用的位置,避免原先的方法調用。對于那些會被頻繁調用的小型函數(shù)而言,代碼內聯(lián)比較有意義,因為小型函數(shù)的調用開銷會大于代碼本身的執(zhí)行開銷

以下這些情況都會阻止方法內聯(lián)的發(fā)生

虛方法

同一處調用了接口(Interface)的多種實現(xiàn)代碼

循環(huán)

異常處理函數(shù)

遞歸

方法體的IL編碼大于32個字節(jié)

3.4 減少JIT編譯時間和程序啟動時間

JIT編譯器關乎性能的另一個主要因素是生成代碼所耗費的時間,歸根結底最主要還是取決于需要編譯的代碼量

特別注意

可能有大量代碼是你看不到的,實際執(zhí)行的代碼明顯要比源代碼中看到的要多得多。對全部隱藏代碼進行JIT編譯可能需要耗費相當多的時間。特別是正則表達式和代碼自動生成,有可能會生成大量重復的代碼

LINQ

LINQ簡潔的語法,把執(zhí)行查詢時實際運行的代碼數(shù)量隱藏了起來。LINQ還把生成委托、分配內存等行為也都隱藏了。簡單的LINQ查詢也許沒有問題,但最重要的一點是你應該進行確切的性能評估

dynamic關鍵字

dynamic關鍵字帶來的主要問題,也是因為它會轉換為大量的代碼

正則表達式

正則表達式會轉換為一個動態(tài)程序集中的IL狀態(tài)機,然后進行JIT編譯。這在一開始會多花一些時間,但重復執(zhí)行時就能節(jié)省很多時間

代碼自動生成

還有JIT之外的因素也會影響啟動時間

比如I/O就會增加啟動開銷

PerfView 分析JIT代碼樁

?

3.5 利用Profile優(yōu)化JIT編譯

Profile文件可被用于代碼執(zhí)行之前的生成過程。Profile的記錄過程運行在獨立的線程中,保存下來的Profile可以讓生成的代碼獲得與JIT編譯相同的就近訪問可能性(Locality)。該Profile在程序每次執(zhí)行時都會自動更新

啟用Profile

ProfileOptimization.SetProfileRoot(@”C:\MyAppProfile”); ProfileOptimization.StartProfile(“default”);

3.6 使用NGEN的時機(簡略)

NGEN把IL匯編代碼轉換為本機映像,實際上就是運行JIT編譯器并把編譯結果保存到本機映像程序集緩存目錄中

NGEN一般是作為最后的手段來使用

第一個缺點就是喪失了對象引用的就近訪問可能性

你可能還失去了某些優(yōu)化效果,比如交叉匯編的內聯(lián)化

如果應用程序的啟動(“預熱”)開銷太高,上一節(jié)所述的Profile優(yōu)化效果也無法滿足性能需求,可能就該輪到NGEN上場了

決定使用NGEN之前,請牢記性能優(yōu)化的基本指導原則是:評估、評估、再評估

3.6.2 本機代碼生成

3.7 JIT無法勝任的場合

比如有一些處理器指令JIT是不會去使用的,即便當前的處理器能夠支持也不會。數(shù)量最多的就是大部分SSE和SIMD指令

JIT編譯器另一個不如本機代碼編譯器的地方,就是托管數(shù)組與直接訪問本機內存的對比

直接訪問本機內存通常意味著無需復制內存,而托管代碼卻是需要封送(Marshalling)的。雖然有辦法繞過內存復制,比如用UnmanagedMemoryStream把本機緩沖區(qū)封裝為Stream,但這樣實際上你是在做不安全的內存訪問

果應用程序要執(zhí)行大量的數(shù)組或矩陣計算,你就不得不在性能和安全性之間做出平衡

如果你真的發(fā)現(xiàn)本機代碼的效率要更高一些,可以嘗試用P/Invoke把所有數(shù)據(jù)封送給本機代碼編寫的函數(shù),把計算交給高度優(yōu)化的C++ DLL完成,然后把結果返回給托管代碼

3.8 評估

3.8.1 性能計數(shù)器

# of IL Bytes Jitted

# of Methods Jitted

Time in Jit

IL Bytes Jitted / sec

Standard Jit Failures

Total # of IL Bytes Jitted(和“# of IL Bytes Jitted”完全一樣)

Time Loading

Bytes in Loader Heap

Total Assemblies

Total Classes Loaded

3.8.2 ETW事件

利用ETW事件,對每一個JIT編譯過的方法,你都可以得到大量詳細的性能數(shù)據(jù),包括IL代碼大小和JIT編譯耗時

MethodID——該方法的唯一ID。

ModuleID——該方法所屬模塊(Module)的唯一ID。

MethodILSize——該方法IL代碼的大小。

MethodNameSpace——與該方法關聯(lián)的完整命名空間名稱。

MethodName——方法名稱。

MethodSignature——方法的簽名,以逗號分隔的類型名稱列表

MethodFlags:

◎0x1——動態(tài)方法。

◎0x2——泛型方法。

◎0x4——經(jīng)JIT編譯的方法(否則為NGEN處理過的方法)。

◎0x8——JIT助手方法。

3.8.3 找出JIT耗時最長的方法和模塊

JIT的耗時通常與方法中的IL指令數(shù)量直接相關,但由于類型加載時間也可能包含在JIT耗時中,問題就變得復雜了,特別是當模塊被第一次用到時

3.9 小結

請認真考慮那些有可能大量自動生成的代碼

Profile優(yōu)化可以對絕大部分使用到的代碼進行并行JIT編譯,可用于減少應用程序的啟動時間

如果要從函數(shù)內聯(lián)中獲得性能收益,請避免用到虛方法、循環(huán)、異常處理、遞歸和代碼較多的方法體

對于大型應用,或者對程序啟動階段的JIT開銷無法容忍,可以考慮使用NGEN,在使用NGEN之前,請用MPGO對本機映像進行優(yōu)化


本文使用 文章同步助手 同步


編寫高性能.net代碼-JIT的評論 (共 條)

分享到微博請遵守國家法律
佛教| 稻城县| 乌恰县| 铜山县| 望奎县| 乌拉特前旗| 延寿县| 大英县| 晋宁县| 新竹市| 大厂| 博湖县| 东台市| 陈巴尔虎旗| 会理县| 遵义县| 廉江市| 尚志市| 洛扎县| 息烽县| 孝感市| 图木舒克市| 苏尼特左旗| 河源市| 正定县| 巫溪县| 平和县| 富源县| 鹤山市| 株洲市| 宁蒗| 茶陵县| 奉新县| 西宁市| 淮滨县| 昌宁县| 东阳市| 秭归县| 宁远县| 雅江县| 广德县|