歡迎光臨
每天分享高質量文章

你覺得 .NET 性能低,可能只是因為你的能力低

奇了個怪

.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 年的測試,主要內容已經丟失,我在網上找到的爬蟲文章

當時一幫哥們兒看了我的試驗都手癢秀了一遍優化:
滑鼠移到作者名字上可以查看作者信息

▼ 各路大神和我試驗的結果(4096×[email protected]反色)

編號 作者 耗時(毫秒) 實現方法 平臺
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++ 的性能非常接近了,輕微的差異在大部分場景下幾乎是可以忽略的。這一點,我以前這個試驗就是很好的解釋。計算機技術發展到今天,語言的運行效率差異早就可以忽略不計了,方法論和演算法的才是核心。

重新再試驗

有人說,跟程式員交流,不要說那麼多話,要麼秀代碼,要麼秀妹子。那麼我接下來就請出互聯網的first lady——瑞典模特Lena Soderberg(展示的樣本經過了處理)。Lena的介紹可以看昨天的新聞:《花花公子》的封面女郎,計算機圖像界的女神。
Lena是瑞典拼法,Lenna是英文拼法。

▲ Lena/Lenna

測試圖我用Lena原圖,超高清3831×[email protected],檔案大小94.2MB。圖像樣本可以在 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++) {
      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

大神之所以能叫大神,因為他們可以利用語言以及計算機全部實力。思路上,他們能夠選用最佳的合適演算法;技巧上,他們可以挖掘電腦的所有潛力。同樣的語言,不同的性能,我再次提出那個問題:你說瓶頸在語言還是在人

萌新 vs 大神

▲ 同一種語言,同一個任務

看看結果吧!42466ms對上101ms,420倍的差距。誰跟我說 .NET性能差來著?請大點兒聲,謝謝!?

完畢

其實就上面的例子來說,還能把性能再往上提,但這都是次要的。我想表達的意思已經表達完了:.NET的性能並不低,如果你覺得低,那可能是因為你的能力低

原文地址:https://www.cnblogs.com/conmajia/p/low-performance-csharp-all-your-fault.html


.NET社區新聞,深度好文,歡迎訪問公眾號文章彙總 http://www.csharpkit.com


 

    閱讀原文

    赞(0)

    分享創造快樂