簡體   English   中英

C ++ / cli識別托管/非托管之間的過渡並衡量其成本

[英]C++/cli recognizing transitions between managed/unmanaged and measuring their cost

我對C ++ / cli還是很陌生,不確定在編寫某些內容時是否在做某些在托管時間和非托管時間之間轉換的操作。 例如,我不能添加LARGE_INTEGER或std :: vector作為托管類的成員,但是我可以在托管方法中間使用它,但是我不知道這樣做是否會在托管和非托管之間創建過渡運行時間。 我如何才能看到要強制進行過渡的每個點,以及如何衡量這些過渡的成本?

我想到的一種可能性是,我期望Windows中存在“到非托管的轉換”和“到托管的轉換”代碼塊。 我可以在其中使用諸如windbg等設置斷點的符號嗎,以便查看每個過渡? 有沒有辦法讓Visual Studio在運行時向您顯示每個過渡?

為了測量在有許多轉換時的影響,我是否可以通過xperf看到與Windows事件相對應的事件跟蹤,或者可以通過perfmon看到針對它們的性能計數器?

“非托管運行時”有點矛盾。 非托管代碼無法在虛擬機中運行。 另外,托管運行時本身就是非托管代碼。 我認為您通常對代碼感興趣,不僅是CLR和標准庫,而且最終所有內容都是本機代碼,其中一些是由CLR JIT創建的,其中一些是由本機編譯器創建的,但是全部是本機代碼到底。 .NET和本機異常甚至都有一個通用的異常處理模型(SEH)(或更准確地說,.NET使用操作系統提供的異常模型)。

JIT運行后,沒有太多托管->非托管轉換的跡象,因為它們只是一個簡單的函數調用(調試器可以分辨出差異,因為非托管代碼位於本機庫的地址空間中,而JIT-編譯后的托管代碼位於JIT擁有的動態地址空間中。 由於調用指令是在它所調用的代碼之前創建的,因此反向指令要稍微復雜一些,它必須是間接調用(通過函數指針)。 但這仍然是直接指向JIT編譯的代碼的指針,而不是指向可以在其中放置斷點的單個unmanaged-> managed thunk。 實際上,函數指針可能始於指向JIT本身,它會指出正在調用的方法,對其進行編譯,更新函數指針,最后對目標進行尾部調用,就好像它首先被調用一樣。 。

這是C ++互操作的魔力。 這也意味着托管->非托管過渡實際上甚至都不值得擔心。 剖析並找出哪些代碼路徑比較昂貴,如果事實證明這是托管代碼與非托管代碼之間的調用,請對其進行優化。 但是不要隨意尋找托管/非托管的過渡。

現在,還有其他原因可能需要查找所有托管/非托管轉換。 例如,垃圾收集器可以中斷任何運行托管代碼的線程(同樣,實際運行的代碼是本機代碼,但是GC可以識別它,因為它位於JIT使用的內存空間內,並且JIT生成了對象使用情況表,詳細說明了什么堆棧變量是任何給定指令指針處的可訪問對象)。 因此,如果您想確保某個線程永遠不會被垃圾回收所停止,則需要查找並消除在該線程中運行的函數中的所有非托管->托管過渡。 即使有放置斷點的地方,斷點注入仍然不是正確的方法,因為斷點注入只能捕獲實際進行的轉換,而不是有條件的轉換。

Profiler可以為您提供答案。 您可以使用VS2010 Profiler來測量過渡。

您也可以使用ETW跟蹤,但是要分析它們要困難得多。 PerfMonitor可以幫助您進行ETW跟蹤。

僅供參考,甚至VS2010分析器僅使用ETW跟蹤,但是它具有更好的呈現方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM