英文:https://arpitbhayani.me/blogs/constant-folding-python

作者:arprit

译者:豌豆花下猫(“Python猫”公众号作者)

声明:本翻译是出于交流学习的目的,基于 CC BY-NC-SA 4.0 授权协议。为便于阅读,内容略有改动。

每种编程语言为了表现出色,并且实现卓越的性能,都需要大量编译器级的优化。

一种著名的优化技术是“常量折叠”(Constant Folding):在编译期间,编译器会设法识别出常量表达式,对其进行求值,然后用求值的结果来替换表达式,从而使得运行时更精简。

在本文中,我们深入探讨了什么是常量折叠,了解了它在 Python 世界中的适用范围,最后解读了 Python 的源代码(即 CPython),并分析出 Python 是如何优雅地实现它。

常量折叠

所谓常量折叠,指的是在编译时就查找并计算常量表达式,而不是在运行时再对其进行计算,从而会使运行时更加精简和快速。

>>> day_sec = 24 * 60 * 60

当编译器遇到一个常量表达式时,如上所述,它将对表达式求值,并作替换。

通常而言,表达式会被“抽象语法树”( Abstract Syntax Tree,简写为 AST)中的计算值所替换,但是这完全取决于语言的实现。

因此,上述表达式可以等效地被执行为:

>>> day_sec = 86400

Python 中的常量折叠

在 Python 中,我们可以使用反汇编模块(Disassembler)获取 CPython 字节码,从而更好地了解代码执行的过程。

当使用dis模块反汇编上述常量表达式时,我们会得到以下字节码:

>>> import dis
>>> dis.dis("day_sec = 24 * 60 * 60") 0 LOAD_CONST 0 (86400)
2 STORE_NAME 0 (day_sec)
4 LOAD_CONST 1 (None)
6 RETURN_VALUE

从字节码中可以看出,它只有一个LOAD_CONST ,以及一个已经计算好的值86400

这表明 CPython 解释器在解析和构建抽象语法树期间,会折叠常量表达式 24 * 60 * 60,并将其替换为计算值 86400。

常量折叠的适应范围

Python 会尝试折叠每一个常量表达式,但在某些情况下,即使该表达式是常量,但是 Python 并不会对其进行折叠。

例如,Python 不会折叠x = 4 ** 64,但会折叠 x = 2 ** 64

除了算术表达式,Python 还会折叠涉及字符串和元组的表达式,其中,长度不超过 4096 的字符串常量表达式会被折叠。

>>> a = "-" * 4096   # folded
>>> a = "-" * 4097 # not folded
>>> a = "--" * 4096 # not folded

常量折叠的内部细节

现在,我们将重点转移到内部的实现细节,即关注 CPython 在哪里以及如何实现常量折叠。

所有的 AST 优化(包括常量折叠)都可以在 ast_opt.c 文件中找到。基本的开始函数是 astfold_expr,它会折叠 Python 源码中包含的所有表达式。

这个函数以递归方式遍历 AST,并试着折叠每个常量表达式,如下面的代码片段所示:

astfold_expr 在折叠某个表达式之前,会尝试折叠其子表达式(操作对象),然后将折叠操作代理给特定的表达式折叠函数。

特定操作的折叠函数对表达式求值,并返回计算后的常数,然后将其放入 AST 中。

例如,每当 astfold_expr 遇到二值运算时,它便调用 fold_binop,递归地计算两个子操作对象(表达式) 。

fold_binop 函数返回计算后的常量值,如下面的代码片段所示:

fold_binop 函数通过检查当前运算符的种类,然后调用其相应的处理函数来折叠二值运算。例如,如果当前的操作是加法运算,为了计算最终值,它会对其左侧和右侧操作数调用 PyNumber_Add。

怎样优雅?

为了有效地折叠某些模式或类型的常量表达式,CPython 不会写特殊的逻辑,而是调用相同的通用代码。例如,在折叠时,它会调用通用的 PyNumber_Add 函数,跟执行常规的加法操作一样。

因此,CPython 通过确保其通用代码/计算过程可以处理常量表达式的求值,从而消除了编写特殊函数来处理常量折叠的需要。

参考材料

Python优化机制:常量折叠的更多相关文章

  1. python的优化机制与垃圾回收与gc模块

    python属于动态语言,我们可以随意的创建和销毁变量,如果频繁的创建和销毁则会浪费cpu,那么python内部是如何优化的呢? python和其他很多高级语言一样,都自带垃圾回收机制,不用我们去维护 ...

  2. ☕【Java技术指南】「编译器专题」重塑认识Java编译器的执行过程(常量优化机制)!

    问题概括 静态常量可以再编译器确定字面量,但常量并不一定在编译期就确定了, 也可以在运行时确定,所以Java针对某些情况制定了常量优化机制. 常量优化机制 给一个变量赋值,如果等于号的右边是常量的表达 ...

  3. C++的常量折叠(一)

    前言 前几天女票问了我一个阿里的面试题,是有关C++语言的const常量的,其实她一提出来我就知道考察的点了:肯定是const常量的内存不是分配在read-only的存储区的,const常量的内存分配 ...

  4. python变量与常量内容:

    ''' python变量与常量内容: ''' # 变量:定义世间万物变化的状态 ''' height 180 weight 140 age 18 tree_name yuyang ''' # prin ...

  5. C++中的常量折叠

    先看例子: #include <iostream> using namespace std; int main() { ; int * p = (int *)(&a); *p = ...

  6. const常量折叠

    首先来看一个例子: int main(int argc, char* argv[]) { ; int *j = (int *) &i; *j=; cout<<&i<& ...

  7. C++的常量折叠(二)

    前面的C++的常量折叠(一)的最后留下了一个问题,那就是在声明i的时候,加上修饰符volatile关键字,发现结果输出的就不一样了,下面来说一下volatile这个关键字. C/C++中的volati ...

  8. Python反射机制理解

    Python反射机制用沛齐老师总结的话说就是:利用字符串的形式去对象(模块)中操作(寻找)成员. getattr(object, name) object代表模块,name代表模块中的属性或成员,该函 ...

  9. java之常量折叠

    为什么会写着篇博客,因为昨天看了关于final关键字的解析.但是有个问题始终没有得到解决,于是请教了我qq上之前添加的知乎大神.他给我回复的第一条消息:常量折叠.身为渣渣猿的我立马查询了这个概念.这是 ...

随机推荐

  1. 如果using语句中出现异常,资源会被释放掉吗?

    <CLR Via C#>第三版 P489 在using内部抛出了异常,被using的对象还是会被释放掉. Using编译时会自动生成Try Finally代码块. 同样Using只能用于实 ...

  2. CSSmargin击穿问题(子元素margin-top会影响父元素)

    最近写一个H5页面的时候发现了这个被忽视的问题,一时没想到什么原因,搜了半天,记录一下,方便他人踩坑.唉,有些东西不用就忘. 一.问题描述 <div class="container& ...

  3. 编译Nacos,解决No Server available 以及 failed to req API__nacos_v1_ns_instance after all servers

    问题描述:如图,显示没有服务可用 仔细看控制台,看到上面Error部分,相关参数没有读取到配置信息,那么配置信息这块似乎是有问题,赶紧看看IDE对配置信息的扫描情况: 可以看到有信息了,但是报错:No ...

  4. .NET 中依赖注入组件 Autofac 的性能漫聊

    Autofac 是一款超赞的 .NET IoC 容器 ,在众多性能测评中,它也是表现最优秀的一个.它管理类之间的依赖关系, 从而使 应用在规模及复杂性增长的情况下依然可以轻易地修改.它的实现方式是将常 ...

  5. 3、剑指offer-数组——数组中重复的数字

    *题目描述* **在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输 ...

  6. poj2185Milking Grid

    Milking Grid Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8325   Accepted: 3588 Desc ...

  7. Vue3.0短视频+直播|vue3+vite2+vant3仿抖音界面|vue3.x小视频实例

    基于vue3.0构建移动端仿抖音/快手短视频+直播实战项目Vue3-DouYin. 5G时代已来,短视频也越来越成为新一代年轻人的娱乐方式,在这个特殊之年,又将再一次成为新年俗! 基于vue3.x+v ...

  8. Vue-Cli程序环境搭建

    环境搭建 ##1.下载node.js cmd输入 node -v 查看是否能够正确打印出版本号 cmd输入 npm -v 查看是否能够正确打印出版本号 ##2.安装node.js淘宝镜像加速器 ### ...

  9. sql如何查询数据库最后10条记录并正序输出

    select * from (select * from 表名 order by 字段 desc limit 10) 临时表 order by 字段

  10. cassandra权威指南读书笔记--数据建模

    没有join操作.有轻量级事务和批处理,但是没有外键等.反规范化.3.0支持物化视图,允许在一个表上创建数据的多个物化视图.使用cassandra要从查询入手,而不是先从数据模型开始.先对查询建模,然 ...