原文:使用C#进行系统编程

虽然对于系统编程(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#

【转载】使用C#进行系统编程的更多相关文章

  1. Linux高并发网络编程开发——10-Linux系统编程-第10天(网络编程基础-socket)

    在学习Linux高并发网络编程开发总结了笔记,并分享出来.有问题请及时联系博主:Alliswell_WP,转载请注明出处. 10-Linux系统编程-第10天(网络编程基础-socket) 在学习Li ...

  2. Linux系统编程【3.1】——编写ls命令

    ls命令简介 老规矩,直接在终端输入:man ls (有关于man命令的简介可以参考笔者前期博客:Linux系统编程[1]--编写more命令) 可以看到,ls命令的作用是显示目录中的文件名,它带有可 ...

  3. Linux系统编程【1】——编写more命令

    背景介绍 笔者知识背景 笔者接触Linux快一年了.理论知识方面:学习了操作系统基础知识,了解进程调度.内存分配.文件管理.磁盘I/O这些基本的概念. 实操方面:会使用Linux简单命令,在嵌入式系统 ...

  4. Linux系统编程【2】——编写who命令

    学到的知识点 通过实现who命令,学到了: 1.使用man命令寻找相关信息 2.基于文件编程 3.体会到c库函数与系统调用的不同 4.加深对缓冲技术的理解 who命令的作用 who命令的使用 在控制终 ...

  5. Linux系统编程【3.2】——ls命令优化版和ls -l实现

    前情提要 在笔者的上一篇博客Linux系统编程[3.1]--编写ls命令中,实现了初级版的ls命令,但是与原版ls命令相比,还存在着显示格式和无颜色标记的不同.经过笔者近两天的学习,基本解决了这两个问 ...

  6. linux下系统编程C环境搭建

    一.系统安装 我使用的是VMware8下的ubuntu12.04,这是培训老师说的,12.04相对来说,比较新,而且是5年长期支持版,不容易过时.对于系统的安装,我不想说很多,只是希望大家主义这几点: ...

  7. Linux系统编程温故知新系列 --- 01

    1.大端法与小端法 大端法:按照从最高有效字节到最低有效字节的顺序存储,称为大端法 小端法:按照从最低有效字节到最高有效字节的顺序存储,称为小端法 网际协议使用大端字节序来传送TCP分节中的多字节整数 ...

  8. linux系统编程之错误处理

    在linux系统编程中,当系统调用出现错误时,有一个整型变量会被设置,这个整型变量就是errno,这个变量的定义在/usr/include/errno.h文件中 #ifndef _ERRNO_H /* ...

  9. LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

    19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程 ...

随机推荐

  1. 四则运算GUI版本

    要求:用户界面新增支持 Windows GUI,同时保留原有命令行下所有功能.提示: 先测试驱动开发,然后重构代码,以GUI为目标修改"核心"函数,把与GUI/Console相关的 ...

  2. SQL SERVER2012秘钥

    来自网络: MICROSOFT SQL SERVER 2012 DEVELOPER 版(开发版)序列号:YQWTX-G8T4R-QW4XX-BVH62-GP68YMICROSOFT SQL SERVE ...

  3. ImagXpress中如何修改Alpha通道方法汇总

    ImagXpress支持处理Alpha通道信息来管理图像的透明度,Alpha通道支持PNG ,TARGA和TIFF文件,同时还支持BMP和ICO文件.如果说保存的图像样式不支持Alpha通道,就将会丢 ...

  4. Linux系统调用---同步IO: sync、fsync与fdatasync【转】

    转自:http://blog.csdn.net/cywosp/article/details/8767327 [-] 1  write不够需要fsync 2 fsync的性能问题与fdatasync ...

  5. include指令

    include:文件加载指令(用于在JSP文件中插入一个包含文本或代码的文件.把文件插入后和原来的JSP文件合并成一个新的JSP页面.) 语法格式:<%@ include file=" ...

  6. php curl向远程服务器上传文件

    <?php /** * test.php: */ header('content-type:text/html;charset=utf8'); $ch = curl_init(); //加@符号 ...

  7. node-webkit 新建实例窗口间通信问题解决办法

    终于弄明白这问题了,只要在js文件里加上段代码,就可解决两窗口间通信问题. var str = { username: User.name, userrole: User.role }; var ne ...

  8. C++ Template Operator

    #include <iostream> #include <string> #include <deque> #include <stdexcept> ...

  9. Java实现批量修改文件名称

    import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; /** ...

  10. JavaScript DOM 编程艺术(第2版)读书笔记 (7)

    动态创建标记 一些传统方法 document.write document.write()方法可以方便快捷的把字符串插入到文档里. 请把以下标记代码保存为一个文件,文件名就用test.html 好了. ...