重现unladen-swallow的性能对比实验

来源:互联网 发布:淘宝男装外贸 编辑:程序博客网 时间:2024/05/16 07:14

unladen-swallow项目的失败实际上宣告了大幅度改变动态语言的性能是不可能的,个人觉得像python这样的动态语言改变他的性能的意义也不是特别大.没一种语言都有他实际的应用领域,其次随着计算机性能的越来越好,运行效率的问题不会显得太突出

我在编译unladen-swallow这个项目的时候,遇到一个很诡异的make错误:

-g -O3  -I. -IInclude -I../src -I../src/Include   -DPy_BUILD_CORE -o Python/bltinmodule.o ../src/Python/bltinmodule.c              #(这一行是ok的)

下一行的提示

../src/Python/makeopcodetargets.py ../src/Python/opcode_targets.h

:没有那个文件或目录#(no such file or directory)

make: *** [../src/Python/opcode_targets.h] 错误 127

我的第一反应是../src/Python/makeopcodetargets.py ../src/Python/opcode_targets.h 这两个东西是不是不存在,于是我去文件夹里面寻找了一下,发现这两个文件都存在的,于是我就想,是不是makeopcodetargets.py这个python脚本在运行的时候遇到以它所在的目录为当前目录,然后在当前目录下寻找../scr/Python/opcode_targets.h.于是我做了一下测试,发现脚本在运行的时候当前目录并没有改变.接下来我能想的就是看看makeopcodetargets.py这个文件里面倒是是什么,在下面我列了出来

#! /usr/bin/env python"""Generate C code for the jump table of the threaded code interpreter(for compilers supporting computed gotos or "labels-as-values", such as gcc)."""import impimport osdef find_module(modname):    """Finds and returns a module in the local dist/checkout.    """    modpath = os.path.join(        os.path.dirname(os.path.dirname(__file__)), "Lib")    return imp.load_module(modname, *imp.find_module(modname, [modpath]))def write_contents(f):    """Write C code contents to the target file object.    """    opcode = find_module("opcode")    targets = ['_unknown_opcode'] * 256    for opname, op in opcode.opmap.items():        if opname == "STOP_CODE":            # XXX opcode not implemented            continue        targets[op] = "TARGET_%s" % opname    f.write("static void *opcode_targets[256] = {\n")    f.write(",\n".join("\t&&%s" % s for s in targets))    f.write("\n};\n")if __name__ == "__main__":    import sys    assert len(sys.argv) < 3, "Too many arguments"    if len(sys.argv) == 2:        target = sys.argv[1]    else:        target = "Python/opcode_targets.h"    f = open(target, "w")    try:        write_contents(f)    finally:        f.close()

这个.py中的代码有两个函数,find_module和write_contents.既然代码比较短,我就直接把这段代码的意思给看了.当然先从注释看起,可以看出这主要是生成一个c代码,为生成线程代码解释器的跳转表服务.看完之后发现问题也不在这儿.

既然都不是这写原因,那我只能去看make文件了,找到了对应的make文件的657行

$(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)    $(OPCODETARGETGEN) $(OPCODETARGETS_H)Python/eval.o: Python/eval.cc $(OPCODETARGETS_H)

奇葩了,完全没有问题,这是不是系统的原因,我用的是国产的linux deepin,于是我去实验室在ubuntu上重新实现了一下上面的过程,这个时候出现了新的问题。也就是/usr/include/gnu/stubs-32.h,no such file or directory。我对linux的内核不是特别了解,没法从根源去寻找原因,这个时候我就上网寻找答案,将网上可以有的答案都实现了一遍,发现还是没有解决问题。然后我去/usr/gnu文件夹下去寻找,发现确实没有stubs-32.h文件,但是有stubs.h和stubs-64.h。难道是因为我装的ubuntu 12.04 LTS导致stubs-32.h被装到别的地方去了?search文件,发现这个东西跑到/usr/include/i386-linux-gnu/gnu/里面去了。将其copy到/usr/include/gnu/里面,接着make。没有出现上面的奇葩问题,顺利通过编译。unladen-swallow 成功生成,看到python可执行文件略感欣慰,擦,废了哥一天时间

最后我将得到的优化后的python在benchmark上运行了一下,主要跑了一个django的程序,迭代100次。得到了unladen-swallow在llvm开启优化功能后的性能和未开启优化功能的运行效率对比,



Unladen-Swallow是隶属于Google的开源项目,初始目标:1)将Python的速度提高至少5倍;2)用它写出来的Python应用程序性能必须能十分稳定;3)提供与CPython源代码级的兼容;4)提供与CPython源代码级的扩展模块的兼容;5)这个项目会逐渐成为Python实现的一个独立的分支。这个项目将Python字节码架构在LLVM上面,利用LLVM的JIT编译器实现部分优化,保留Python其他部分不变,他这么做的原因是Python的大部分的运行时间用在eval循环里面。在Q1版本中,用vmgen[2]重新实现了eval核心循环,提高了垃圾回收和cPickle的性能,简化帧对象,提高全局和内建对象的查询速度;在Q2版本中加入了基于LLVM的JIT编译器;在Q3版本中将执行性能提高了15-70%。最后做了一个对比,将Q1和Q2以及Q3的性能分别做了一个测试并将我的方法用在Q1,Q2,Q3,Q4上面,得到了性能的提升。Q4和CPython的性能对比如上图所示。

从这两幅图片可以看出来,效率还是有一定的提高的,只是对于一个本来效率就不太高的语言来说,这样的提高有多大意义就另当别论了,但有一点是肯定的,这跟unladen-swallow开始的目标差的太远了……