最近研究了下Python的代码,有了一些新的发现。
1、大量的内置字符串常量没有做Intern优化,在python源码中搜索形如"__dict__"之类的常量是这么用的:
class="highlight">
这样会导致每次调用到这里时都会去查找一下有没有创建过这个字符串。实际上对于脚本虚拟机中这类常量应该提前分配好,直接使用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倍之间。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.