写点什么

使用 C#进行系统编程

2016 年 7 月 17 日

虽然对于系统编程(System programming)的定义很模糊,不过可以将其描述为在比特、字节、指令,或 CPU 周期层面所进行的思考。系统编程这个概念也暗含了对性能和可靠性的需求。Microsoft 技术总监 Joe Duffy 在 QCon New York 活动中介绍了使用 C#进行系统编程的战略,同时他还谈到了这其中的一些陷阱以及缓解方法。

Joe 的演讲中很多内容来自一个名为 Midori 的研究项目。该项目意在使用 C#从零开始打造一个操作系统,这也让我们对编译器的结构和有关高性能代码的新战略有了全新认识。

使用托管语言(Managed language)构建操作系统使得我们能够在内存层面上运用 C#中的安全功能。这样做可以避免由于缓冲区溢出或格式字符串(Format string)弱点而针对内存进行的代码注入攻击,因为此时可以由运行时负责边界检查(Bound checking)和类型安全(Type safety)。

代码的生成

代码可以通过预先(Ahead of time,Aot)或即时(Just in time,Jit)的方式编译。Jit 的优势在于编译速度更快,但 Aot 可以获得更好的机器代码,因为编译器可以对代码执行更多优化。

原生语言编译器实现的很多优化原本是托管语言所不具备的。一般原因通常在于,通过 Jit 编译器实现这些优化通常可能需要极大的运算量或过于复杂。正是这些问题导致 C#在紧密、高效的底层代码生成方面口碑不佳。最近通过 RyuJit 实现了下列这些优化:

  • Inlining(使用所调用函数的主体取代函数调用点)
  • Flowgraph 和 Loop 分析
  • 静态单一指派(SSA)和全局值编号
  • 通用子表达式消元(Common subexpression elimination)
  • 复制 / 常量传播(Copy/constant propagation)
  • 无用代码删除
  • 范围分析
  • 非虚拟化(Devirtualization)
  • 循环不变量代码提升(Loop invariant code hoisting)
  • SIMD 和向量化
  • 通用共享(Generic sharing)
  • 堆栈分配(正在开发中)

垃圾回收

.NET 中的垃圾回收已发展到第三代。一些数据程序分析师需要将自己过半的时间用于垃圾回收,而无法用在更有价值的工作中。

改善性能的方法之一是使用 Struct,Struct 可改善下列领域的性能问题:

  • 降低 GC 压力,因为 Struct 是针对堆栈分配的。
  • 提高内存局部性(Memory locality),改善缓存命中率。
  • 整体减少对内存的使用,避免 32-64 位应用程序中对象的 8-16 字节开销。

关于 Struct 有个问题需要注意:在复制超出某一大小的 Struct 时可能导致 Memcpy。为了优化性能,应确保 Struct 尽可能小,不要超过 32/64 字节。

C# 7 的一些功能使得通过 Struct 进行底层优化的过程变得更容易。C# 7 的元数组(Tuple)是 Struct,而非老版本中的 System.Tuple<>,后者现已成为对象。引用返回则是 Struct 的另一个特性,可以无需复制直接通过函数返回 Struct。

错误处理

可恢复的错误总会存在例外,然而很多错误都是不可恢复的。诸如无效转换、栈溢出以及空引用等错误实际上属于 Bug。但 I/O 故障和验证错误是可以预见并从中恢复的。

这种错误恢复催生了 Fail fast 策略。 Fail fast 是一种包含在.NET 中的机制,这种机制下诸如 StackOverflow 等例外可能会绕过异常处理程序导致进程崩溃。该策略使得查找此类错误的过程变得更简单,因为此时例外已经无法被过度的通用异常处理程序所处理。Midori 团队发现他们的可恢复错误(例外)与 Bug(Fail fast)已经达到了 1:10 的比例。

详细信息请参阅 Joe 的博客,他在博客上写了很多有关Midori 的文章。他的演讲演示文稿也已经发布到网上。

查看英文原文 Systems Programming in C#

2016 年 7 月 17 日 19:002373
用户头像

发布了 283 篇内容, 共 86.1 次阅读, 收获喜欢 36 次。

关注

评论

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

Docker基础修炼6--网络初探及单机容器间通信

黑马腾云

Docker Linux 运维 虚拟化 容器化

性能测试与优化学习总结

qihuajun

架构师训练营Week7作业

Frank Zeng

搭建Hadoop开发环境并编写运行测试类

大数据学徒

Java hadoop IDEA

简约而不简单的分布式通信基石

架构师修行之路

分布式 socket udp TCP/IP 通信协议

动手实现一下 JavaScript 中的 call, apply 和 bind

墨子苏

Java 前端

修改 Docker 数据根目录的 3 种方式

FeiLong

Docker

Docker网络学习第三篇-路由

Lazy

Docker Linux 网络

性能优化作业

qihuajun

优秀的求职者,是如何巧妙应对面试提问呢?

xcbeyond

面试 加班 职业规划 薪资 自我介绍

深入理解 CSS 中的外边距折叠及 BFC

墨子苏

CSS 前端

性能测试学习总结

周冬辉

性能测试

谁说天平不稳——安全性与用户体验设计思考

石君

安全产品设计 安全设计 用户体验

Docker基础修炼4--Docker仓库及相关命令

黑马腾云

Docker Linux 运维 容器技术 虚拟化

第七周作业

赵龙

week07总结 性能测试&操作系统

Z冰红茶

架构师训练营 - 第七周 - 作业

韩挺

js基础作业总结

Geek_896619

Docker基础修炼5--容器数据共享和持久化实战

黑马腾云

Docker Linux 运维 虚拟化 容器化

第七周学习总结

赵龙

JavaScript 中 new 一个对象的过程中发生了什么

墨子苏

Java 前端

性能优化(一)

olderwei

LeetCode题解:283. 移动零,JavaScript,一次遍历,详细注释

Lee Chen

LeetCode 前端进阶训练营

阿朱的决定

一直AC一直爽

随笔杂谈 观后感

架构师训练营 - 第七周 - 学习总结

stardust20

关注系统压力测试

麻辣

总结

chenzt

架构师训练营Week7学习总结

Frank Zeng

MySQL - 主从复制的几种方式

Aaron_涛

MySQL 架构 分布式 主从复制 数据一致性

【第七周作业】

Aldaron

【第十三课】性能测试与优化

Aldaron

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

使用C#进行系统编程-InfoQ