为什么拳击和拆箱操作之间的速度变化如此之大?有10倍的差异.我们什么时候应该关心这个?上周Azure支持告诉我们,我们的应用程序的堆内存中存在问题.我很想知道它是否与装箱拆箱问题有关.
using System; using System.Diagnostics; namespace ConsoleBoxing { class Program { static void Main(string[] args) { Console.WriteLine("Program started"); var elapsed = Boxing(); Unboxing(elapsed); Console.WriteLine("Program ended"); Console.Read(); } private static void Unboxing(double boxingtime) { Stopwatch s = new Stopwatch(); s.Start(); for (int i = 0; i < 1000000; i++) { int a = 33;//DATA GOES TO STACK object b = a;//HEAP IS REFERENCED int c = (int)b;//unboxing only hEre ....HEAP GOES TO STACK } s.Stop(); var UnBoxing = s.Elapsed.TotalMilliseconds- boxingtime; Console.WriteLine("UnBoxing time : " + UnBoxing); } private static double Boxing() { Stopwatch s = new Stopwatch(); s.Start(); for (int i = 0; i < 1000000; i++) { int a = 33; object b = a; } s.Stop(); var elapsed = s.Elapsed.TotalMilliseconds; Console.WriteLine("Boxing time : " + elapsed); return elapsed; } } }
usr.. 5
将拆箱视为从盒装对象到寄存器的单个内存加载指令.可能有一些周围的地址计算和转换验证逻辑.盒装对象就像一个带有一个盒装类型字段的类.这些操作有多贵?不是很特别,因为基准测试中的L1缓存命中率约为100%.
拳击涉及分配一个新的对象和GC以后.在您的代码中,GC可能会在99%的情况下触发分配.
这表示你的基准测试无效,因为循环没有副作用.目前的JIT可能无法优化它们.以某种方式让循环计算结果并将其汇入其中GC.KeepAlive
以使结果显示为使用.此外,您可能正在运行调试模式.
将拆箱视为从盒装对象到寄存器的单个内存加载指令.可能有一些周围的地址计算和转换验证逻辑.盒装对象就像一个带有一个盒装类型字段的类.这些操作有多贵?不是很特别,因为基准测试中的L1缓存命中率约为100%.
拳击涉及分配一个新的对象和GC以后.在您的代码中,GC可能会在99%的情况下触发分配.
这表示你的基准测试无效,因为循环没有副作用.目前的JIT可能无法优化它们.以某种方式让循环计算结果并将其汇入其中GC.KeepAlive
以使结果显示为使用.此外,您可能正在运行调试模式.