← 返回 Day 98 正文

Day 98 · 图解

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 ────────────────┘        │
│        ↓ (迭代结束)                      │
│  [循环后代码]                            │
└─────────────────────────────────────────┘