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

相信很有朋友在面试时大多会被问到 装箱 的问题,也是一个经典的问题,可深可浅,那今天我们就从 汇编内存 角度进行统一解读下。

为了方便演示,先上一段装箱的代码。

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)  //生成一个初始化类型放在 eax 中。(objheader+methodtable+占位符)
022e0883 8945f0          mov     dword ptr [ebp-10h],eax                    //备份地址到 栈中
022e0886 8b45f0          mov     eax,dword ptr [ebp-10h]                    //恢复 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

因为每句汇编代码都有注释,我就不解释了,这里主要看一下 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 是用于分配 小对象,无终结器,非数组 的专用方法,也属于高效的 快速分配路径,那分配完之后的初始化长什么样子呢?这就需要用 windbg 下断点调试,从汇编代码看,最后的结果会存放在 eax 上, 如下图所示:

3f80ac7fae3441bef75dbd5355f2267e.png

最后将栈上的10复制到堆上区域。

可以看到,这里涉及到了如下几个性能开销。

  1. 内存分配

风险在于分配引发的gc回收概率,比如判代回收 (临时代,FullGC)。

  1. 多次内存复制 (stack -> heap -> register)

一个装箱就有 6 个mov,反复的在 ,,寄存器 之间交换。

  1. 增加 gc 回收压力

gc本来工作压力就很大,这又有无谓的分配,难哈。

最后就是如何解决,大概有如下两点。尽可能避免装箱 或者合理的使用 泛型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中方法的继承以及父类未被子类覆盖的方法调用的问题

在看java继承这一块的时候发现了一个问题&#xff0c;即父类未被子类覆盖的方法是如何调用的&#xff1f; 是子类拥有了父类的该方法只是没有显示表示&#xff0c;还是子类调用了父类的该方法。 为此做了一下验证 代码如下&#xff1a; public class One {protected void print…

数据结构实验之栈四:括号匹配

数据结构实验之栈四&#xff1a;括号匹配 Description 给你一串字符&#xff0c;不超过50个字符&#xff0c;可能包括括号、数字、字母、标点符号、空格&#xff0c;你的任务是检查这一串字符中的( ) ,[ ],{ }是否匹配。Input 输入数据有多组&#xff0c;处理到文件结束。Outpu…

10.29 工作笔记 ndk编译C++,提示找不到头文件(ndk-build error: string: No such file or directory)...

ndk编译C。提示找不到头文件&#xff08;ndk-build error: string: No such file or directory&#xff09; 被这个问题弄得愁眉苦脸啊。心想为啥一个string都找不到呢。。于是百度到了。。。遇到这个问题&#xff0c;就在所在的文件夹 Application.mk 文件里。加入&…

Excel VBA编程基础

一、程序基本调试方法 1、VB程序的三种状态:设计时、运行时和中断模式。 2、但不执行代码,快捷键为F8。 3、中断程序的方法: (1)使用断点 (2)使用Debug.Assert (3)使用监视条件 二、Excel Shape对象

分治算法之合并排序

1、问题 合并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列 2、思路 1、分解:将待排序元素分成大小大致相同的两个子序列 2、治理:对两个子序列进行合并排序 3、…

WPF 实现截屏控件之移动(二)(仿微信)

WPF开发者QQ群此群已满340500857 &#xff0c;请加新群458041663由于微信群人数太多入群请添加小编微信号yanjinhuawechat 或 W_Feng_aiQ 邀请入群需备注WPF开发者 接着上一篇&#xff0c;兼容屏幕缩放问题。01—代码如下一、创建ScreenCut.xaml代码如下。<ResourceDictiona…

构造不可变类及其优点

不可变类的优点 易于构造&#xff0c;测试和使用天然线程安全&#xff0c;没有同步问题不需要实现clone方法引用不可变类的实例时&#xff0c;不需要考虑实例的值发生变化的情况如何构造不可变类 不声明“setter”方法。所有属性设为private final。class声明为final&#xff0…

深入剖析阿里云推荐引擎——新架构,新体验

摘要&#xff1a;本文的整理自2017云栖大会-上海峰会上阿里云算法专家郑重&#xff08;卢梭&#xff09;的分享讲义&#xff0c;从2016年2月V2.0公开使用到现在&#xff0c;阿里云推荐引擎有了更大的进步。有着获取排序的在线计算&#xff0c;修正匹配的近线计算及匹配排序的离…

分治算法之快速排序

1、快速排序 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序 2、思路 ( 1 )分解:先从数列中取出一个元素作为基准元素。以基准元素为标准,将问题分解为两个子序列,使小于…

java程序结构_java程序结构

java是一门面向对象的语言&#xff0c;在编程过程中当然离不开对象的声明&#xff0c;而对象又是通过类定义的&#xff0c;所以java中最重要的就是各式各样的类&#xff0c;在java中&#xff0c;类也是一个程序的基本单位0x01&#xff1a;默认生成类在eclipse中创建好一个java类…

C#金额小写转大写

public string ConvertMoney(decimal Money){//金额转换程序string MoneyNum = "";//记录小写金额字符串[输入参数]string MoneyStr = "";//记录大写金额字符串[输出参数]string BNumStr = "零壹贰叁肆伍陆柒捌玖";//模string UnitStr = "万…

SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型

SQL Server 2008空间数据应用系列三&#xff1a;SQL Server 2008空间数据类型 原文:SQL Server 2008空间数据应用系列三&#xff1a;SQL Server 2008空间数据类型友情提示&#xff0c;您阅读本篇博文的先决条件如下&#xff1a; 1、本文示例基于Microsoft SQL Server 2008 R2调…

shell脚本中怎样同时执行多个.sql文件,并把结果写入文件中(转)

转载&#xff1a;http://joewalker.iteye.com/blog/408879命令行下具体用法如下&#xff1a; mysqldump -u用戶名 -p密码 -d 数据库名 表名 > 脚本名;导出整个数据库结构和数据mysqldump -h localhost -uroot -p123456 database > dump.sql导出单个数据表结构和数据mysql…

.NET 很好,你可能对它有一些误解

> 作者&#xff1a;Charles Chen在 20 年前的 2002 年, 微软公布了下一代的软件、服务的愿景和路线&#xff0c;2 月 13 日&#xff0c;Visual Studio .NET 推出&#xff0c;.NET 开发平台的第一个版本正式向世界发布。到现在为止&#xff0c;.NET 都已经 20 岁了, 它已经成…

ajax返回数据类型为JSON数据的处理

ajax返回数据类型为JSON数据的处理 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"> <head> <…

SQL语言实现金额小写转大写完整案例代码

1. 数字大小写对照表 一到十数字大小写: 1——壹,2——贰,3——叁,4——肆,5——伍,6——陆,7——柒,8——捌,9——玖,10——拾 2. 大小写转换案例 将12.345元转换为大写 select dbo.L2U(12.345,1) select dbo.L2U(123456789.345,1) 结果: 3. SQL转化代码 CREA…

Android studio之编译出现 Error:null value in entry: outputDirectory=null

1、问题 昨天编译好好的&#xff0c;今天编译无缘无故报下面这个错 Error:null value in entry: outputDirectorynull 2、解决办法 cd 到项目的根目录去&#xff0c;然后删除.gradle/文件夹就可以了 rm -rf .gradle/

c# 操作excle

添加引用 Microsoft.Office.Interop.Excel; 添加命名空间 using Excel Microsoft.Office.Interop.Excel; //创建接口变量------------------------------------------ _Workbook _xlWorkBook null; Worksheet _xlWorkSheet null; Excel.Application _xlApp null;//创建exc…

mysql 权重 取值_mysql如何按权重查询数据啊?

楼上的回答全都会错意了&#xff0c;题主意思是根据权重设定随机几率&#xff0c;例如 A 的权重为10&#xff0c;B 的权重为 5&#xff0c;这个时候随机出现 A 的几率要比出现 B 的几率高。你可以试试这个备选方案。就是先取出权重列表再去根据权重随机出来的那个权重值&#x…

使用 JsonSchema 验证 API 的返回格式

使用 JsonSchema 验证 API 的返回格式Intro最近我们的 API 提供给了别的团队的小伙伴用&#xff0c;按照他们的需求做了接口的改动&#xff0c;API 返回的数据结构有一些变化&#xff0c;我们提供的接口有缓存&#xff0c;数据库更新之后不会马上刷新&#xff0c;于是就想验证一…