天天看點

python lua 性能比較 記憶體_Lua 的速度為什麼比 Python 快?

最近研究了下Python的代碼,有了一些新的發現。大量的内置字元串常量沒有做Intern優化,在python源碼中搜尋形如"__dict__"之類的常量是這麼用的:

PyObject* xxxObject = PyObject_GetAttrString(someObject, "__dict__");

這樣會導緻每次調用到這裡時都會去查找一下有沒有建立過這個字元串。實際上對于腳本虛拟機中這類常量應該提前配置設定好,直接使用PyObject引用,而不是每次都嘗試去建立一個。要命的是GetAttrString在很多基礎操作中會大量使用…… lua對這些字串則都緩存了起來。

在Python 3之後,python使用了_Py_Identifier緩存了一些靜态名字,使得這部分性能得到了一定的優化。

2. 使用RC和TRACE的GC方案導緻需要大量,頻繁地增減計數器。lua沒有這個開銷。

3. Python 中調用函數會把參數打包成一個tuple,頻繁建立和删除tuple造成比較大的開銷(雖然内部對tuple有緩存機制,但是仍然會增加約10%的消耗)。Python 2中instancemethod會導緻重新打包一次tuple再去call,加重了這個問題。實際上由于Python不支援多線程,在有些情況下可以使用複用這些tuples的,沒必要每次都重新建立。lua則直接在lua_State的棧上展開了參數,不需要打包數組。

4. 運算符的調用鍊和需要處理的動态情況過多,導緻自定義一個支援運算符的類型的性能極差。相比lua的metatable少量的table查找,python的實作極其複雜。有興趣地童鞋可以看看PyNumber_Add的實作。

5. 對輕類型的支援不好,為了OOP實作得太重了。這一點其他答案說得比較多,這部分主要是記憶體消耗和是否走GC的差異,在這方面lua的内置類型number/lightuserdata不走gc的優勢很明顯。

6. 虛拟機實作上的差異,lua register-based VM可以讓指令的數量少很多。Python這方面天然比較吃虧且沒有什麼簡單的解決辦法。

7. C-API效率上python的api比較難用,而使用封裝好的綁定庫會進一步增加API調用上的開銷。一個簡單地讀取自定義C對象中某個屬性的操作,從發起調用到讀到對應屬性的半程操作中(不算寫回到腳本),Python有80%的時間花費在調用鍊和資料轉換上,相比Lua隻有50%左右。

後面的想到再說~

總的來說,如果把腳本語言比作一個垃圾處理站,那麼Python就是不管你要扔什麼垃圾,統一都通過一個入口倒進去,然後垃圾處理站内部再用複雜的流程去分類處理。而Lua會預設幾個大的門類,常用的紙箱飲料瓶專窗背後直接對接再生制品的工廠,廚餘垃圾專窗背後直接對接飼料場,剩下的再走複雜流程。

大多數情況下,來倒垃圾的都在lua預設的那幾個大門類裡。

最後貼一下Python和Lua在如下幾個方面實測的效率差異吧,平台Windows 64Bit:基礎數值計算:Lua速度是Python的10-15倍

與宿主語言互動:Lua速度是Python的3-5倍

字元串操作:兩者差不多

綜合性能:具體取決于代碼中各種操作的比例,實際效果Lua一般在Python的2-4倍之間。