【AICon】探索八个行业创新案例,教你在教育、金融、医疗、法律等领域实践大模型技术! >>> 了解详情
写点什么

加载速度提升 15%,关于 Python 启动加速探索与实践的解析

  • 2022-12-27
    北京
  • 本文字数:1474 字

    阅读完需:约 5 分钟

加载速度提升 15%,关于 Python 启动加速探索与实践的解析

在 PyCon China 2022 大会上,龙蜥社区开发者严懿宸分享了主题为《Python 启动加速的探索与实践》的技术演讲。本次演讲,作者将从 CPython 社区相关工作、本方案的设计及实现,以及业务层面的集成等方面进行介绍。本文为本次演讲内容整理。

一、Python 启动速度简析


首先从一个 Python 3 中空解释器启动时间的好事分析开始。我们可以看到,主要的耗时都和 Python 包加载有关。



其中,CPU 时间中包加载占据了 30% 左右的时间;而 37% 的等待时间中,磁盘 IO 等花费的时间也和包加载有较大的关联。


熟悉 Python 机制的朋友大概知道,Python 中加载一个包首先会搜索对应的 pyc 文件,这是一种序列化的字节码格式。找到之后会对其进行反序列化,并执行其中的代码。如对应的 pyc 文件不存在,会重新编译 py 文件得到字节码,并序列化为 pyc 文件持久化保存。我们优化的主要目标主要集中在加载包这个过程,希望能够至少免去每次查找、读取、反序列化的开销。



Python3.10 为例,这里是使用 python 解释器启动一个空语句的所需时间,同时使用了 -Ximporttime 打印出过程中加载每一个包的耗时。可以粗略地看到,包加载时间大约占了总时间的 30% 左右。我们发现这种情况和 Java 虚拟机类似。在 Java 中,Java 会首先将 Java 源代码编译为 Java 字节码,随后由 Java 命令执行。


我们知道 Java 的优势并不包括启动速度,这种流程也是原因之一。那么 Java 如何部分解决这个问题呢?

二、PyCDS (代码对象共享)设计与实现



Java 中有一个叫做 CDS/AppCDS 的机制,通过将 Java 字节码和一些辅助数据持久化保存,在后续启动时使用 mmap 加载,节约了磁盘 IO 和解析验证 class 文件的开销。


很自然的想法是,如果我们希望在 Python 中使用类似的技术,目标应该是 Python 字节码



Python 默认从 py 文件导入模块的逻辑如上图左边所示,首先根据制定的名字获取对应的规则,随后尝试寻找 pyc 文件或重新编译。最后,使用 exec 命令利用代码和一个空 dict 来创建模块,并加入 runtime。


我们做的事情可以简化为右侧逻辑。同样根据包名,尝试从 mmap 中加载。如果成功,那么同样的 codeobject 也可以用于初始化。


这样做有什么直接的障碍?


可以看到,Python 中代码对象的 C 数据结构大致如图,包括 consts、string、bytes 等 Python 数据类型。



以使用到的 codeobject 作为 root,将涉及的数据序列化存储到内存映射中。


在这一步,最直接的问题是内存随机化机制。在处理 code object 中的 Python 对象时,每个 Python 对象头中都保存着指向当前进程中对应类型信息的指针。Runtime 通过这个指针判断该对象在 Python 中的类型。


以 PyCode_Type 为例,如果不做处理,这里会丢失类型信息(红色 offset)。


为了解决这个问题,在我们创建的镜像文件中会保存涉及的对象指针。在加载时动态 patch 相关的指针。


在整个过程中涉及的 Python 类型包括


1. 常量(bool/None/ellipsis)

2. 字面量(float/complex)

3. 需要额外分配的变量(long/bytes/str)

4. container(tuple/frozenset)


对于常量和字面量,在内存映射中分配好空间后直接赋值即可保存;对于后两种,需要模拟 Python 中变量初始化的逻辑,创建合适的内存大小并写入对应位置。同时,对于非常量的类型,还需要对内存映射中的引用计数额外赋值,防止意外触发 Python 中的回收。


以上就是本项目的大致内容,另外关于项目的具体用法请前往 PyCDS 项目主页或我们在龙蜥实验室上的课程查看,链接见下:

龙蜥实验室课程:

https://lab.openanolis.cn/#/apply/chapters?courseId=117

 PyCDS 主页:

https://github.com/alibaba/code-data-share-for-python

2022-12-27 18:253491

评论

发布
暂无评论
发现更多内容

数据库性能优化入门:数据库分片初探

PingCAP

数据库 TiDB

Linux常用命令cupsdisable命令

百度搜索:蓝易云

云计算 Linux 运维 云服务器 cupsdisable

Linux网卡与IP地址:通往网络世界的通行证 🌐

GousterCloud

IP Linux Kenel 网卡

IP地址:是给主机配置的,还是给网卡配置的?🤔

GousterCloud

IP Linux Kenel

2024-04-06:用go语言,给你两个非负整数数组 rowSum 和 colSum, 其中 rowSum[i] 是二维矩阵中第 i 行元素的和, colSum[j] 是第 j 列元素的和,换言之你

福大大架构师每日一题

福大大架构师每日一题

Paste Mac破解版下载 苹果电脑首选剪切板历史管理工具

Rose

AnyGo for mac中文破解版,轻松修改手机定位,畅游应用无界限

Rose

mac ppt破解版下载 PowerPoint 2019 mac中文永久版

Rose

TiDB 社区智慧合集丨解码 TiDB 性能谜题:让你的数据库发挥最强动力!

PingCAP

数据库 TiDB

Consensus Cash or A Gift Card?

EchoZhou

Expression English

产品设计案例

执于业务

CAD快速看图 VIP激活版 CAD快速看图破解版 mac/win

Rose

mnova14怎么安装?核磁数据处理MestReNova 14详细图文下载安装教程 Mac/win

Rose

remote desktop mac破解版下载 微软远程连接工具中文版

Rose

常态化降本增效,陌陌生产服务成本治理实践

童子龙

降本增效 基础架构 FinOps

阿里巴巴中国站按图搜索1688商品(拍立淘) API:如何通过图片快速获取商品的标题、价格、图片、链接,提高了更加智能化、个性化的商品搜索体验

技术冰糖葫芦

api 网关 API 文档 API 类型

MySQL的Json类型个人用法详解

百度搜索:蓝易云

json MySQL Linux 运维 云服务器

VMware ESXi 7.0 U3p macOS Unlocker & OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版)

sysin

macos esxi 驱动 OEM unlocker

事业-最佳实践-编码-编码规范

南山

数据库设计 代码规范 接口设计 检查清单 编码规范

Proxifier:网络代理神器,轻松突破访问限制

Rose

Python面试必备一之迭代器、生成器、浅拷贝、深拷贝

Hunter熊

Python 迭代器 深拷贝 浅拷贝 生成器

在云上使用过哪些外网暴露服务,简单说一下优缺点(nginx-ingress,treafik,云alb,云loadblance)

百度搜索:蓝易云

nginx Linux 运维 云服务器 loadbalance

vue组件开发中props和data之间的区别

百度搜索:蓝易云

Linux 运维 Vue 云服务器 props

《剑指Offer(专项突破版):数据结构与算法名企面试题精讲》PDF

程序员李木子

VMware ESXi 7.0 U3p macOS Unlocker & OEM BIOS 标准版和厂商定制版

sysin

esxi OEM unlocker dell hpe

PR 2024破解版下载 Premiere Pro 2024v24.3.0中文直装版 Mac/win

Rose

anytoiso pro mac中文破解版 专业级ISO镜像文件制作工具

Rose

支付系统概述(四):收单系统

agnostic

支付系统设计与实现

Invalid bound statement (not found) 报错

百度搜索:蓝易云

sql Linux 运维 mybatis 云服务器

SYN攻击是什么,该怎么防御syn攻击

德迅云安全杨德俊

如何注册midjourney账号

蓉蓉

MidJourney

加载速度提升 15%,关于 Python 启动加速探索与实践的解析_文化 & 方法_严懿宸_InfoQ精选文章