Day 098 - Python 内部机制 - 图解
1. Python 执行模型
┌──────────────────────────────────────────────────────┐
│ Python 执行流程 │
├──────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 源代码 │───→│ 编译器 │───→│ 字节码 │ │
│ │ (.py) │ │ (Parser) │ │ (.pyc) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────┐ │
│ │ CPython PVM │ │
│ │ 虚拟机执行 │ │
│ └──────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────┐ │
│ │ 执行结果 │ │
│ └──────────────┘ │
└──────────────────────────────────────────────────────┘
2. 栈帧(Frame)结构
┌─────────────────────────────────────────┐
│ Frame Object │
├─────────────────────────────────────────┤
│ f_code → Code Object │
│ f_back → 上一级 Frame │
│ f_locals → 局部变量字典 │
│ f_lineno → 当前行号 │
│ f_lasti → 最后执行指令偏移 │
│ f_valuestack → 值栈 │
│ f_blockstack → 块栈 │
└─────────────────────────────────────────┘
调用栈示例:
┌──────────────┐
│ main() │ ← 最外层
├──────────────┤
│ func_a() │ ← 调用 func_a
├──────────────┤
│ func_b() │ ← 调用 func_b
├──────────────┤
│ func_c() │ ← 当前执行
└──────────────┘
3. Code Object 结构
┌─────────────────────────────────────────┐
│ Code Object │
├─────────────────────────────────────────┤
│ co_code → 字节码指令 │
│ co_consts → 常量池 │
│ co_varnames → 局部变量名 │
│ co_names → 全局/属性名 │
│ co_stacksize → 栈大小 │
│ co_argcount → 参数个数 │
│ co_nlocals → 局部变量数 │
│ co_flags → 标志位 │
│ co_filename → 源文件名 │
│ co_firstlineno → 第一行行号 │
└─────────────────────────────────────────┘
4. 值栈(Value Stack)执行模型
表达式: x = 3 + 4 * 5
指令 栈状态 说明
────────────────────────────────────────────
LOAD_CONST 3 [3] 加载 3
LOAD_CONST 4 [3, 4] 加载 4
LOAD_CONST 5 [3, 4, 5] 加载 5
BINARY_MULTIPLY [3, 20] 4 * 5 = 20
BINARY_ADD [23] 3 + 20 = 23
STORE_FAST x [] x = 23
5. PyObject 内存布局
┌─────────────────────────────┐
│ PyObject │
├─────────────────────────────┤
│ ob_refcnt (8 bytes) │ ← 引用计数
│ ob_type (8 bytes) │ ← 类型指针
├─────────────────────────────┤
│ 对象数据 │ ← 类型特定数据
└─────────────────────────────┘
int 类型示例:
┌─────────────────────────────┐
│ PyObject │
├─────────────────────────────┤
│ ob_refcnt (8 bytes) │
│ ob_type → int type │
├─────────────────────────────┤
│ ob_digit (4 bytes) │ ← 整数值
└─────────────────────────────┘
6. 引用计数机制
a = [1, 2, 3]
引用计数变化:
────────────────────────────────────────
操作 引用计数
────────────────────────────────────────
a = [1, 2, 3] 1 (创建)
b = a 2 (赋值)
c = a 3 (赋值)
del b 2 (删除)
c.clear() 1 (容器移除)
del a 0 (销毁)
7. 分代垃圾回收
┌─────────────────────────────────────────┐
│ Generational GC │
├─────────────────────────────────────────┤
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐
│ │ Gen 0 │ │ Gen 1 │ │ Gen 2 │
│ │ 新对象 │ │ 存活一次 │ │ 长期存活 │
│ │ 频繁回收 │ │ 较少回收 │ │ 很少回收 │
│ └───────────┘ └───────────┘ └───────────┘
│ │
│ 新对象 → Gen 0 → 存活 → Gen 1 → 存活 → Gen 2
└─────────────────────────────────────────┘
8. 三级内存分配器
┌─────────────────────────────────────────┐
│ 第三层: pymalloc │
│ (管理 < 512 字节的小对象) │
├─────────────────────────────────────────┤
│ 第二层: pymalloc raw │
│ (管理 512B ~ 1MB 的分配) │
├─────────────────────────────────────────┤
│ 第一层: malloc/free │
│ (管理 > 1MB 的大分配) │
└─────────────────────────────────────────┘
pymalloc 内存池:
┌─────────────────────────────────────────┐
│ Arena (256 KB) │
│ ├── Pool 1 (4 KB) │
│ │ ├── Block 8B × N │
│ │ ├── Block 16B × N │
│ │ ├── Block 32B × N │
│ │ └── Block 64B × N │
│ ├── Pool 2 (4 KB) │
│ └── ... │
└─────────────────────────────────────────┘
9. CPython 3.11+ 自适应解释器
┌─────────────────────────────────────────┐
│ Adaptive Interpreter │
├─────────────────────────────────────────┤
│ │
│ 字节码 ──→ 普通执行 ──→ 热点检测 │
│ ↓ │
│ 特化 (Specialize) │
│ ↓ │
│ 特化指令执行 │
│ (更快的版本) │
└─────────────────────────────────────────┘
特化指令示例:
原指令 特化指令
──────────────────────────────────────
LOAD_ATTR → LOAD_ATTR_INSTANCE_VALUE
BINARY_OP → BINARY_OP_ADD_INT
CALL → CALL_PY_EXACT_ARGS
10. 字节码指令执行流程
if-else 语句的字节码结构:
源码:
if x > 0:
return "正数"
else:
return "负数"
字节码流程:
┌─────────────────────────────────────────┐
│ LOAD_FAST x │
│ LOAD_CONST 0 │
│ COMPARE_OP > │
│ POP_JUMP_IF_FALSE ──────────────┐ │
│ LOAD_CONST "正数" │ │
│ RETURN_VALUE │ │
│ ┌──────┘ │
│ ↓ │
│ LOAD_CONST "负数" │
│ RETURN_VALUE │
└─────────────────────────────────────────┘
11. for 循环的字节码结构
源码:
for item in lst:
total += item
字节码流程:
┌─────────────────────────────────────────┐
│ GET_ITER ← 获取迭代器 │
│ ↓ │
│ >> FOR_ITER ──────────────────┐ │
│ ↓ │ │
│ STORE_FAST item │ │
│ ↓ │ │
│ [循环体: total += item] │ │
│ ↓ │ │
│ JUMP_ABSOLUTE ────────────────┘ │
│ ↓ (迭代结束) │
│ [循环后代码] │
└─────────────────────────────────────────┘