你觉得 .NET 性能低,可能只是因为你的能力低
by Conmajia
本文由以下大佬赞助 加入赞助者行列
{{ sponsor.name }}
感恩,你们的赞助让我在抓耳挠腮写文章时不至于断了香烟。
var s = [{
name: '◎梦想起航◎',
amount: 6.66,
date: '2019-02-19'
}, {
name: 'tzhang',
amount: 0.01,
date: '2019-02-19'
}, {
name: 'Tim',
amount: 6.00,
date: '2019-02-19'
}, {
name: '李敏',
amount: 3.00,
date: '2019-02-20'
}, {
name: '倾听',
amount: 5.00,
date: '2019-02-20'
}, {
name: 'metoer',
amount: 0.1,
date: '2019-02-20'
}, ];
var cache = {};
for (var i = 0; i
破除现代迷信,人人有责。.NET的源码点这里 Fork。
奇了个怪
.NET作为开发平台来说,不可否认是优雅的、高效的。可是有些人就是看不到它极高的开发效率,极短的市场推出时间,极强的扩展能力,非得在性能上较劲,把一帮小萌新忽悠得一说起 .NET就觉着是“慢”、“卡”的代名词。
这些人总是存在一个思维误区,认为程序性能是和语言挂钩的。您没事儿吧?真要这样,《数据结构》、《算法》这些课早他妈该撤了好吧。汽车和飞机速度确实不一样,但就算给您一架私人飞机,您能给表演表演每天开飞机去买菜?任何语言的性能瓶颈,大半还是出在使用这语言的人蠢身上。新手司机开着十辆布加迪也不可能拼过驰骋秋名山的五菱宏光老司机。咱们不抬杠,今天就只说性能,不说开发效率、上市速度。非要跟我抬杠,算上这些,可能我的“低性能”产品已经出街了,你憋半天憋不出屁的“高性能”产品还在扑街,优越个 8呢。
.NET的开发语言一般用C#,后边我就不区分 .NET和C# 了。F# 其实也差不多,反正最后都编译成intermediate language,可以认为是等价的(函数式编程更多的是一种思想,这个话题我以后会写)。实话实说,C# 这门编程语言,一开始就处于一个挺尴尬的位置。性能上,有C/C++ 在前边拦着;应用上,有Java、Python在后边堵截,不上不下。.NET玩家心里总憋着股邪火,只好左右互搏,自娱自乐了。
语言的比较
这个问题的根源,很大一部分在于很多程序员只会一种语言,甚至连这唯一的语言也不够精通,所以才会要么看不起别的语言,要么埋怨自己这语言性能太弱。想要一招鲜吃遍天,梦里可以,醒来最好还是把这茬给忘了。而那些对 .NET一知半解就开始嘲讽的“别的语言”玩家,就更别指望他们能理解到其中的精髓了。
把自己限制于一种语言的程序员会经常错过其他地方提供的重要机会。这样的程序员绝对不会被他们的老板或客户看成是专业领域中的专家。
C# 虽然定位尴尬,但是它本身是高度优化的,要比性能,无非就C/C++ 或者汇编才配跟它比。Java、Python这些,大家都是IL解释的,本是同根生,相煎急锤子,都不一定能比过C#。C系玩家就算了,特性使然确实比不过,但是事实上优化之后性能也大差不差(我马上就能证明这一点)。最奇怪的就是好多J、P玩家居然好意思笑话C# 性能辣鸡,完全没意识到自己那惨样儿。就好像宋小宝去够姚明手里的球,结果潘长江在边儿上笑得挺欢,笑您 呢?和机器码比起来,任何使用中间语言虚拟机/runtime的语言都有损失,这话没人能反驳吧?Benchmark,一般都是用最耗资源的操作——比如图像处理——来比较。这无非就是测试磁盘、内存的IO性能呗。操作系统最终的性能在那卡着,assembly可以达到95%,C系8、90%,C# 可能亏点儿,6、70%的样子。然而,这都不是重点,重点在于,你有没有完全利用到语言的全部特性,以及那些你认为低效率的算法,非要用它们真的大丈夫?40米大刀拿来削苹果,可能它的性能真的很低吧。
我过去的试验
2012年的时候我就测试过用C# GDI+读写bitmap,一开始用的常规算法,很慢。但是经过优化后,性能提升了363倍,我也没用别的任何类库,还是 .NET 2.0原生。您说怎么判断C# 的性能到底是低还是高?

当时一帮哥们儿看了我的试验都手痒秀了一遍优化:
鼠标移到作者名字上可以查看作者信息,他们都是真·大神
.tftable {font-size:12px;color:#333333;width:100%;border-width: 1px;border-color: #ebab3a;border-collapse: collapse;}
.tftable th {font-size:12px;background-color:#e6983b;border-width: 1px;padding: 8px;border-style: solid;border-color: #ebab3a;text-align:center;}
.tftable tr {background-color:#ffffff;}
.tftable td {font-size:12px;border-width: 1px;padding: 8px;border-style: solid;border-color: #ebab3a;}
.tftable tr:hover {background-color:#ffff99;}
编号 | 作者 | 耗时(毫秒) | 实现方法 | 平台 |
---|---|---|---|---|
a. | laviewpbt | 25 | 汇编 + PowerBasic | i3 380M/3GB/Win7 32-bit |
b. | 兰征鹏 | 12~19 | VC++.NET调用SSE指令 | i7 860/12GB/Win7 64-bit |
c. | 胡飞 | 33 | 重写C# 图像库、unsafe 指针 |
优于 a |
d. | Conmajia | 46 | 原生GDI+、unsafe 指针 |
同a |
上面这张表,可以看到,几种语言的性能是接近的,相差最大20毫秒(C# vs 汇编)。除了b项C++ 加了buff(当时i7是顶级CPU),换到同平台,基本差不多的。当技巧和算法都优化到极致之后,其实C#、VB、C++ 的性能非常接近了,轻微的差异在大部分场景下几乎是可以忽略的。这一点,我以前这个试验就是很好的解释。计算机技术发展到今天,语言的运行效率差异早就可以忽略不计了,方法论和算法的才是核心。事实上,对现代C# 而言,提高性能其实挺简单的,通过下面的试验你就可以看出来。
重新再试验
有人说,跟程序员交流,不要说那么多话,要么秀代码,要么秀妹子。我只有请出互联网的first lady——瑞典模特Lena Soderberg(展示的样本经过了处理)。Lena的介绍可以看昨天的新闻:《花花公子》的封面女郎,计算机图像界的女神。
Lena是瑞典拼法,Lenna是英文拼法。

测试图我用Lena原图,超高清3831×8192@24bpp,文件大小94.2MB。完整的 样fu本li可以在 lenna.org 下载。

拿DIP里最最简单的反色举例,同样用C#,一个萌新和一个大神分别实现,那最后的效率可差老了去了。不信咱来试试。(例子使用的方法仅限演示,不代表标准方法,也不是我这篇文章要讲述的主题——它只是个例子)
萌新的实现:单线程、managed
虽然有点儿欺负人,但它确实是实际存在的现象。新手玩家不管是熟练度还是连招都跟老油条没得比。
private void invert(Bitmap bmp) {
Color sc = new Color();
// 逐像素处理
for (int i = 0; i < bmp.Width; i++) {
for (int j = 0; j < bmp.Height; j++) {
// managed operations
sc = bmp.GetPixel(i, j);
bmp.SetPixel(i, j, Color.FromArgb(0xff - sc.R, 0xff - sc.G, 0xff - sc.B));
}
}
}
这种做法理论上是没错的,也能实现效果,就是太慢了。于是萌新可能就开始骂街:C# 真辣鸡,.NET真辣鸡。可是这算法就他妈的辣鸡啊!这种单线程的managed语法,想快它也快不起来啊。

大神的实现:并行计算、unsafe
大神之所以能叫大神,因为他们可以利用语言以及计算机的全部实力。思路上,他们能够选用最佳的合适算法;技巧上,他们可以挖掘电脑的所有潜力。同样的语言,不同的性能,我再次提出那个问题:你说瓶颈在语言还是在人?
private void invert(Bitmap bmp) {
BitmapData bdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
Parallel.ForEach(Partitioner.Create(0, bdata.Height), (H) => {
unsafe {
int x, y, w, h, s;
byte * s0, p;
w = bdata.Width;
h = bdata.Height;
s = bdata.Stride;
s0 = (byte * ) bdata.Scan0;
// 逐像素处理
for (y = H.Item1; y < H.Item2; y++) {
p = s0 + y * s;
// unsafe pointer write operations
for (x = 0; x < w; x++) {
* p = (byte)(0xff - * p);
p++;* p = (byte)(0xff - * p);
p++;* p = (byte)(0xff - * p);
p++;
}
}
}
});
bmp.UnlockBits(bdata);
}
注意这个实现用到了并行计算,没有用SetPixel
而是直接用指针操作的,虽然有点像C/C++,但是依然属于原生C# 的范畴。可是我不会逐条讲解为什么用了这些技术性能就可以提高。我这文章的主题不是教你怎么用Parallel
或者给你对比单线程和多线程的性能差,而是演示给你看初哥和大手子能轻易拉开多大的距离,以此反驳那些动不动觉得某某语言性能不行的门外汉。我可不负责科普教学,那是你自己解决的事儿。
萌新 vs 大神

看看结果吧!42466ms对上101ms,420倍的差距。谁跟我说 .NET性能差来着?请大点儿声,谢谢!
你觉得 .NET 性能低,可能只是因为你的能力低的更多相关文章
- oracle 高版本导出低版本数据库并且导入到低版本数据的方法
第一步:sqlplus system/egis@orcl as sysdba; 进入sqlplus (输入管理员用户名/密码@数据库密码) 第二步: create directory dumpdir ...
- js动画性能提升笔记
JavaScript动画的性能并不亚于CSS动画.因此,如果使用了现代的动画库,例如Velocity,那么动画引擎的性能将不再是app的瓶颈,构成瓶颈的只有代码. 网络性能相关 动画是浏览器运行中资源 ...
- HBase 管理,性能调优
设置 Hadoop 来扩展磁盘 I/O 现代服务器通常有多个磁盘硬件来提供大存储能力.这些磁盘通常配置成 RAID 阵列,作为它们的出厂设置.这在很多情况下是有益的,但对 Hadoop 却不是. Ha ...
- Unity性能优化(3)-官方教程Optimizing garbage collection in Unity games翻译
本文是Unity官方教程,性能优化系列的第三篇<Optimizing garbage collection in Unity games>的翻译. 相关文章: Unity性能优化(1)-官 ...
- 数据库访问性能优化 Oracle
特别说明: 1. 本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2. 本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...
- 1.linux服务器的性能分析与优化
[教程主题]:1.linux服务器的性能分析与优化 [课程录制]: 创E [主要内容] [1]影响Linux服务器性能的因素 操作系统级 CPU 目前大部分CPU在同一时间只能运行一个线程,超线程的处 ...
- raid性能对比
1,raid0的特性:采用剥离,数据将在几个磁盘上进行分割.数据被分成很多数据块,每一数据块会被写入不同的磁盘.从而, 每一磁盘的工作负荷都得到了降低,这有助于加速数据传输.RAID-0可让磁盘更好地 ...
- 高性能Linux服务器 第10章 基于Linux服务器的性能分析与优化
高性能Linux服务器 第10章 基于Linux服务器的性能分析与优化 作为一名Linux系统管理员,最主要的工作是优化系统配置,使应用在系统上以最优的状态运行.但硬件问题.软件问题.网络环境等 ...
- Loggly:提高ElasticSearch性能的九个高级配置技巧
Loggly日志管理服务在其很多核心功能里使用ElasticSearch作为搜索引擎.Jon Gifford在其文章“ElasticSearch vs Solr”中指出,日志管理领域对搜索技术有了更高 ...
随机推荐
- BZOJ_1864_[Zjoi2006]三色二叉树_树形DP
BZOJ_1864_[Zjoi2006]三色二叉树_树形DP 题意: 分析:递归建树,然后DP,从子节点转移. 注意到红色和蓝色没有区别,因为我们可以将红蓝互换而方案是相同的.这样的话我们只需要知道当 ...
- BZOJ_3503_[Cqoi2014]和谐矩阵_高斯消元
BZOJ_3503_[Cqoi2014]和谐矩阵_高斯消元 题意: 我们称一个由0和1组成的矩阵是和谐的,当且仅当每个元素都有偶数个相邻的1.一个元素相邻的元素包括它本身,及他上下左右的4个元素(如果 ...
- BZOJ_1697_[Usaco2007 Feb]Cow Sorting牛排序_贪心
BZOJ_1697_[Usaco2007 Feb]Cow Sorting牛排序_贪心 Description 农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行 ...
- BZOJ_2724_[Violet 6]蒲公英_分块
BZOJ_2724_[Violet 6]蒲公英_分块 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod ...
- MIP技术交流分享(3月9日)
3月9日上周四下午,MIP 团队工程师与去哪儿酒店云.众荟的 Web 前端工程师进行了一次面对面的技术交流. 在这次交流中,MIP 工程师主要分享了 MIP 技术原理,MIP 加速原理,以及 MIP ...
- Aria2序之导言
aria2是什么,如果此时此刻你看到标题读到第一行正在思索着一个问题,很抱歉 ,这篇以及后续我的blog不适合你,请移步. 我在aria2的官方站点抄袭了如下语句用来充实本文: aria2 is a ...
- Win10构建Python全栈开发环境With WSL
目录 Win10构建Python全栈开发环境With WSL 启动WSL 总结 对<Dev on Windows with WSL>的补充 Win10构建Python全栈开发环境With ...
- Web前端-Ajax基础技术(下)
Web前端-Ajax基础技术(下) 你要明白ajax是什么,怎么使用? ajax,web程序是将信息放入公共的服务器,让所有网络用户可以通过浏览器进行访问. 浏览器发送请求,获取服务器的数据: 地址栏 ...
- 安卓开发笔记(二十二):读取本地(内置)html文件并实现和Javascript交互
实际上我们通常是使用WebView控件对本地html进行读取,这样就可以体会类似web app和安卓原生混合开发的乐趣了.在读取本地html并展示在前台的时候,并不需要在Androidmenifast ...
- Android studio 2 版本升级 Android studio 3 版本注意事项
1. compile 需要改成 implementation 或者 api例:implementation 'com.android.support:support-v4:23.4.0'详细规则 ht ...