Cinder:Instagram以性能为导向的CPython

2021-05-05 20:59:40

Cinder是Instagram' S的内部性能型生产版本的PyThon 3.8。它包含许多性能优化,包括CONETECODE内联的缓存,渴望评估考程,A-A-timeJIT,以及使用类型注释的实验数据,用于在JIT中执行更好的Emittype专用字节码。

我们' ve of to puindly可公开可用,以便促进对话逐次向CPython的一些工作和努力减少努力,努力在努力履行CPYTHON绩效。

煤渣没有抛光或记录在其他任何人和#39;使用。我们没有将Cinder支持Cine作为一个独立的开源项目,也不是为了成为CPython的替代品。我们在制作该代码的目标是统一的CPython。因此,虽然我们进行Cinder Inproduction,如果您选择这样做,那么您就是自己的。我们可以' t提交offixing外部错误报告或审核拉请求。我们确保削减渣油足够稳定,速度快速,但我们对任何其他工作加载或使用的稳定性或矫正性或性能进行了释放。

那说,如果您在动态语言运行时有经验,并且具有ideasto更快地制作煤粉;或者如果您在CPython上工作并希望使用Cinder asinspiration进行CPython(或帮助Cinder Tocpython的上游部分),请伸出援手;我们' d喜欢聊天!

剪切仅在Linux x64上构建或测试;其他任何东西(包括OS X)可能会赢得' T工作。我们在Github CI验证,它构建和测试Passon Fedora 32(请参阅oss-build-andstest.sh和.github / workflows / cinder-Os-build-and-test.yml),因此Fedora 32是您最好的选择。

有一些可能有趣的新测试目标。 maketestcinder与制作测试相同,除了它跳过我们在我们的开发环境中有问题的Awew测试。 maketestcinder_jit使用完全启用的JIT运行测试套件,因此Allfunctions jitty。 make testruntime为JIT运行一套C ++ GTEST unittests。并使test_strict_module运行测试套件托架模块(见下文)。

" shadowcode"或"影子字节码"是我们内联的缓存实现。 Itobserves在执行通用Pythonopcodes和(对于热函数)的执行中的特定案例动态替换了具有特定版本的那些操作码。 ShadowCode的核心在Python / shadowCode.c中生存,尽管专业元站的实现在Python / Ceval.c中,其余的eval Loop.ShadowCode特定测试位于lib / test / test_shadowcode.py中。

如果立即等待对对异步函数的调用,我们立即将呼叫函数直接致电,直至其第一次等待。如果被称为函数达到返回而不需要等待,我们将能够在没有甚至创建Coroutine对象或推迟到AEvent循环的情况下返回那个值。这是我们的异步 - 重载中的重要(〜5%)CPU优化。

这主要是在Python / Ceval.c中实现的,通过新的VectorCall标志_py_awaited_call_Marker,指示呼叫者立即等待此调用。寻找is_await()宏和此vectorcallflag以及_pyeval_evaleagoro函数的使用。

Ciner Jit是在C ++中实现的AT-A-TIME定制JIT。它通过-x jit标志或pythonjit = 1环境变量迭代。它支持几乎所有Python操作码,并且可以在许多Python性能基准上实现1.5-4倍的快艇。

默认情况下,启用时,它将jit编译每个常见的功能,这可能会使您的程序较慢,而不是更快,因为延长了jit-compling很少被称为函数。 option -xjit-list-file = / path / to / jitlist.txt或pythonjitlistfile = / path / to / jitlist.txt可以指向文本文件介绍完全限定的函数名称(在表单路径中.to.to.to.to.to.module:funcname或path.to.to.to.module:classname.method_name),每行一个,应该是JIT编译的。我们使用此选项来编译一组从生产分析数据派生的热函数。 (JIT的MoreTypicatib方法是动态编译函数,因为他们常常观察到。它是值得的,因为我们的生产架构是前叉网络服务器,而且为内存而值得这一点。分享理由我们希望在工人分叉之前在初始过程中进行所有JIT编译,这意味着我们可以'在决定哪个函数才能编译之前,删除工作负载。)

JIT生活在JIT /目录中,其C ++测试在Runtimetests /(使用make testruntime运行这些测试)。在lib / test / test_cinderjit.py中还有Somepython测试;这些aren' t意味着穷举,因为我们通过make testcinder_jit在JIT下运行整个CPython测试套件;它们涵盖了在TheCPython测试套件中未发现的JIT边缘案例。

有关某些其他-X选项和环境variablesthat影响JIT的行为,请参阅JIT / PYJIT.CPP。在该文件中,还有一个cinderjit在该文件中向Python代码公开了一些JIT实用程序(例如,要编译特定函数,检查函数是否编译,禁用JIT)。请注意,CinderJit.disable()只禁用Futurecompilation;它立即编译所有已知的函数并保留现有的jit编译的函数。

JIT首先将Python字节码降低到高级介入物理(HIR);这是在JIT / HIR /中实现的。 HIR紧密地用Python字节码,虽然它是堆栈机器的寄存器MachineInstead,但它是一个较低的级别,它是键入的,并且由Python字节码而掩盖但是对于性能(特别是参考计数)掩盖的总体尾部是明确公开的河流。 HIRSTRANSFRANSEDOREDS形式,对其执行了一些优化通行证,ANTTHEN COUNTING操作将自动插入到HIR操作码的REFCOUNT和内存效果的元数据中。

然后将HIR降低到低级中间表示(LIR),在JIT / LIR /中实现了对组装的抽象。在LIR中,我们解读了分配,一些额外的优化通过,然后使用优秀的ASMJIT库将LOSTLIR降低到组装(在JIT / CODEGEN /)中。

JIT在早期阶段。虽然它已经可以消除Interperloop开销,并且为许多功能提供了显着的性能改进,我们只开始划伤可能的优化表面。尚未实施Many Common Compler优化。优化的upiorization在很大程度上是由Instagram生产工作量的特征驱动的。

1.一种能够验证执行模块&#39的静态分析仪;停止级别代码在该模块外面不会有副作用。

3.一种能够识别模块以识别到StrictMode(通过模块顶部的导入__strict__)的Python模块加载器,分析它们验证没有导入副作用,并在sys中填充它们。

我们目前在生产中使用的严格模块的版本是编写的,并且不是Cinder的一部分。 StrictModules /目录incinder是进入的I ++重写进口副作用分析仪。

静态Python是一个实验的字节码编译器,它利用类型的类型来发射型式专用和键入的Python字节码。多功能机组与煤渣吉特,它可以在许多情况下提供类似于MyPyC或Cython的性能,同时提供纯Python开发人员体验(普通Python语法,没有额外的编译步骤)。静态Python Plus Cinderjit实现了7倍的股票CPython在键入版本的Therichards基准测试中的表现。在Instagram中,我们已成功使用静态Python Inproduction来替换我们PrimaryWebServer CodeBase中的大部分曲线模块,没有性能回归。

静态Python编译器建立在Python编译器的顶部,从Python 3中的标准库中删除了删除,并且从外部更新并更新;此编译器纳入Cinderin Lib / Compiler。静态Python编译器是在lib / compiler / static.py中实现的,其测试在lib / test / test_compiler / test_static.py中。

静态Python模块中定义的类是自动给出键入的插槽(基于__init__中的键入类属性和注释分配器),并且属性加载和存储这些类型的次数使用新Store_field和Load_field操作码,在JIT中成为直接负载/从/到固定的内存偏移octhe对象,没有load_attr或store_attr的间接。类还获得其方法的VTables,供下面提到的Invoke_ * Opcode。这些功能的运行时支持位于包含/ classloader.h和python / classloader.c中。

静态Python函数以新的Check_args Opcode始于提供的参数'类型匹配类型的注释,如果不是,则会引发TypeError。从静态Python函数到另一个staticpython函数的调用将跳过此操作码(由于编译器已经验证了这些类型)。静态呼叫也可以避免典型的Python函数调用的大部分开销。我们发出invoke_function或Invoke_method操作码,它带有关于Callfunction或方法的IT元数据;这加上可选的模块(通过StrictModule)和类型(通过Ciner.FREEZE_TYPE(),我们正在进口装载机中的严格和静态模块中的所有类型应用于所有类型,但是INFUTURE可能成为静态Python的固有部分,并编译时Callee签名允许我们(在JIT中)将许多PythonFunction调用转到直接呼叫到使用X64Calling约定的固定内存地址,而且比C函数调用更多。

静态Python仍然逐渐键入,并支持唯一通过返回正常的pythondynamic行为而唯一的批次注释或使用未知类型的代码。在某些情况下(例如,当从返回注释返回的函数返回的静态未知类型的值)时,插入运行时courtopcode,如果运行时类型不匹配预期类型,则会引发TypeError。

静态Python还支持机器整数,BOOL,双打和向量/阵列的新类型。在JIT中,它们被处理为未封箱值,而e.g.primitive整数算术避免了所有Python开销。还优化了OnBuiltin类型的一些操作(例如,列表或字典下标或LEN())。

Cinder NON' t目前捆绑在一起,模块装载机能够以浅析静态模块,并将其装载为静态,具有交叉调制化合物;我们目前通过我们的严格/静态导入加载器来执行此操作,这不是Cinder的一部分。目前,在Cinder中使用静态度进行实验的最佳方法是使用./python -M编译器--static you_module.py,它将将模块编译为静态python并执行它。 (添加--dis标志也将其拆卸汇编。)由于这不默认注意到StrictModule和Freeze类型,因此结果代码赢得了' TJIT尽可能地作为我们所获得的产品,特别是对于功能和方法。