原文:使用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. C# 文件读取(二)

    将我的电脑中的文件夹信息显示到TreeView控件上. 方法很多种,下面这种方法添加了我的文档. public partial class Form1 : Form { public Form1() ...

  2. 【py】安装ipython-notebook

    os:ubunutu(debian)-based linux 分两步: 安装ipython及其依赖包 sudo apt-get install ipython-notebook   安装可选的附加工具 ...

  3. 创建与删除SQL约束或字段约束

    1)禁止所有表约束的SQLselect 'alter table '+name+' nocheck constraint all' from sysobjects where type='U'2)删除 ...

  4. NLog

    C# 使用NLog记录日志 C#第三方日志库Nlog NLog类库使用探索——详解配置 使用Nlog记录日志到数据库 NLog文章系列——系列文章目录以及简要介绍 NLog日志框架简写用法(write ...

  5. 深拷贝 vs 浅拷贝 释放多次

    如果类中有需要new的数据,那么一定要注意delete; 如果只free一次,但是提示free多次,一定要注意了,有可能是因为你没有定义拷贝函数! 以我的亲身经历来说: operater *(mycl ...

  6. 【jQuery UI 1.8 The User Interface Library for jQuery】.学习笔记.6.Dialog控件

    习惯上,我们播放一条简短的信息,或向浏览者询问一个问题,都会用到dialog. 创建一个基本的dialog 使用dialog 选项 形式 启用内置动画 给dialog添加按钮 使用dialog回调函数 ...

  7. 使用Jil序列化JSON提升Asp.net web api 性能

    JSON序列化无疑是Asp.net web api 里面性能提升最重要的一环. 在Asp.net web api 里面我们可以插入自定义的MediaTypeFormatter(媒体格式化器), 说白了 ...

  8. android使用其他应用打开文件

    根据文件的MIME类型来判断,手机中有哪些应用可以打开这个文件,然后把应用在弹窗列表中显示 /** * 打开文件 * * @param file */ public static void openF ...

  9. (jdbc)取得数据库自动生成的主键方法

    一些类,在前面的博客中有,就不重复了 public class Test2 { TestDAO t=new TestDAO(); /*前提是数据表的主键是自动增加的, *取得数据库自动生成的主键 * ...

  10. 山东理工大学第七届ACM校赛-飞花的鱼塘 分类: 比赛 2015-06-26 10:30 43人阅读 评论(0) 收藏

    飞花的鱼塘 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 一日,飞花壕在稷下湖游玩,忽然,飞花巨有了一个养鱼的想法,于是,他大手 ...