日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

都说不要装箱,那装箱到底带来了什么开销?

發(fā)布時(shí)間:2023/12/4 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 都说不要装箱,那装箱到底带来了什么开销? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

相信很有朋友在面試時(shí)大多會(huì)被問到 裝箱 的問題,也是一個(gè)經(jīng)典的問題,可深可淺,那今天我們就從 匯編 和 內(nèi)存 角度進(jìn)行統(tǒng)一解讀下。

為了方便演示,先上一段裝箱的代碼。

class?Program{static?void?Main(string[]?args){var?i?=?10;var?o?=?(object)i;Console.ReadLine();}}

接下來用 windbg 看一下它的匯編代碼。

0:000>?!U?/d?022e089a Normal?JIT?generated?code ConsoleApp1.Program.Main(System.String[]) Begin?022e0848,?size?5bD:\net5\ConsoleApp1\ConsoleApp1\Program.cs?@?15: 022e0872?c745f80a000000??mov?????dword?ptr?[ebp-8],0AhD:\net5\ConsoleApp1\ConsoleApp1\Program.cs?@?17: 022e0879?b9a8429e62??????mov?????ecx,offset?mscorlib_ni!System.Text.Encoding.GetEncodingCodePage(Int32)$##6006719?<PERF>?(mscorlib_ni+0x142a8)?(629e42a8)???????????//?獲取編碼類型 022e087e?e845282ffe??????call????005d30c8?(JitHelp:?CORINFO_HELP_NEWSFAST)??//生成一個(gè)初始化類型放在 eax 中。(objheader+methodtable+占位符) 022e0883?8945f0??????????mov?????dword?ptr?[ebp-10h],eax????????????????????//備份地址到?棧中 022e0886?8b45f0??????????mov?????eax,dword?ptr?[ebp-10h]????????????????????//恢復(fù)?eax?值 022e0889?8b55f8??????????mov?????edx,dword?ptr?[ebp-8]??????????????????????//將?0A?賦給?edx?上 022e088c?895004??????????mov?????dword?ptr?[eax+4],edx??????????????????????//將?edx?賦給?this.x?位置 022e088f?8b45f0??????????mov?????eax,dword?ptr?[ebp-10h]????????????????????//提取棧值到?eax?值 022e0892?8945f4??????????mov?????dword?ptr?[ebp-0Ch],eax????????????????????//將eax賦值給變量?o

因?yàn)槊烤鋮R編代碼都有注釋,我就不解釋了,這里主要看一下 CORINFO_HELP_NEWSFAST方法,它是干什么的呢?這得從源碼說起:

/*?Allocating?a?new?object.?Always?use?ICorClassInfo::getNewHelper()?to?decide?which?is?the?right?helper?to?use?to?allocate?an?object?of?a?given?type.?*/CORINFO_HELP_NEW_CROSSCONTEXT,??//?cross?context?new?objectCORINFO_HELP_NEWFAST,CORINFO_HELP_NEWSFAST,??????????//?allocator?for?small,?non-finalizer,?non-array?objectCORINFO_HELP_NEWSFAST_FINALIZE,?//?allocator?for?small,?finalizable,?non-array?objectCORINFO_HELP_NEWSFAST_ALIGN8,???//?allocator?for?small,?non-finalizer,?non-array?object,?8?byte?alignedCORINFO_HELP_NEWSFAST_ALIGN8_VC,//?allocator?for?small,?value?class,?8?byte?alignedCORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE,?//?allocator?for?small,?finalizable,?non-array?object,?8?byte?alignedCORINFO_HELP_NEW_MDARR,?????????//?multi-dim?array?helper?(with?or?without?lower?bounds?-?dimensions?passed?in?as?vararg)CORINFO_HELP_NEW_MDARR_NONVARARG,//?multi-dim?array?helper?(with?or?without?lower?bounds?-?dimensions?passed?in?as?unmanaged?array)CORINFO_HELP_NEWARR_1_DIRECT,???//?helper?for?any?one?dimensional?array?creationCORINFO_HELP_NEWARR_1_R2R_DIRECT,?//?wrapper?for?R2R?direct?call,?which?extracts?method?table?from?ArrayTypeDescCORINFO_HELP_NEWARR_1_OBJ,??????//?optimized?1-D?object?arraysCORINFO_HELP_NEWARR_1_VC,???????//?optimized?1-D?value?class?arraysCORINFO_HELP_NEWARR_1_ALIGN8,???//?like?VC,?but?aligns?the?array?startCORINFO_HELP_STRCNS,????????????//?create?a?new?string?literalCORINFO_HELP_STRCNS_CURRENT_MODULE,?//?create?a?new?string?literal?from?the?current?module?(used?by?NGen?code)

可以看到,CORINFO_HELP_NEWSFAST 是用于分配 小對(duì)象,無(wú)終結(jié)器,非數(shù)組 的專用方法,也屬于高效的 快速分配路徑,那分配完之后的初始化長(zhǎng)什么樣子呢?這就需要用 windbg 下斷點(diǎn)調(diào)試,從匯編代碼看,最后的結(jié)果會(huì)存放在 eax 上, 如下圖所示:

最后將棧上的10復(fù)制到堆上區(qū)域。

可以看到,這里涉及到了如下幾個(gè)性能開銷。

  • 內(nèi)存分配

  • 風(fēng)險(xiǎn)在于分配引發(fā)的gc回收概率,比如判代回收 (臨時(shí)代,FullGC)。

  • 多次內(nèi)存復(fù)制 (stack -> heap -> register)

  • 一個(gè)裝箱就有 6 個(gè)mov,反復(fù)的在 棧,堆,寄存器 之間交換。

  • 增加 gc 回收壓力

  • gc本來工作壓力就很大,這又有無(wú)謂的分配,難哈。

    最后就是如何解決,大概有如下兩點(diǎn)。盡可能避免裝箱 或者合理的使用 泛型。

    總結(jié)

    以上是生活随笔為你收集整理的都说不要装箱,那装箱到底带来了什么开销?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。