為什么動態(tài)類型語言相對比較慢?
靜態(tài)類型語言中,在聲明變量時已經(jīng)指定了數(shù)據(jù)類型和表示方法。動態(tài)類型語言是在運行期間檢查數(shù)據(jù)的類型,不得不保持描述變量值的實際類型標(biāo)記,程序在每次操作變量時,需要執(zhí)行數(shù)據(jù)依賴分支。
而間接分支(Indirect branch)和數(shù)據(jù)局部性(data locality)對于運行時的性能是致命的。
這就是動態(tài)語言的JIT編譯器基準(zhǔn)測試要強(qiáng)調(diào)near-C的內(nèi)循環(huán)速度,以及避免大的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)處理問題的原因。
我也希望像Python這樣的動態(tài)類型語言可以變快。我試過用Python來進(jìn)行傳統(tǒng)的服務(wù)器編程——“系統(tǒng)語言”領(lǐng)域——但是效果真的不好,我現(xiàn)在考慮用Java重寫一個服務(wù)器。
因此,我花時間思考如何真正靜態(tài)地編譯Python。畢竟,那是我夢寐以求的編程語言!但當(dāng)我思考如何將動態(tài)類型代碼與靜態(tài)編譯Python結(jié)合起來時,我遇到了數(shù)據(jù)變慢的問題:
在動態(tài)語言中,通常所有數(shù)組中的元素(或其他數(shù)據(jù)結(jié)構(gòu))類型各不相同,所以有不同的表示值。因此,這些值都必須被單獨存放為堆,而不是順序地存為數(shù)組。這意味著如果對不相鄰的內(nèi)存執(zhí)行數(shù)據(jù)依賴分支,則對緩存有更高的要求。
也有一些聰明的技巧,使用變量中的特殊bit,將一些原生類型(像整型)打包成一個類型,類似于指針,但這要求寄存器在操作過程中進(jìn)行跟蹤,會增加開銷。
還有一些方法,比如使用JIT編譯熱路徑(hot path)時,如果你直接插入沒有標(biāo)類型的值,而不是在堆里分別標(biāo)記類型, 那么與JIT編譯過的代碼的互操作性會降低,如果其他代碼改變了數(shù)組中的一個值的類型,就會出現(xiàn)非常嚴(yán)重的后果。
我一直在思考,在Python語言中,什么是靜態(tài)的,什么不是。通過SSTA(統(tǒng)計靜態(tài)分析)和逃逸分析可以判斷,大量正常的程序是靜態(tài)的。Paul Biggar給了我信心證實我的猜測是正確的,我的Python代碼90%都是靜態(tài)的。
有人會問,那另外的10%呢?通常情況下,我可以讓所有的都是靜態(tài)的,或者想象它被參數(shù)類型的限制范圍特殊化了。除了Python語言的標(biāo)準(zhǔn)模式,其他模式都由Web服務(wù)器分配給基于HTTP方法(如果收到GET請求就稱為“get”方法)的Web處理器,這也需要程序員依照switch語句(如elifs的長鏈)來進(jìn)行修改。
Robert Harper對“從單一類型靜態(tài)語言方面,動態(tài)語言是如何實現(xiàn)的”這個問題作出了很好的解釋,下面這句話是我希望他能進(jìn)一步進(jìn)行解釋的:
引用
我深知“編譯器可以優(yōu)化它”,至少在某些情況下。 |
我確信他說的“某些情況”是指遇到non-escaping的情況,因為和后面的執(zhí)行代碼進(jìn)行交互時,你應(yīng)該要能夠確定escape的類型。
一些動態(tài)調(diào)用是無污染的——編譯器可以從代碼檢查中發(fā)現(xiàn)一些變量(或方法)是動態(tài)的,但動態(tài)的代碼不表示其他變量也是動態(tài)的,因為不同類型的變量、方法、成員的存在或缺失都被限制成了可識別的類型(或null)。
但通常編譯器是無法從代碼檢查中發(fā)現(xiàn)這些情況的,如果無法追蹤到執(zhí)行的情況,就無法知道代碼如何依賴以及如何改變其他靜態(tài)變量的值。因此,工作中斷,所有變量再次變?yōu)閯討B(tài)的。
我一直在努力尋找把Monkey Patch(不改變初始源代碼來擴(kuò)展和修改動態(tài)語言運行代碼的方法)、Set(屬性或索引器元素賦值的“訪問器”方法)、SetAttr(SetAttr 語句可以為一個文件設(shè)置屬性信息)等解決辦法移植到我虛構(gòu)的Python編譯器里,因為類型標(biāo)記嚴(yán)重地降低了運行性能。
快速的數(shù)據(jù)結(jié)構(gòu)對于內(nèi)存訪問模式和緩存位置是非常重要的,還可以減少分支和對這些分支的標(biāo)記工作。
Jonathan Shapiro的文章Programming Language Challenges in Systems Codes非常棒,我很贊同文中的觀點。
英文原文:Why Dynamic Programming Languages Are Slow
原文鏈接:http://www.iteye.com/news/24615
【編輯推薦】