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一知半解就开始嘲讽的“别的语言”玩家,就更别指望他们能理解到其中的精髓了。

把自己限制于一种语言的程序员会经常错过其他地方提供的重要机会。这样的程序员绝对不会被他们的老板或客户看成是专业领域中的专家。

——Oliver Sturm

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# 的性能到底是低还是高?

▲ 2012 年的测试,主要内容已经丢失,我在网上找到的爬虫文章

当时一帮哥们儿看了我的试验都手痒秀了一遍优化:

鼠标移到作者名字上可以查看作者信息,他们都是真·大神

.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;}

▼ 各路大神和我试验的结果(4096×4096@24bpp反色)
编号 作者 耗时(毫秒) 实现方法 平台
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/Lenna

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

▲ Playboy 1972 Miss November

拿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语法,想快它也快不起来啊。

▲ 你来告诉我1个核上慢慢摇性能怎么提起来?

大神的实现:并行计算、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 性能低,可能只是因为你的能力低的更多相关文章

  1. oracle 高版本导出低版本数据库并且导入到低版本数据的方法

    第一步:sqlplus system/egis@orcl as sysdba;  进入sqlplus (输入管理员用户名/密码@数据库密码) 第二步: create directory dumpdir ...

  2. js动画性能提升笔记

    JavaScript动画的性能并不亚于CSS动画.因此,如果使用了现代的动画库,例如Velocity,那么动画引擎的性能将不再是app的瓶颈,构成瓶颈的只有代码. 网络性能相关 动画是浏览器运行中资源 ...

  3. HBase 管理,性能调优

    设置 Hadoop 来扩展磁盘 I/O 现代服务器通常有多个磁盘硬件来提供大存储能力.这些磁盘通常配置成 RAID 阵列,作为它们的出厂设置.这在很多情况下是有益的,但对 Hadoop 却不是. Ha ...

  4. Unity性能优化(3)-官方教程Optimizing garbage collection in Unity games翻译

    本文是Unity官方教程,性能优化系列的第三篇<Optimizing garbage collection in Unity games>的翻译. 相关文章: Unity性能优化(1)-官 ...

  5. 数据库访问性能优化 Oracle

    特别说明: 1.  本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2.  本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...

  6. 1.linux服务器的性能分析与优化

    [教程主题]:1.linux服务器的性能分析与优化 [课程录制]: 创E [主要内容] [1]影响Linux服务器性能的因素 操作系统级 CPU 目前大部分CPU在同一时间只能运行一个线程,超线程的处 ...

  7. raid性能对比

    1,raid0的特性:采用剥离,数据将在几个磁盘上进行分割.数据被分成很多数据块,每一数据块会被写入不同的磁盘.从而, 每一磁盘的工作负荷都得到了降低,这有助于加速数据传输.RAID-0可让磁盘更好地 ...

  8. 高性能Linux服务器 第10章 基于Linux服务器的性能分析与优化

    高性能Linux服务器 第10章    基于Linux服务器的性能分析与优化 作为一名Linux系统管理员,最主要的工作是优化系统配置,使应用在系统上以最优的状态运行.但硬件问题.软件问题.网络环境等 ...

  9. Loggly:提高ElasticSearch性能的九个高级配置技巧

    Loggly日志管理服务在其很多核心功能里使用ElasticSearch作为搜索引擎.Jon Gifford在其文章“ElasticSearch vs Solr”中指出,日志管理领域对搜索技术有了更高 ...

随机推荐

  1. POJ1038 Bugs Integrated, Inc 状压DP+优化

    (1) 最简单的4^10*N的枚举(理论上20%) (2) 优化优化200^3*N的枚举(理论上至少50%) (3) Dfs优化状压dp O(我不知道,反正过不了,需要再优化)(理论上80%) (4) ...

  2. java面试题总结

    一.http://blog.csdn.net/moneyshi/article/details/50786786 二.http://blog.csdn.net/moneyshi/article/det ...

  3. 从MVC和三层架构说到SSH整合开发

    相信很多人都认同JavaWeb开发是遵从MVC开发模式的,遵从三层架构进行开发的,是的,大家都这么认同.但是相信大家都会有过这样一个疑问,if(MVC三层模式==三层架构思想)out.println( ...

  4. 【毕业原版】-《伦敦艺术大学毕业证书》UAL一模一样原件

    ☞伦敦艺术大学毕业证书[微/Q:865121257◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归& ...

  5. python 安装cv2

    问题描述:import cv2 报错提示未安装此包. 解决措施: 1.cmd框中输入pip install cv2,若安装成功,则恭喜你一次性成功,如提示"无法找到与你当前版本的匹配&quo ...

  6. Java 11 新功能来了!

    关键时刻,第一时间送达! 目前 Oracle 已经发布了 Java Development Kit 10,下个版本 JDK 11 也即将发布.本文介绍 Java 11 的新功能. 根据Oracle新出 ...

  7. postman接口测试举例情况

    http请求:http请求分为请求头和请求体,get请求只有请求头没有请求体. 1.get请求 是可以直接在浏览器访问,不需要借助任何工具.好看一些,可以打开postman测试接口 http://xx ...

  8. HashMap 实现及原理

    1.为什么用HashMap? HashMap是一个散列桶(数组和链表),它存储的内容是键值对(key-value)映射HashMap采用了数组和链表的数据结构,能在查询和修改方便继承了数组的线性查找和 ...

  9. 解决tomcat部署项目中碰到的几个问题

    在tomcat上部署项目并进行测试,经常会碰到各种问题.在不同的操作系统上部署,对问题的解决也会有一些差异. 1 发现问题 1.1 项目部署 先将项目达成war包,放到tomcat的webapps目录 ...

  10. 【转载】Docker+Kubernetes 干货文章精选

    主要涉及到以下关键字: K8S.Docker.微服务.安装.教程.网络.日志.存储.安全.工具.CI/CD.分布式.实践.架构等: 以下盘点2018年一些精选优质文章! 漫画形式: 漫画:小黄人学 S ...