Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Что внутри у Питона: как работает интерпретатор

Что внутри у Питона: как работает интерпретатор

Злата Обуховская (Nvidia) @ Moscow Python Meetup 60

"Это первая из трёх лекций в цикле «Внутренности Питона». Мы разберёмся, как устроен Питон, посмотрим на этапы работы интерпретатора, построение деревьев разбора и генерацию байткода, а также выясним, какое пространство для оптимизаций нам это дает.

Если хотите больше знать про язык, на котором пишете, то приходите. Если уже все знаете, всё равно приходите".

Видео: http://www.moscowpython.ru/meetup/60/inside-python1/

Moscow Python Meetup
PRO

September 21, 2018
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Что внутри у питона
    Как работает интерпретатор
    Злата Обуховская

    View Slide

  2. Зачем понимать, как работает питон?

    View Slide

  3. View Slide

  4. Зачем понимать, как работает питон?
    ● повседневные прикладные задачи зачастую не повышают уровень
    инженерных навыков:
    ○ проектирование архитектуры
    ○ выбор подходящих для задачи технологий
    ○ решение задачи оптимальным по трудозатратам способом
    ● хорошие инженерные навыки помогают выполнять работу качественнее
    и быстрее
    ● понимание внутренностей питона — один из способов повысить свой
    уровень

    View Slide

  5. View Slide

  6. Часть 1: Компиляция

    View Slide

  7. Спойлер
    Компиляция в CPython устроена почти, как в учебнике Ахо Ульмана

    View Slide

  8. View Slide

  9. Типичный компилятор

    View Slide

  10. Типичный CPython

    View Slide

  11. Как интерпретируется 1.py

    View Slide

  12. Инициализация
    1. pymain_main — точка входа
    2. _Py_InitializeCore инициализует:
    ● interpreter state
    ● thread state
    ● GIL
    ● подгружает sys
    ● подгружает builtins
    3. PyRun_FileExFlags выделяет память, компилирует и интерпретирует

    View Slide

  13. Разбор кода
    PyParser_ParseFileObject:
    ● инициализует токенайзер
    ● разбивает файл на токены
    ● использует LL-грамматику, определенную в Parser/Python.asdl
    ● строит дерево разбора (parse tree)

    View Slide

  14. Грамматика

    View Slide

  15. Дерево разбора 1.py

    View Slide

  16. Дерево разбора a = 0

    View Slide

  17. Дерево разбора
    ● это список всех цепочек вывода для распаршенных токенов
    ● для работы с деревьями вывода есть модуль parser
    ● идентификаторы токенов можно найти в модулях symbol и token

    View Slide

  18. AST 1.py

    View Slide

  19. AST a = 0

    View Slide

  20. Abstract Syntax Tree
    ● строится в PyAST_FromNodeObject
    ● представляет программу в независимом от синтаксиса виде
    ● может использоваться для оптимизаций программы
    ● для работы с синтаксическими деревьями есть модуль ast

    View Slide

  21. Control Flow Graph и генерация байткода
    Генерация происходит в PyAST_CompileObject:
    ● код разделяется на блоки
    ● определяются области видимости переменных (global, local, builtins)
    ● строится таблица символов
    ● строится CFG
    ● обходится граф
    ● для каждого узла CFG генерится байткод и производятся оптимизации

    View Slide

  22. Узел Control Flow Graph для блока кода

    View Slide

  23. Блок кода с инструкциями

    View Slide

  24. Инструкции корневого блока 1.py

    View Slide

  25. Инструкции блока функции f

    View Slide

  26. Результатом компиляции является code object

    View Slide

  27. Репрезентация code object в питоне

    View Slide

  28. Этап компиляции
    Переводит код в code object

    View Slide

  29. Часть 2: Интерпретация

    View Slide

  30. Интерпретация байткода
    Code object попадает в _PyEval_EvalCodeWithName:
    ● инициализуется фрейм для выполнения кода
    ● инициализует параметры вызова функции, переменные замыканий
    ● вызывает _PyEval_EvalFrameDefault
    ● попадает в цикл с огромным свитчем

    View Slide

  31. Великий свитч ceval.c

    View Slide

  32. Байткод 1.py

    View Slide

  33. Фреймы

    View Slide

  34. Фреймы

    View Slide

  35. CALL_FUNCTION

    View Slide

  36. CALL_FUNCTION

    View Slide

  37. Много разных стейтов

    View Slide

  38. Этап интерпретации
    Выполняет инструкции в фрейме в стеке в стейте треда
    Переключает треды
    И кое-что еще

    View Slide

  39. Часть 3. Кое-что об оптимизациях

    View Slide

  40. Куда засунуть оптимизации?

    View Slide

  41. Генерация байткода: peephole optimizer
    имплементирован в Python/peephole.c
    ● удаляет ненужные инструкции
    ● оптимизирует jump-инструкции
    ● арифметические оптимизации

    View Slide

  42. AST оптимизации в CPython
    можно сделать:
    ● вычисление констант
    ● copy propagation
    ● dead code elimination
    ● разворачивание циклов
    ● builtins в константы
    нужны проверки изменения переменных

    View Slide

  43. Когда в CPython будет JIT?
    ● никогда

    View Slide

  44. Откуда так много питонов?
    ● CPython
    ● Stackless (свои микротреды)
    ● Unladen swallow (все на llvm)
    ● PyPy (RPython)
    ● IronPython (генерят байткод для Mono)
    ● Numba (подмножество питона, llvm, есть JIT)
    ТЫСЯЧИ ИХ!

    View Slide

  45. Выводы
    ● CPython позволяет добиться тотальной мутабельности
    ● Скорость выполнения при этом теряется
    ● Оптимизации возможны за счет переписывания виртуальной машины
    ● Можно оптимизировать процесс исполнения инструкций в vm
    ● А можно вводить оптимизации из теории компиляторов

    View Slide

  46. View Slide