写点什么

.NET 4.6 中的性能改进

  • 2015-07-23
  • 本文字数:1782 字

    阅读完需:约 6 分钟

.NET 4.6 中带来了一些与性能改进相关的 CLR 特性,这些特性中有一部分将会自动生效,而另外一些特性,例如 SIMD 与异步本地存储(Async Local Storage)则需要对编写应用的方式进行某些改动。

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<int>.Count)
{
Vector<int> v = new Vector<int>(A,i) + new Vector<int>(B,i);
v.CopyTo(C,i);
}</int></int></int></int>

请注意这个循环是如何按 Vector.Count 的取值进行递增的,根据 CPU 类型的不同,它的取值可能是 4 或是 8。.NET JIT 编译器将根据 CPU 的不同生成相应的代码,以 4 或 8 的值对数组进行批量相加。

这种方式看起来有些繁琐,因此微软还提供了一系列辅助类,包括:

程序集卸载

恐怕大多数开发者都不知道这一点:.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 对象用于保存数据。

查看英文原文 Performance Improves in .NET 4.6

2015-07-23 10:173634
用户头像

发布了 428 篇内容, 共 179.8 次阅读, 收获喜欢 39 次。

关注

评论

发布
暂无评论
发现更多内容

Java测试框架九大法宝

FunTester

自动化测试 JUnit 测试框架 selenium testNG

高频面试题-请把Java垃圾回收器说清楚

Java 编程 架构 面试 JVM

Spring Boot 实战派,让开发像喝水一样简单!

Java 程序员 架构 面试 IT

终于有人把“SpringCloudAlibaba学习笔记”整理出来了

Java 程序员 架构 微服务 计算机

清爽视频编辑器 Tech Support

凌天一击

Java 程序性能优化“学习日记”

Java 编程 面试 IT 计算机

使用Micronaut框架构建一个微服务网络.

Java 编程 架构 面试 程序人生

987页的Java面试宝典,看完才发现,应届生求职也没那么难

Java~~~

Java 面试 微服务 多线程 架构师

为什么安全性在托管中变得越来越重要

九河云安全

低代码开发平台的出现会是开发者的威胁吗

雯雯写代码

开发者 低代码 低代码开发平台

又一里程碑!阿里首推Java技术成长笔记,业内评级“钻石级”

Java~~~

Java redis spring 面试 架构师

全面到哭!BAT内部Java求职面试宝典,应届生必须人手一份

Java~~~

Java 面试 微服务 多线程 架构师

xposed 入门之修改手机 IMEI

Qunar技术沙龙

android 程序员 App 经验分享 安卓

面试进阶齐飞!霸榜GitHub的 Java 全栈笔记太香了!

Java 编程 程序员 IT 计算机

2021 斩获 90K 月薪的 Spring 全家桶:文档 + 面试题 + 学习笔记 + 思维导图

编程 架构 微服务 IT 计算机

毕业六年本科,去年疫情期间备战二个月,阿里巴巴四面成功!定级 P7

Java 程序员 架构 面试 IT

一文搞懂指标采集利器 Telegraf

尔达Erda

学习 微服务 开发者 云原生 插件开发

凭借一份“面试真经pdf”,我四面字节跳动,拿下1-2级offer

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

经验分享:我是如何拿下微软、滴滴、百度等 20家大厂的 Offer?

Java 程序员 架构 面试 IT

28天读完349页,这份阿里面试通关手册,助我闯进字节跳动

Java~~~

Java 面试 算法 多线程 架构师

社招三面阿里“落榜”,幸获内推名额,4面揽下美团offer

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

2021 年主要网络安全威胁,及时发现提早规避风险

九河云安全

读完SpringBoot,Cloud,Nginx与Docker技术,我拿到了阿里offer

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

惠及百万用户 医保“上云”有了新思路

云计算

渣本全力以赴33天,四面阿里妈妈(淘宝联盟),拿下实习岗offer

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

Tensor:Pytorch神经网络界的Numpy

华为云开发者联盟

神经网络 数组 PyTorch Numpy Tenso

spring cloud 在国内中小型公司能用起微服务来吗?

Java 程序员 架构 面试 IT

算法有救了!GitHub 上神仙项目手把手带你刷算法,Star 数已破500k

Java 编程 程序员 面试 算法

“助力金九银十”25 大Java后端面试指南,3000道面试题解析

Java 编程 程序员 面试 IT

经过两年努力,我终于进入腾讯(PCG事业群4面总结)

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

百分点科技参加MIT数智未来创新峰会 入选产业数字化生态图谱

百分点科技技术团队

.NET 4.6中的性能改进_.NET_Jonathan Allen_InfoQ精选文章