Wednesday, January 09, 2008 - 文章

Smart C# Compiler

前陣子幫同事追查問題,由於懷疑主機上的程式版本有誤,便找來Source Code,與Reflector反編譯(Decompile)主機上DLL得到的Code比較,在一段程式上發現了小小的差異: Souce Code裡是先將DropDownList的SelectedValue先存到變數中,再將該變數當成呼叫另一個函數的參數;而Reflector中看到的卻是直接將DropDownList.SelectedValue直接被當成呼叫另一函數的參數。

程式寫法的差異,讓人懷疑上線的程式版本有誤。但同事印象中從頭到尾不曾用過這種寫法,追查上線記錄則顯示版本管理出錯的機率極低,到底是怎麼一回事? 幾經波折,最後在其他地方找到錯誤的根源,與程式邏輯無關,證實了程式版本並沒有任何問題。但引發一個有趣的結論: "DLL反編譯的結果與Source Code可能存在差異",之前在探討Nullable Value Type時,曾有類似的經驗,莫非這次又遇到?

一些效能討論文章中提過Compiler本身會做一些最佳化,剛才提到Source Code將DropDownList.SelectedValue存成變數,變數只被用了一次--當成呼叫函數時的參數。少了這個變數不會對邏輯有任何影響,還可以省下宣告/建立變數的成本,的確是種最佳化。

為了印證這點,我寫了以下的程式,還順道驗證一下上回提過的靜態字串相加會直接被Compiler做掉的理論,程式如下:

using System;
using System.Collections.Generic;
using System.Text;
 
namespace SmartCompiler
{
    class Program
    {
        static void Main(string[] args)
        {
            int j = 0;
            string s = "Hello " + "World!";
            string t = s;
            Console.Write(t);
            int i = 3 + 5;
            Console.Write(i);
        }
    }
}

用Reflector解析一下,有幾個地方被"最佳化"了:

1.變數j宣告了卻從未用到,Compiler直接忽略,在DLL中完全未現身。
2.由於s只被用來指定給t,所以就直接用t取代s。
3."Hello World!"直接變成一個字串指定給t。
4.Compiler直接算好3+5=8指定給i。

Compiler真是愈來愈聰明了,不過不代表以後程式可以亂寫,再交給Compiler去調。Compiler能做的小修正有限,省下來多半只是幾個Tick的極微時間,有時數百萬個Compiler最佳化也抵不上Coding時的一個小疏忽,只能當成錦上添花。

講到Coding時應注意效能,最近又再度見識到在上萬次迴圈中反覆做Database查詢的"好"程式,一整個囧!

搜尋

Go

<January 2008>
SunMonTueWedThuFriSat
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789
 
RSS
【工商服務】
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


BlogLook Score and Rank

Syndication