27. Vòng đánh giá

Vòng đánh giá là công cụ thực thi trung tâm của CPython. Nó lấy một đối tượng mã được biên dịch, thực thi các lệnh mã byte của nó và tạo ra một kết quả hoặc một ngoại lệ.

Ở mức độ cao, quá trình thực thi CPython trông như thế này:```text Python source ↓ tokens ↓ parser ↓ AST ↓ symbol table ↓ compiler ↓ code object ↓ frame ↓ evaluation loop ↓ Python result or exception


Vòng lp đánh giá nm trong quá trình trin khai trình thông dch ca CPython. Trong lch s, tp tin chính đã được`Python/ceval.c`, vi máy thông dch xung quanh tri rng trên các tp khác. CPython hin đại cũng to ra mt s mã trình thông dch t các định nghĩa mã byte. Các chi tiết di chuyn gia các bn phát hành nhưng mô hình vn n định: mt khung thc thi mt đối tượng mã bng cách gi đi nhiu ln các lnh mã byte. Hướng dn dành cho nhà phát trin ca CPython ch ra tài liu ni b và cây ngun làm tài liu tham kho hin ti vì mã này thay đổi gia các phiên bn.

## 27.1 Công việc của vòng đánh giá

Vòng đánh giá không phân tích văn bn Python. Nó không xây dng AST. Nó thường không quyết định phm vi t vng. Nhng công vic đó đã được hoàn thành vào thi đim bt đầu thc hin.

Công vic ca nó hp hơn và máy móc hơn:```text
read the next bytecode instruction
decode its operand
perform the operation
update the frame
continue, jump, call, return, or raise
```Ví d: chc năng này:```python
def add(a, b):
    return a + b
```được biên dch thành mt đối tượng mã. Đối tượng mã cha mã byte. Khi`add(2, 3)`được gi, CPython to hoc khi to khung cho lnh gi đó, lưu tr các đối s trong các v trí cc b nhanh, sau đó chy khung đó qua vòng đánh giá.

Vòng lp cui cùng đạt ti lnh return. Lnh đó bt hoc đọc giá tr tr v, m khung và tr v con tr đối tượng cho người gi.

V mt khái nim:```text
call add(2, 3)
    create frame
    store a = 2
    store b = 3
    execute LOAD_FAST a
    execute LOAD_FAST b
    execute BINARY_OP +
    execute RETURN_VALUE
return 5
```Vic trin khai thc tế phc tp hơn nhưng đây là mô hình ct lõi.

## 27.2 Các đối tượng thời gian chạy chính

Vòng đánh giá kết ni mt s đối tượng thi gian chy CPython.

| Đối tượng thi gian chy | Vai trò |
|---|---|
| Đối tượng mã | Mã byte và siêu d liu được biên dch bt biến |
| Khung | Trng thái thc thi có th thay đổi cho mt cuc gi |
| Trng thái ch đề | Trng thái thc thi trình thông dch trên mi lung |
| Trng thái thông dch viên | Trng thái thi gian chy trên mi phiên dch viên |
| Đối tượng Python | Giá tr thi gian chy được thao tác theo hướng dn |
| Nhp đối tượng | Bng hành vi thi gian chy cho các đối tượng Python |

Mt đối tượng mã mô t nhng gì s chy.

Mt khung lưu tr mt ln thc thi đang hot động ca mã đó.

Vòng lp đánh giá thc thi khung.

S khác bit này quan trng. Mt đối tượng mã có th được thc thi nhiu ln. Mi cuc gi có trng thái khung riêng.```python
def f(x):
    return x + 1

a = f(10)
b = f(20)
```C hai cuc gi đều s dng cùng mt đối tượng mã, nhưng mi cuc gi có cc b, trng thái ngăn xếp và giá tr tr v riêng bit.

## 27.3 Đối tượng mã

Mt đối tượng mã cha biu din được biên dch ca mã Python.

Bn có th kim tra mt cái t Python:```python
def f(x):
    y = x + 1
    return y

code = f.__code__

print(code.co_name)
print(code.co_varnames)
print(code.co_consts)
print(code.co_names)
print(code.co_stacksize)
```Các lĩnh vc đin hình bao gm:

| Lĩnh vc | Ý nghĩa |
|---|---|
|`co_code`| Lung mã byte, được hin th  dng ph thuc vào phiên bn |
|`co_consts`| Các hng s theo nghĩa đen được mã s dng |
|`co_names`| Tên được tham chiếu theo mã byte |
|`co_varnames`| Tên biến cc b |
|`co_freevars`| Các biến min phí được ghi li t phm vi bên ngoài |
|`co_cellvars`| Các biến được nm bt bi phm vi bên trong |
|`co_argcount`| S đối s v trí |
|`co_kwonlyargcount`| S lượng đối s ch t khóa |
|`co_stacksize`| Kích thước ngăn xếp giá tr bt buc |
|`co_flags`| C mã |
|`co_filename`| Tên tp ngun |
|`co_name`| Tên hàm hoc khi |
|`co_qualname`| Tên đủ điu kin |
|`co_firstlineno`| Dòng ngun đầu tiên |
| bng dòng | Ánh x t độ lch mã byte sang dòng ngun |
| bng ngoi l | Siêu d liu x lý ngoi l có cu trúc |

các`dis`module tn ti đặc bit để kim tra mã byte CPython. Tài liu ca nó lưu ý rng mã byte CPython là mt chi tiết trin khai và có th thay đổi gia các phiên bn Python.

## 27.4 Khung hình

Mt khung là mt bn ghi thc thi.

Khi mt hàm chy, CPython cn mt nơi nào đó để lưu tr:```text
the code object being executed
the instruction pointer
local variables
temporary stack values
globals dictionary
builtins dictionary
closure cells
exception state
return state
tracing and profiling state
```Cu trúc đó là khung.

Mt mô hình khung đơn gin trông như thế này:```text
frame
    code object
    globals
    builtins
    locals / fast locals
    instruction pointer
    value stack
    block and exception state
    previous frame / caller relation
```Chui cuc gi Python to ra mt chui khung:```python
def a():
    return b()

def b():
    return c()

def c():
    return 42

a()
```V mt khái nim:```text
frame for a
    frame for b
        frame for c
```Ti bt k thi đim nào, trng thái lung hin ti s tr đến khung hin đang thc thi hoc biu din khung bên trong tương đương.

## 27.5 Người dân địa phương nhanh

Các biến cc b ca hàm thường không được lưu tr trong t đin thông thường trong quá trình thc thi.

CPython s dng b cc ging mng cho các biến cc b nhanh. Tên được phân gii ti thi đim biên dch thành ch mc cc b. Sau đó, các hướng dn mã byte có th truy cp các biến cc b theo ch mc thay vì thc hin tra cu t đin.

Ví d:```python
def f(a, b):
    c = a + b
    return c
```Trình biên dch gán các v trí cc b:

| Tên | Khe |
|---|---:|
|`a`| 0 |
|`b`| 1 |
|`c`| 2 |

Mã byte sau đó có th s dng các hot động da trên v trí:```text
LOAD_FAST 0     load a
LOAD_FAST 1     load b
BINARY_OP +
STORE_FAST 2    store c
LOAD_FAST 2     load c
RETURN_VALUE
```Đây là lý do ti sao truy cp biến cc b thường nhanh hơn truy cp biến toàn cc. Truy cp cc b có th s dng khe khung trc tiếp. Quyn truy cp toàn cu phi tìm kiếm t đin và x lý d phòng ni trang.

## 27.6 Ngăn xếp giá trị

Mã byte CPython s dng mô hình ngăn xếp.

Hu hết các hướng dn đọc và ghi vào ngăn xếp giá tr khung cc b. Ngăn xếp này tách bit vi ngăn xếp cuc gi C. Nó lưu tr`PyObject *`các giá tr trong quá trình thc thi mã byte.

Đối vi biu thc này:```python
x = (a + b) * c
```Hành vi ngăn xếp đại khái là:```text
LOAD_FAST a      stack: [a]
LOAD_FAST b      stack: [a, b]
BINARY_OP +      stack: [a_plus_b]
LOAD_FAST c      stack: [a_plus_b, c]
BINARY_OP *      stack: [product]
STORE_FAST x     stack: []
```Ngăn xếp giá tr là trung tâm ca thiết kế mã byte. Nó tránh vic cn mi hướng dn để đặt tên cho các thanh ghi ngun và đích rõ ràng. Thay vào đó, các hướng dn thng nht v hiu ng ngăn xếp.

Mt s hướng dn đẩy giá tr:```text
LOAD_CONST
LOAD_FAST
LOAD_GLOBAL
BUILD_LIST
```Mt s hướng dn bt giá tr:```text
STORE_FAST
POP_TOP
RETURN_VALUE
```Mt s làm c hai:```text
BINARY_OP
CALL
LOAD_ATTR
COMPARE_OP
```## 27.7 Con trỏ lệnh

Khung theo dõi nơi thc thi nm trong lung mã byte.

Đối vi mã đường thng, con tr lnh di chuyn v phía trước sau mi lnh.

Đối vi các nhánh, vòng lp, x lý ngoi l và tr v, lung điu khin thay đổi hướng dn.

Ví d:```python
def sign(x):
    if x < 0:
        return -1
    return 1
```Lung mã byte khái nim:```text
load x
load 0
compare <
jump if false to positive_return
load -1
return
positive_return:
load 1
return
```Con tr lnh là th giúp thc hin được điu này. Lnh r nhánh thay đổi lnh tiếp theo s được thc thi.

##27.8 Công văn

Gi đi là hành động chn cách trin khai C cho lnh mã byte hin ti.

Mt vòng lp thông dch được đơn gin hóa trông như thế này:```c
for (;;) {
    opcode = read_opcode(frame);
    oparg = read_operand(frame);

    switch (opcode) {
        case LOAD_FAST:
            /* load local variable */
            break;

        case LOAD_CONST:
            /* load constant */
            break;

        case BINARY_OP:
            /* perform binary operation */
            break;

        case RETURN_VALUE:
            /* return from frame */
            break;
    }
}
```Đây ch là mt mô hình ging dy. CPython hin đại s dng các k thut điu phi được ti ưu hóa và mã trình thông dch được to  nhiu nơi. Tuy nhiên, hình dng thiết yếu vn còn:```text
fetch
decode
dispatch
execute
repeat
```Vn đề chi phí gi hàng. Mi lnh mã byte Python đều đi qua công văn. Nếu mt vòng lp thc thi hàng triu lnh mã byte, chi phí điu phi s hin th.

## 27.9 Hiệu ứng ngăn xếp

Mi lnh bytecode đều có hiu ng ngăn xếp.

Hiu ng ngăn xếp mô t s lượng giá tr mà mt lnh tiêu th và to ra.

Ví d:

| Hướng dn | Ngăn xếp đầu vào | Ngăn xếp đầu ra |
|---|---|---|
|`LOAD_CONST` | `[]` | `[const]` |
| `LOAD_FAST` | `[]` | `[local]` |
| `STORE_FAST` | `[value]` | `[]` |
| `BINARY_OP` | `[left, right]` | `[result]` |
| `RETURN_VALUE` | `[value]`| tr v t khung |

Trình biên dch phi biết hiu ng ngăn xếp để tính toán kích thước ngăn xếp ti đa mà đối tượng mã yêu cu. Giá tr đó xut hin dưới dng`co_stacksize`.

Vì:```python
def f(a, b, c):
    return (a + b) * c
```Ngăn xếp không bao gi cn cha nhiu hơn hai hoc ba giá tr tm thi, tùy thuc vào mã byte chính xác. CPython ghi li độ sâu ngăn xếp cn thiết ti đa để khung có th dành đủ không gian.

## 27.10 Toán hạng mã byte

Nhiu lnh bytecode có toán hng.

Toán hng là mt đối s nguyên nh gn lin vi lnh. Ý nghĩa ph thuc vào opcode.

Ví d:```text
LOAD_CONST 0      load co_consts[0]
LOAD_FAST 1       load fast local slot 1
STORE_FAST 2      store into fast local slot 2
LOAD_GLOBAL 3     load name from name table index 3
```Lnh mã byte thường không lưu tr mt con tr đầy đủ ti tên đối tượng hoc chui. Nó lưu tr mt ch mc vào mt bng thuc s hu ca đối tượng mã.

Điu này gi cho mã byte nh gn và tách bit siêu d liu bt biến khi trng thái thc thi.

## 27.11 Chạy một hàm đơn giản

Hãy xem xét:```python
def add(a, b):
    return a + b
```Vic tháo g có th khác nhau tùy theo phiên bn Python, nhưng trình t hướng dn khái nim là:```text
load local a
load local b
binary add
return value
```Quá trình thc hin din ra như sau:

| Bước | Hướng dn | Xếp chng trước | Xếp chng sau |
|---:|---|---|---|
| 1 |`LOAD_FAST a` | `[]` | `[a]`|
| 2 |`LOAD_FAST b` | `[a]` | `[a, b]`|
| 3 |`BINARY_OP +` | `[a, b]` | `[a + b]`|
| 4 |`RETURN_VALUE` | `[a + b]`| tr li |

 cp độ C, mi phn t ngăn xếp là mt`PyObject *`.

Vì`add(2, 3)`, ngăn xếp cha các con tr ti các đối tượng s nguyên Python. Hot động b sung gi đi thông qua ng nghĩa đối tượng Python. Nó không trc tiếp phát ra phép cng s nguyên CPU trong trường hp chung.

## 27.12 Tại sao`a + b`Không chỉ là một lệnh CPU

Trong Python,`a + b`là năng động.

Các đối tượng có th là s nguyên:```python
1 + 2
```Chúng có th là chui:```python
"hello " + "world"
```Chúng có th là danh sách:```python
[1] + [2]
```Chúng có th là các đối tượng do người dùng định nghĩa:```python
class X:
    def __add__(self, other):
        return "custom"

X() + X()
```Hướng dn mã byte để b sung phi tôn trng mô hình d liu ca Python. Nó phi kim tra các loi toán hng, tìm phép toán s hoc chui chính xác, gi các phương thc đặc bit khi cn, x lý li và tr v mt đối tượng Python.

Vì vy vòng đánh giá không th x lý`+`như phép cng máy đơn gin. Đây là mt hot động động trên các đối tượng Python.

CPython hin đại gim chi phí này khi có th. Trình thông dch thích ng chuyên bit có th chuyên môn hóa các hot động sau khi quan sát hành vi thi gian chy n định. PEP 659 mô t đây là s chuyên môn hóa trên các khu vc nh vi kh năng thích ng nhanh chóng khi hành vi thay đổi.

## 27.13 Lệnh gọi hàm

Các lnh gi hàm là mt trong nhng đường dn quan trng nht trong vòng đánh giá.

Vì:```python
result = f(x, y)
```Người phiên dch phi:```text
load callable f
load arguments x and y
arrange call arguments
check callable type
enter optimized call path if possible
create or initialize callee frame if it is a Python function
execute callee frame
receive return value
continue caller frame
```V mt khái nim:```text
caller frame
    LOAD_FAST f
    LOAD_FAST x
    LOAD_FAST y
    CALL 2
        create callee frame
        run callee frame
        return object
    STORE_FAST result
```CPython đã dành n lc ti ưu hóa đáng k cho các cuc gi vì các cuc gi din ra thường xuyên và tn kém. Các cơ chế quan trng bao gm:```text
vectorcall
fast locals
specialized call bytecodes
inline caches
frame optimizations
reduced temporary tuple/dict creation
```Mc đích là để tránh vic đóng gói đối s không cn thiết. Trong lch s, nhiu lnh gi yêu cu xây dng b d liu và t đin cho các đối s. Đường dn cuc gi hin đại c gng truyn đối s theo b cc ging như mng khi có th.

## 27.14 Trở về từ một khung

Lnh quay li kết thúc khung hin ti.

Vì:```python
def f():
    return 42
```Lnh return to ra mt`PyObject *`kết qu và thư giãn khung.

Người gi nhn đối tượng đó là kết qu ca biu thc cuc gi:```python
x = f()
```V mt khái nim:```text
callee frame stack: [42]
RETURN_VALUE
    pop result
    finish callee frame
    give result to caller
caller resumes with stack: [42]
STORE_FAST x
```Mt khung có th kết thúc bng nhiu cách:

| Li thoát | Ý nghĩa |
|---|---|
| Li nhun bình thường | Hàm tr v mt giá tr |
| Ngoi l | Chc năng thoát bng cách raise |
| Năng sut máy phát đin | Khung tm dng và tiếp tc sau đó |
| Coroutine đang ch đợi | Coroutine tm dng |
| Li nghiêm trng | Li cp độ thi gian chy |

Vòng đánh giá phi x lý tt c các đường dn này.

## 27.15 Ngoại lệ

Các ngoi l là mt phn ca lung điu khin trình thông dch thông thường.

Vì:```python
def div(a, b):
    return a / b
```Nếu như`b`bng 0, phép chia tăng lên`ZeroDivisionError`.

Lnh bytecode không tr v kết qu bình thường. Thay vào đó, nó đặt trng thái ngoi l và chuyn điu khin sang logic x lý ngoi l.

V mt khái nim:```text
execute BINARY_OP /
    operation fails
    set current exception
    search exception table
    jump to handler or unwind frame
```CPython hin đại s dng các bng ngoi l có cu trúc được liên kết vi các đối tượng mã. Các bng này mô t các phm vi và trình x lý mã byte được bo v. Điu này cho phép trình thông dch tìm được trình x lý chính xác khi xy ra ngoi l.

Ví d:```python
try:
    x = 1 / y
except ZeroDivisionError:
    x = 0
```Vòng đánh giá phi biết phm vi được bo v  đâu, trình x lý bt đầu  đâu và trng thái ngăn xếp nào được yêu cu  trình x lý.

## 27.16 Vòng lặp và nhánh

Các vòng lp Python biên dch để nhy.

Ví d:```python
def count(n):
    i = 0
    while i < n:
        i += 1
    return i
```Hình dng mã byte khái nim:```text
i = 0

loop_start:
    load i
    load n
    compare <
    jump if false to loop_end

    load i
    load 1
    add
    store i

    jump to loop_start

loop_end:
    load i
    return
```Vòng lp đánh giá không có vòng lp while cp C đặc bit cho mi Python`while`. Nó thc thi các lnh mã byte để thc hin vòng lp.

Do đó, vòng lp Python là vòng lp trình thông dch bên trong vòng lp trình thông dch bên ngoài:```text
C evaluation loop
    executes Python loop bytecode
        jumps backward many times
```Đây là mt lý do khiến vòng lp Python cht ch có th đắt tin. Mi ln lp có th thc thi nhiu lnh mã byte và mi lnh mã byte có chi phí điu phi và đối tượng động.

## 27.17 Lặp lại

A`for`vòng lp s dng giao thc lp.

Ví d:```python
for item in xs:
    use(item)
```Thc hin khái nim:```text
iterator = iter(xs)

loop:
    item = next(iterator)
    if StopIteration:
        exit loop
    use(item)
    jump loop
```Vòng đánh giá thc hin các lnh gi`iter()`, gi thao tác tiếp theo ca iterator, x lý`StopIteration`, và nhánh.

Điu này có nghĩa là cp độ Python`for`các vòng lp da trên giao thc. Chúng hot động vi các danh sách, b d liu, ký t, tp, trình to, trình vòng lp tùy chnh và nhiu loi tin ích m rng vì trình thông dch gi đi thông qua các khe giao thc đối tượng.

## 27.18 Truy cập thuộc tính

Truy cp thuc tính cũng năng động.

Vì:```python
value = obj.name
```Trình thông dch phi trin khai các quy tc tra cu thuc tính ca Python:```text
look at object type
handle descriptors
look in instance dictionary if applicable
look in class dictionary and base classes
call custom __getattribute__ if present
fall back to __getattr__ if applicable
raise AttributeError if missing
```Mt biu hin trông đơn gin có th liên quan đến máy móc quan trng.

CPython hin đại s dng b đệm ni tuyến và chuyên môn hóa để tăng tc các mu truy cp thuc tính ph biến. Ví d: truy cp nhiu ln vào cùng mt thuc tính trên các đối tượng có hình dng n định có th tránh được mt s công vic tra cu lp li.

## 27.19 Tra cứu toàn cầu và tích hợp

Tra cu toàn cu đắt hơn tra cu cc b.

Vì:```python
print(len(xs))
```Nhng cái tên như`print`Và`len`không phi là biến cc b tr khi được gán cc b. CPython tra cu chúng thông qua các không gian tên toàn cc và dng sn.

V mt khái nim:```text
look in globals dictionary
if missing, look in builtins dictionary
if missing, raise NameError
```Đây là lý do ti sao liên kết cc b có th nhanh hơn trong các vòng lp cht ch:```python
def slow(xs):
    for x in xs:
        len(x)

def faster(xs):
    local_len = len
    for x in xs:
        local_len(x)
```CPython hin đại có th chuyên môn hóa vic tra cu toàn cu, do đó, vic ti ưu hóa vi mô cũ này ít hu ích hơn so vi trước đây. Tuy nhiên, đim khác bit cơ bn vn là: các v trí cc b đơn gin hơn vic tra cu tên da trên t đin.

## 27.20 GIL và Vòng đánh giá

Trong thi gian chy CPython truyn thng, vòng đánh giá chy trong khi lung hin ti gi Khóa phiên dch toàn cu.

GIL bo v trng thái trình thông dch, bao gm s lượng tham chiếu và nhiu ni dung bên trong đối tượng. Vòng lp đánh giá kim tra định k xem nó có nên loi b GIL, x lý tín hiu, x lý các cuc gi đang ch x lý hay cho phép mt lung khác chy hay không.

Điu này có nghĩa là vic thc thi mã byte là hp tác  cp độ trình thông dch. Mt thread thường không gi GIL mãi mãi. CPython có các lch trình kim tra cho phép chuyn đổi gia các lung.

H qu thc tế:```text
one thread executes Python bytecode at a time per traditional interpreter
I/O operations may release the GIL
C extensions may release the GIL around long native work
CPU-bound Python threads do not normally execute bytecode in parallel
```Công vic CPython mi hơn bao gm các bn dng theo lung t do và các thay đổi trên mi trình thông dch, nhưng vòng đánh giá vn là v trí trung tâm nơi gp nhau trng thái lung, công vic đang ch x lý và thc thi mã byte.

## 27,21 Số lượng tham chiếu trong quá trình thực thi

Mi giá tr trên ngăn xếp là mt con tr đối tượng Python có quy tc s hu.

Vòng đánh giá phi duy trì cn thn s lượng tham chiếu. Khi mt lnh đẩy mt giá tr, lưu tr mt giá tr, thay thế mt giá tr hoc loi b mt giá tr, nó phi duy trì tui th ca đối tượng mt cách chính xác.

Ví d:```python
x = a + b
```V mt khái nim:```text
load a        obtain reference to object a
load b        obtain reference to object b
add           produce new reference to result
store x       bind result to local slot
discard temporaries
```Qun lý tham chiếu không chính xác có th gây rò r hoc phá hy sm.

 cp độ C, điu này có nghĩa là các hot động được sp xếp cn thn tương đương vi:```c
Py_INCREF(obj);
Py_DECREF(obj);
```Vic trin khai chính xác thường s dng các macro chuyên dng và quy ước v quyn s hu. Nhưng tính bt biến rt đơn gin: mt đối tượng phi tn ti trong khi nó vn có th được s dng và nó phi được gii phóng khi trình thông dch không còn s hu mt tham chiếu na.

## 27.22 Báo lỗi

Hu hết các hàm tr giúp C trong CPython đều s dng quy ước chung:```text
return a valid pointer or success code on success
return NULL or error code on failure
set an exception on failure
```Vòng đánh giá kim tra các kết qu này.

Ví d đơn gin:```c
PyObject *result = PyNumber_Add(left, right);
if (result == NULL) {
    goto error;
}
```các`NULL`return không t nó mô t ngoi l. Ngoi l được lưu tr  trng thái lung.

Mu này xut hin  khp mi nơi:```text
call helper
if failed:
    go to error path
else:
    push or store result
```Vòng lp đánh giá cha nhiu li thoát ra vì hu hết mi thao tác Python đều có th tht bi:```text
allocation can fail
attribute lookup can fail
function call can fail
comparison can fail
iteration can fail
import can fail
descriptor code can fail
user-defined special method can fail
```## 27.23 Cuộc gọi đang chờ xử lý, tín hiệu và sự kiện không đồng bộ

Vòng đánh giá cũng hot động như mt đim kim tra an toàn cho công vic  cp độ thi gian chy.

CPython không th x lý mi tín hiu hoc s kin đang ch x lý  ranh gii lnh C tùy ý. Thay vào đó, nó ghi li rng có điu gì đó cn được chú ý và kim tra ti các đim được kim soát trong quá trình đánh giá.

Ví d:```text
signal handling
pending calls from C APIs
thread switching requests
async exception injection
tracing and profiling hooks
monitoring hooks
interrupt checks
```Điu này giúp cho trình thông dch có th qun lý được. Vòng đánh giá tr thành nơi thc thi Python thông báo các s kin bên ngoài.

## 27.24 Truy tìm và lập hồ sơ

Python h tr theo dõi và lp h sơ thông qua các API như:```python
sys.settrace(...)
sys.setprofile(...)
```Nhng cái móc này yêu cu s hp tác t vòng đánh giá.

Vòng lp phi phát ra các s kin như:```text
call
line
return
exception
opcode, when enabled
```Vic theo dõi khiến vic thc thi chm hơn vì nó thêm các lnh kim tra và gi li. Nhưng nó cho phép trình g li, công c bao quát, trình lp h sơ, công c ging dy và h thng quan sát.

Trình g li thc hin các bước thông qua mã Python ph thuc vào kh năng ca vòng đánh giá trong vic ánh x thc thi mã byte tr li dòng ngun.

## 27.25 Phiên dịch thích ứng chuyên dụng

K t Python 3.11, CPython đã bao gm mt trình thông dch thích ng chuyên dng da trên PEP 659. Ý tưởng là gi cho ng nghĩa Python luôn năng động trong khi thc hin các trường hp n định ph biến nhanh hơn. PEP 659 mô t vic chuyên môn hóa mang tính tích cc trên các vùng nh, có kh năng thích ng khi mô hình thi gian chy thay đổi.

Trình thông dch bt đầu vi mã byte chung. Khi mã chy, CPython quan sát hành vi và có th thay thế hoc tăng cường các hot động chung bng các biu mu chuyên bit.

Ví d: mt phép toán nh phân chung có th được ti ưu hóa cho các loi toán hng ph biến:```text
generic BINARY_OP
    observed int + int repeatedly
        
specialized integer-add path
```Để truy cp thuc tính:```text
generic LOAD_ATTR
    observed same attribute layout repeatedly
        
cached attribute access path
```Để tra cu toàn cu:```text
generic LOAD_GLOBAL
    observed stable globals and builtins dictionaries
        
cached global lookup path
```Chuyên môn hóa phi luôn chính xác. Nếu gi định không thành công, trình thông dch s lùi li hoc điu chnh.

Điu này không ging vi trình biên dch JIT đầy đủ truyn thng. Nó vn hot động bên trong kiến ​​trúc trình thông dch. Nó chuyên hóa các đường dn thc thi  cp mã byte thay vì biên dch toàn b hàm thành mã máy gc trong trường hp chung.

## 27,26 Bộ nhớ đệm nội tuyến

B đệm ni tuyến là nhng phn lưu tr b đệm nh được liên kết vi các hướng dn mã byte.

Thay vì tính toán li thông tin tra cu mi ln, trình thông dch lưu tr các s kin gn hướng dn cn chúng.

Thông tin b nh đệm mu có th bao gm:```text
type version
dictionary version
attribute offset
resolved descriptor
global dictionary version
builtin dictionary version
specialized call target
```Mt mô hình b đệm thuc tính đơn gin hóa:```text
LOAD_ATTR name
    cache:
        expected type = User
        type version = 123
        attribute offset = 2
```Trong ln thc hin tiếp theo, CPython có th kim tra xem đối tượng có còn khp vi các gi định được lưu trong b nh đệm hay không. Nếu có, nó s dng đường dn nhanh. Nếu không, nó s quay tr li đường dn chung.

B nh đệm ni tuyến hot động tt vì các hướng dn mã byte ti mt v trí ngun nht định thường lp đi lp li các loi đối tượng ging nhau.

## 27.27 Tại sao chuyên môn lại an toàn

Python rt năng động nên tính chuyên môn hóa phi được bo v.

Mt đường dn chuyên bit ch hp l khi các gi định ca nó vn đúng.

Ví d:```python
obj.x
```có th được chuyên môn hóa nếu CPython quan sát b cc đối tượng n định. Nhưng Python cho phép đột biến:```python
obj.__dict__["x"] = 10
type(obj).x = property(...)
obj.__class__ = OtherType
```Vì vy CPython s dng th phiên bn, b bo v, b đếm và đường dn d phòng.

Quy tc an toàn là:```text
use fast path only if guards prove assumptions still hold
otherwise use generic Python semantics
```Đây là chiến lược rng rãi tương t được nhiu thi gian chy ngôn ng động s dng, nhưng CPython gi cho b máy tương đối gn vi trình thông dch mã byte.

## 27.28 Mã thông dịch được tạo

CPython hin đại không coi mi trin khai mã byte là các trường hp chuyn đổi viết tay trong mt tp.

Các b phn ca trình thông dch được to ra t các định nghĩa hướng dn. Điu này giúp gi cho siêu d liu mã byte, hiu ng ngăn xếp, thông tin chuyên môn và mã điu phi nht quán hơn.

Ý tưởng rng:```text
instruction definitions
    
generated opcode metadata
    
generated dispatch support
    
interpreter execution
```Đối vi người đọc, điu này có nghĩa là ngun gc ca s tht không phi lúc nào cũng ch là tp C được to cui cùng. Bn thường cn kim tra các tp định nghĩa lnh, các tiêu đề được to và kết qu đầu ra ca bn dng.

Các tp chính xác và quy trình to có th thay đổi trên các bn phát hành CPython, vì vy hãy s dng cây ngun cho phiên bn bn đang nghiên cu.

## 27.29 Vòng đánh giá và lệnh gọi C

Vòng đánh giá thường xuyên gi các hàm tr giúp C.

Ví d:```text
PyNumber_Add
PyObject_GetAttr
PyObject_SetAttr
PyObject_Call
PyDict_GetItem
PyObject_RichCompare
PyIter_Next
```Nhng người tr giúp này có th gi mã Python do người dùng xác định.

Ví d:```python
a + b
```có th gi:```python
a.__add__(b)
```Và:```python
obj.name
```có th gi:```python
obj.__getattribute__("name")
```Vì vy, vòng đánh giá có th nhp li vic thc thi Python mt cách gián tiếp. Lnh mã byte có th gi mã tr giúp C, mã này có th gi mã Python, to ra mt khung khác, bt đầu thc hin vòng lp đánh giá khác.

V mt khái nim:```text
frame A
    executes BINARY_OP
        calls C helper
            calls user __add__
                frame B
                    evaluation loop
```Mô hình thc thi đệ quy này là trung tâm ca tính linh hot ca Python.

## 27.30 Đệ quy và Độ sâu cuộc gọi

Python bo v chng li s đệ quy không kim soát được.

Ví d:```python
def f():
    return f()

f()
```Mi cuc gi s to mt khung Python khác. CPython theo dõi độ sâu đệ quy và tăng`RecursionError`khi vượt quá gii hn được cu hình.

Vòng đánh giá và máy gi phi hp tác vi vic kim tra này. Nếu không có nó, mã Python đệ quy có th làm cn kit ngăn xếp C hoc x lý b nh.

Bn có th kim tra và điu chnh gii hn:```python
import sys

print(sys.getrecursionlimit())
sys.setrecursionlimit(2000)
```Vic nâng gii hn đệ quy cn được thc hin cn thn. Gii hn Python tn ti mt phn để bo v tài nguyên thi gian chy cp thp hơn.

## 27.31 Máy phát điện

Máy phát đin thay đổi vòng đời ca khung.

Lnh gi hàm bình thường s chy cho đến khi nó tr v hoc tăng lên. Mt máy phát đin có th tm dng và tiếp tc.

Ví d:```python
def gen():
    yield 1
    yield 2
```Đang gi`gen()`không ngay lp tc chy phn thân hàm để hoàn thành. Nó to ra mt đối tượng trình to s hu khung treo hoc trng thái thc thi tương đương.

Mi`next()`tiếp tc thc hin:```text
first next()
    enter frame
    run until yield 1
    suspend frame

second next()
    resume frame
    run until yield 2
    suspend frame

third next()
    resume frame
    finish function
    raise StopIteration
```Vòng đánh giá phi h tr vic tm dng. Nó không th đơn gin phá hy khung hình `yield`.

## 27.32 Coroutine và chờ đợi

Coroutines m rng mô hình h thng treo tương t.

Ví d:```python
async def fetch():
    data = await read()
    return data
```MT`await`có th tm dng coroutine cho đến khi mt chương trình có th ch đợi khác hoàn thành.

Vòng đánh giá phi h tr:```text
coroutine frame creation
suspension at await
resumption with value
resumption with exception
final return
cancellation behavior
```Do đó, vic thc thi không đồng b không phi là mt trình thông dch riêng bit. Nó được xây dng trên cùng mt khung và máy móc mã byte, vi các hướng dn và giao thc c th để tm dng và tiếp tc.

## 27.33 Thân lớp và Thân mô-đun

Vòng đánh giá không ch thc hin các chc năng.

Nó cũng thc thi các thân mô-đun và thân lp.

Mt tp tin mô-đun:```python
x = 1

def f():
    return x
```được biên dch thành mt đối tượng mã cp mô-đun. Vic nhp hoc chy mô-đun s thc thi đối tượng mã đó.

Mt câu lnh lp cũng thc thi mã:```python
class C:
    x = 1

    def method(self):
        return self.x
```Thân lp chy trong mt không gian tên được chun b cho vic xây dng lp. Sau khi thc thi, CPython xây dng đối tượng lp t không gian tên đó.

Vì vy, vòng đánh giá thc hin mt s loi khi:

| Loi khi | Ví d |
|---|---|
| Mô-đun |`.py`ni dung tp tin |
| Chc năng |`def f(): ...`|
| Lp cơ th |`class C: ...`|
| Lambda |`lambda x: x + 1`|
| Hiu |`[x * 2 for x in xs]`|
| Máy phát đin |`(x for x in xs)`|
| Coroutine |`async def f(): ...`|

## 27.34 Hiểu biết

S hiu biết biên dch thành các đối tượng mã ca riêng chúng trong nhiu trường hp.

Ví d:```python
ys = [x * 2 for x in xs if x > 0]
```V mt khái nim:```text
create list
iterate xs
for each x:
    if x > 0:
        append x * 2
return list
```Điu này có nghĩa là quá trình hiu thường chy qua mt khung lng nhau hoc đường dn thc thi ni b chuyên bit. Chúng có hành vi phm vi cc b ca riêng mình, đó là lý do ti sao các biến vòng lp bên trong kh năng hiu danh sách không rò r vào phm vi xung quanh trong Python 3.

Vòng đánh giá coi vic thc thi hiu là thc thi mã byte, không phi là mt dng cú pháp đặc bit.

## 27.35 Thực thi nhập khẩu

Vic nhp cui cùng cũng thc thi mã byte.

Khi Python nhp mt`.py`mô-đun, h thng nhp s tìm mô-đun, đọc mã ngun hoc mã byte được lưu trong b nh đệm, to đối tượng mô-đun, sau đó thc thi đối tượng mã mô-đun.

V mt khái nim:```text
import module
    find spec
    create module object
    compile or load code object
    execute code object in module namespace
```Do đó, vòng đánh giá s tham gia vào quá trình nhp khu. Nhp mô-đun có nghĩa là chy mã.

Đây là lý do ti sao tác dng ph ti thi đim nhp khu xy ra:```python
# module.py
print("imported")
import module
```Bản in chạy  việc thực thi phần thân -đun  việc thực thi  thông thường.

## 27.36 Mẫu hiệu suất

Vòng đánh giá giải thích phần lớn hiệu năng của Python.

Một hoạt động Python thường  nhiều lớp chi phí:```text
bytecode dispatch
stack manipulation
reference count updates
dynamic type checks
dictionary lookup
descriptor protocol
function call overhead
allocation
error checks
``` dụ:```python
obj.x + y
``` thể yêu cầu:```text
LOAD_FAST obj
LOAD_ATTR x
LOAD_FAST y
BINARY_OP +
```Mỗi hướng dẫn đều  chi phí thông dịch viên.`LOAD_ATTR` thể liên quan đến việc tra cứu  tả.`BINARY_OP` thể liên quan đến việc gửi số. Số lượng tham chiếu phải được duy trì. Các lỗi phải được kiểm tra.

Đây   do tại sao việc di chuyển các vòng lặp nóng vào phần mở rộng C, thư viện được vector hóa hoặc các hoạt động tích hợp  thể nhanh hơn nhiều. Chúng làm giảm số lượng lệnh  byte  các công văn động được thực thi bởi vòng đánh giá.

## 27.37 Tích hợp sẵn dưới dạng các cửa thoát vòng lặp đánh giá

Các hoạt động tích hợp  thể thực hiện một lượng lớn công việc dưới mức  byte.

 dụ:```python
sum(xs)
```Vòng lặp đánh giá thực hiện lệnh gọi tới`sum`, nhưng các phần tử lặp lại  thể chạy trong C bên trong quá trình triển khai tích hợp sẵn.

So sánh:```python
total = 0
for x in xs:
    total += x
```Điều này đòi hỏi nhiều hướng dẫn  byte cho mỗi lần lặp.

Tính năng tích hợp sẵn  thể giảm chi phí cho trình thông dịch  phần lớn công việc lặp lại diễn ra trong C.

Đây  nguyên tắc hiệu suất phổ biến của Python:```text
fewer Python bytecode instructions in hot paths usually means better performance
```## 27.38 Kiểm tra vòng đánh giá từ Python

Bạn  thể nghiên cứu  byte với`dis`:

```python
import dis

def f(a, b):
    c = a + b
    return c

dis.dis(f)
```Bạn  thể kiểm tra khung:```python
import inspect

def f():
    frame = inspect.currentframe()
    print(frame.f_code.co_name)
    print(frame.f_locals)

f()
```Bạn  thể kiểm tra độ sâu cuộc gọi:```python
import sys

def f(n):
    frame = sys._getframe()
    print(n, frame.f_code.co_name)
    if n:
        f(n - 1)

f(3)
```Bạn  thể theo dõi việc thực hiện:```python
import sys

def trace(frame, event, arg):
    print(event, frame.f_code.co_name, frame.f_lineno)
    return trace

def f(x):
    y = x + 1
    return y

sys.settrace(trace)
f(10)
sys.settrace(None)
```Những công cụ này thể hiện một phần của máy móc  vòng đánh giá duy trì nội bộ.

## 27.39 Vòng đánh giá được đơn giản hóa

Phiên bản giảng dạy của vòng lặp  thể trông như thế này:```c
PyObject *
eval_frame(Frame *frame)
{
    for (;;) {
        Instruction instr = next_instruction(frame);

        switch (instr.opcode) {
            case OP_LOAD_CONST: {
                PyObject *value = frame->code->consts[instr.arg];
                push(frame, value);
                break;
            }

            case OP_LOAD_FAST: {
                PyObject *value = frame->locals[instr.arg];
                if (value == NULL) {
                    raise_unbound_local_error();
                    goto error;
                }
                push(frame, value);
                break;
            }

            case OP_STORE_FAST: {
                PyObject *value = pop(frame);
                frame->locals[instr.arg] = value;
                break;
            }

            case OP_BINARY_ADD: {
                PyObject *right = pop(frame);
                PyObject *left = pop(frame);
                PyObject *result = PyNumber_Add(left, right);
                if (result == NULL) {
                    goto error;
                }
                push(frame, result);
                break;
            }

            case OP_RETURN_VALUE: {
                PyObject *result = pop(frame);
                return result;
            }
        }
    }

error:
    return NULL;
}
```Điều này bỏ qua hầu hết các chi tiết thực tế:```text
reference ownership
specialization
inline caches
exception tables
tracing
profiling
GIL checks
pending calls
signals
generators
coroutines
debug builds
statistics
opcode prediction
deoptimization
frame materialization
```Nhưng  nắm bắt được ý tưởng thiết yếu.

## 27.40 Những hiểu lầm phổ biến

| Hiểu lầm | Đúng mẫu |
|---|---|
| CPython thực thi văn bản nguồn trực tiếp | CPython thực thi các đối tượng  đã biên dịch |
| Biến Python lưu trữ giá trị thô | Tên  vị trí giữ tham chiếu đến đối tượng |
| Bytecode ổn định trên các phiên bản | Bytecode  chi tiết triển khai CPython |
|`a + b` phép cộng máy đơn giản | Đó  công văn giao thức đối tượng động, trừ khi |
| Một khung chỉ  một đối tượng truy nguyên | Một khung đang  trạng thái thực thi tích cực |
| GIL chỉ ảnh hưởng đến chủ đề của người dùng |  được kết nối sâu sắc với việc thực thi trình thông dịch  an toàn đối tượng |
| Ngoại lệ chỉ  những lối đi phụ hiếm hoi | Các ngoại lệ được tích hợp vào bộ máy điều khiển luồng thông thường |
| Máy phát điện chỉ  chức năng đặc biệt | Chúng  các khung thực thi  thể tiếp tục hoặc trạng thái tương đương |

## 27.41 Đọc Nguồn Thực

Khi đọc nguồn CPython thực, hãy sử dụng thứ tự này:

1. Bắt đầu với`dis`đầu ra cho một hàm Python nhỏ.
2. Xác định các hướng dẫn  byte.
3. Tìm định nghĩa opcode tương ứng.
4. Tìm cách triển khai trình thông dịch được tạo hoặc viết tay.
5. Thực hiện theo các lệnh gọi trợ giúp cho các hoạt động của đối tượng.
6. Theo dõi quyền sở hữu tài liệu tham khảo.
7. Theo dõi hiệu ứng ngăn xếp.
8. Theo dõi đường dẫn lỗi.
9. Kiểm tra tính chuyên môn hóa  hoạt động của bộ nhớ đệm.
10. So sánh hành vi giữa các phiên bản Python.

Một chức năng nghiên cứu tốt :```python
def example(obj, xs):
    total = 0
    for x in xs:
        total += obj.value + x
    return total
```Hàm này chạm vào nhiều đường dẫn thông dịch:```text
local variable access
loop iteration
attribute lookup
binary operation
in-place update semantics
jump instructions
return
```Tháo rời , sau đó ánh xạ từng hướng dẫn tới máy thông dịch.

## 27.42 Tóm tắt chương

Vòng đánh giá  nơi  Python được biên dịch trở thành hành vi Python đang chạy.  thực thi các đối tượng  thông qua các khung, sử dụng  hình  byte dựa trên ngăn xếp, gửi hướng dẫn, duy trì các tham chiếu, xử  các ngoại lệ, gọi hàm, kiểm tra các sự kiện thời gian chạy  áp dụng chuyên môn hóa khi  thể.

Vòng lặp  ý nghĩa nhỏ nhưng hậu quả lại lớn.  nằm  điểm giao nhau của gần như mọi hệ thống con CPython:```text
compiler
frames
objects
types
reference counting
garbage collection
exceptions
calls
imports
generators
coroutines
tracing
profiling
threading
optimization
```Để hiểu CPython, bạn phải hiểu vòng đánh giá. Đó  cái máy bên trong cái máy.