SIMD
Mono团队一向以他们对SIMD,即单指令流多数据流特征的支撑引以为傲。SIMD是一种CPU指令集,它能够在统一时刻对最多8个值举行统一操纵。而跟着.NET CLR版本4.6的推出,Windows开发者终究也能够运用这一特征了。
为了现实视察一下SIMD的结果,能够参考一下这个示例。假定你须要经由历程c[i] = a[i] + b[i]这类情势对两个数组举行相加,以获得第三个数组。经由历程运用SIMD,你能够依据以下体式格局编写代码:
for (int i = 0; i < size; i += Vector.Count) { Vectorv = new Vector(A,i) + new Vector(B,i); v.CopyTo(C,i); }
请注意这个轮回是怎样按Vector<int>.Count的取值举行递增的,依据CPU范例的差别,它的取值多是4或是8。.NET JIT编译器将依据CPU的差别生成响应的代码,以4或8的值对数组举行批量相加。
这类体式格局看起来有些烦琐,因而微软还供应了一系列辅佐类,包含:
Matrix3x2 构造
Matrix4x4构造
Plane构造
Quaternion构造
Vector 类
Vector(T) 构造
Vector2构造
Vector3构造
Vector4构造
顺序集卸载
生怕大多数开发者都不晓得这一点:.NET常常会对统一个顺序集加载两次。发作这类状况的前提是.NET起首加载了某个顺序集的IL版本,随后又加载了统一顺序集的NGEN版本(即预编译版本)。这类体式格局关于物理内存来讲是相当严重的糟蹋,尤其是对诸如Visual Studio如许的大型32位运用顺序来讲更加显著。
而在.NET 4.6中,一旦CLR加载了某个顺序集的NGEN版本,它会自动清空对应的IL版本所占用的内存。
垃圾接纳
新近我们曾讨论过.NET 4.0中所引入的垃圾接纳滞后时刻形式,虽然这类体式格局比起让GC完全住手一段时刻的做法要牢靠很多,但关于很多GC场景来讲,这类体式格局仍算不上完全。
在.NET 4.6中,你将能够经由历程一种更邃密精美的体式格局暂时中断垃圾接纳器的运作,新的TryStartNoGCRegion要领许可你指定在小对象以及大对象的堆中须要若干内存。
假如涌现内存不足的状况,运转时将会返回false,或是住手运转,直到经由历程GC清算获得充足的内存为止。你能够经由历程为TryStartNoGCRegion传入某个标记的体式格局掌握这一行动,假如你成功地进入了某个无GC地区(在历程完毕前不许可举行GC),那末在历程完毕时必需挪用EndNoGCRegion要领。
在官方文档中并没有申明该要领是不是是线程平安的,不过考虑到GC的事情道理,你应该只管防止让两个历程同时尝试转变GC状况的做法。
关于GC的另一项革新是它处置惩罚pinned对象(即一旦分派后不可挪动位置的对象)的体式格局。虽然在文档中对此方面的形貌有些语焉不详,但当你牢固了某个对象的位置时,一般也会牢固其相邻对象的位置。Rich Lander在文中写道:
GC将以一种更优化的体式格局处置惩罚pinned对象,因而GC能够将pinned对象四周的内存举行更有用地紧缩。关于大批运用pin体式格局的大规模运用来讲,这一修改将极大地革新运用的机能。
GC关于怎样运用较早的几代中的内存方面也体现出更好的智能性,Rich继承写道:
第1代对象升级为第2代对象的体式格局也获得了革新,以更有用地运用内存。在为某一代分派新的内存空间之前,GC会先尝试运用可用的空间。同时,在应用可用空间地区建立对象时运用了新的算法,使新分派的空间大小比起夙昔更接近于对象的大小。
异步当地存储
末了一项革新与机能并没有直接的关联,但经由历程有用的应用依然能到达优化的结果。在异步API还没有流行起来的年代,开发者能够应用线程当地存储(TLS)缓存信息。TLS关于某个特定的线程来讲就像是一种全局对象,这意味着你能够直接接见上下文信息并举行缓存,而无需显式地通报某种上下文对象。
而在async/await形式中,线程当地存储就变得毫无用武之地了。由于每次挪用await的时刻,都有能够跳转至另一个线程。而且即使幸运避开了这类状况,但别的代码也有能够跳转到你的线程中并滋扰TLS中的信息。
新版本的.NET引入了异步当地存储(ALS)机制以处理这一题目,ALS在语义上等价于线程当地存储,但它能够跟着await的挪用举行响应的跳转。这一功能将经由历程AsyncLocal泛型类完成,其内部将挪用CallContext对象用于保留数据。
以上就是细致引见.NET中的机能革新的细致内容,更多请关注ki4网别的相干文章!