Lua 和 Python 同为虚拟机解释型脚本语言,为什么 Lua 的执行速度比 Python 高?
回复内容:
前面几位已经说的很好,我来做一下补充。@冯东 和 @庞巍伟 都提到了Lua使用的是register-based的虚拟机设计,我看到下面有人评论说既然这种VM的设计性能高,那么为什么Python和java还是使用的stack-based的设计。
我的理解是实现难度吧,register-based的设计中,一个操作需要关注到指令的操作数到底存放在哪里,而stack-based的不需要,它分开了几条指令,首先加载数据到栈顶,然后再进行操作,操作时默认的认为数据就存在栈顶了。(如果不清楚这个过程,可以拖上去看看 @庞巍伟 的回答,就不在这里列出来了)
简单的说,register-based的指令格式设计把stack-based的指令中分几条指令要完成的事情用一条指令搞定了,快当然是快了,难度也加大了。
另外还有一点上面的回答中似乎没有提到,Lua使用的是一遍遍历就生产指令的方式,学过编译原理的,大概都能知道一般分两遍遍历,第一遍生成AST,再一遍遍历AST生成指令,而在Lua中是直接跳过了AST指令这一步的。
还是那句话,快是快了,代码的实现难度也大了些。最早的Lua解释器,也是使用lex、yacc这样的工具来自动生成代码的,后来为了提升性能,作者改成了自己手写的递归下降的分析器。这部分代码是我认为Lua代码中最难理解的一个部分了--因为它要一遍分析干太多的事情了。
我在阅读Lua代码的过程中,能充分感受到作者为了Lua在性能上的提升花费的心血,致敬。 有一些 PUC-Rio Lua(也就是没 JIT 的)和 Python 的 benchmark 对比。结论是 Python 比 C 大约慢 70 倍,Lua 大约慢 30-40 倍。
Lua 是 register-based VM。所谓的寄存器,其实并不神秘,就是 runtime stack 的 topmost frame [1] 是可以被 VM 指令随机访问的。至于为什么 CPU 里的某种硬件也叫寄存器,原因在这里有解释:《什么是寄存器》。
Stack frame 可以被随机访问之后,在同一个 VM 指令里就可以用 native code 一次做很多事情。
可以看云风的这篇 blog:《云风的 BLOG: 虚拟机之比较,lua 5 的实现》
- Stack frame 就是 stack 中属于同一个 function invocation 的所有 stack entries。
最关键的是, lua 是基于寄存器的虚拟机实现,而python还有很多其他脚本语言是基于堆栈的,基于寄存器的虚拟机字节码更简单,更高效,因为register based vm的字节码,一般同时包含了指令/操作数/操作目标等.
对比简单的加法操作:
stack based 生成的字节码大概是这样(仅仅是模拟,不代表实际)
PUSH 1
PUSH 2
ADD // ADD 的操作结果存放eax
PUSH eax // 将结果push入堆栈,以便后面的代码不会覆盖eax
而register based 生成的字节码大概是这样:
ADD 1,2,R1
就一行,R1存放1+2的结果
就这么简答的操作就已经相差4条指令,所以基于寄存器的虚拟机字节码运行更有效率. python的一些设计特性,例如完全面向对象,同时也是它在性能表现上的负担。
举个很简单的例子:
<span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
Lua的语言特性设计的很紧凑,在各方面进行优化的困难路径都比JS和Python少(得多),
Python基于纯对象的, 任意东西都是对象. 所以数值运算时, 还要进行转换lua 最新的5.3 已经支持整数类型, 加上基于寄存器的VM和优秀的编译器, 想慢都难 抛个砖,引个玉。
1. 基于栈和基于寄存器的不同是主要的性能差异原因。这点大家也都解析的非常清楚了,也很好想象。基于栈的求值过程必须使用栈顶的值,想想也知道是反人类的(哦不,反机器的-_-!)。因此会出现很多的push(load)和pop(store)指令,而基于寄存器的指令就一条完事了。但这都是在解释执行的情况下,如果编译到本地指令之后,理论上来说,基于寄存器还是基于栈的实现并没有太多影响,因为都转换成了硬件寄存器,两者的转换过程的开销也没有太多差别。
2. 为什么采用基于栈的虚拟机,除了实现简单(后序遍历AST就有了)之外,占用空间小也是一个基于栈的虚拟机的特点,便于网络传输和嵌入式设备。Java在设计之初就是考虑到网络方面的应用,比如Applet技术,以及嵌入式设备的运用。
3. 个人还有一个想法,不知道是否靠谱@RednaxelaFX。基于栈的虚拟机的指令更加完整地保留了源代码的求值过程,几乎是AST直接『压平』的结果,甚至很容易逆回源代码。这就意味着基于栈的指令在后续操作中可以很容易转换成需要的形式,以便于在不同的形式上做优化。栈代码转换成寄存器代码没有什么效率影响,而寄存器代码转换成栈代码就会出现比遍历AST生成还要多的push(load)和pop(store)指令。栈代码的生成适合直接从AST后续遍历得到,因为求值的过程都是围绕着栈顶。简而言之,栈代码是一个可塑性比较强的代码,先存着,后面想怎么处理都保留了可能性。
4. 语法分析到代码生成过程减少pass数,个人觉得并没有太大的意义。严格来讲这个过程的效率应该不能算是performance的效率,最多只是加快了从源码的启动时间。Performance应该从解释执行开始比较。有的时候单趟编译造成了复杂性反而得不偿失,AST这样的数据结构就适合在上面干该干的事。
5. 实际中虚拟机的效率还和很多其他啊因素有关。比如很重要的方面就是垃圾回收。
6. 至于上升到指令集设计高度的话,不太了解,请R大来。 @RednaxelaFX。他应该会贴个这个传送门虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 Lua的指令集非常非常非常简单,我对着指令说明看了半个小时就能看懂lua的汇编代码了,再花十来分钟就能手动修改lua二进制代码了。而我甚至没完整看过lua的源码。 占坑 以我的观点,最大的关键是在 lua 在语言层面相比 python 简单了很多,所以他们的实现相应的就有了速度的差别。

要在有限的时间内最大化学习Python的效率,可以使用Python的datetime、time和schedule模块。1.datetime模块用于记录和规划学习时间。2.time模块帮助设置学习和休息时间。3.schedule模块自动化安排每周学习任务。

Python在游戏和GUI开发中表现出色。1)游戏开发使用Pygame,提供绘图、音频等功能,适合创建2D游戏。2)GUI开发可选择Tkinter或PyQt,Tkinter简单易用,PyQt功能丰富,适合专业开发。

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。 Python以简洁和强大的生态系统着称,C 则以高性能和底层控制能力闻名。

2小时内可以学会Python的基本编程概念和技能。1.学习变量和数据类型,2.掌握控制流(条件语句和循环),3.理解函数的定义和使用,4.通过简单示例和代码片段快速上手Python编程。

Python在web开发、数据科学、机器学习、自动化和脚本编写等领域有广泛应用。1)在web开发中,Django和Flask框架简化了开发过程。2)数据科学和机器学习领域,NumPy、Pandas、Scikit-learn和TensorFlow库提供了强大支持。3)自动化和脚本编写方面,Python适用于自动化测试和系统管理等任务。

两小时内可以学到Python的基础知识。1.学习变量和数据类型,2.掌握控制结构如if语句和循环,3.了解函数的定义和使用。这些将帮助你开始编写简单的Python程序。

如何在10小时内教计算机小白编程基础?如果你只有10个小时来教计算机小白一些编程知识,你会选择教些什么�...

使用FiddlerEverywhere进行中间人读取时如何避免被检测到当你使用FiddlerEverywhere...


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3汉化版
中文版,非常好用

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

Dreamweaver Mac版
视觉化网页开发工具

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。