SlideShare a Scribd company logo
Оптимизация
производительности Python
Александр Маршалов / _@marshalov.org
1 / 216
О чём мы будем говорить?
2 / 216
Мы не будем говорить:
3 / 216
Мы не будем говорить:
Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…)
4 / 216
Мы не будем говорить:
Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…)
О распараллеливании алгоритмов
5 / 216
Мы не будем говорить:
Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…)
О распараллеливании алгоритмов
О переписывании кода на другие языки *
* при этом мы все же немного поговорим о генерации кода на других языках на основе python-
кода
6 / 216
Мы не будем говорить:
Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…)
О распараллеливании алгоритмов
О переписывании кода на другие языки *
Об объективности и правильности приводимых в докладе тестов
* при этом мы все же немного поговорим о генерации кода на других языках на основе python-
кода
7 / 216
Мы не будем говорить:
Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…)
О распараллеливании алгоритмов
О переписывании кода на другие языки *
Об объективности и правильности приводимых в докладе тестов
О том, что всё, о чем вы услышите, нужно применять с умом
* при этом мы все же немного поговорим о генерации кода на других языках на основе python-
кода
8 / 216
Часть 1
Микрооптимизации
9 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
10 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
Модуль dis
11 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
Модуль dis
Использование:
>>> from dis import dis
>>> dis("sec_in_week = 604800")
1 0 LOAD_CONST 6 (604800)
3 STORE_NAME 0 (sec_in_week)
6 LOAD_CONST 3 (None)
9 RETURN_VALUE
12 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
Модуль dis
Использование:
>>> from dis import dis
>>> dis("sec_in_week = 604800")
1 0 LOAD_CONST 6 (604800)
3 STORE_NAME 0 (sec_in_week)
6 LOAD_CONST 3 (None)
9 RETURN_VALUE
Подробнее: docs.python.org/3/library/dis.html
13 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
x = 1
y = 2
Модуль dis
Пример. Мы хотим узнать, какая конструкция выполняется быстрее:
x, y = 1, 2
14 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
x = 1
y = 2
LOAD_CONST ((1, 2))
UNPACK_SEQUENCE 2
STORE_NAME (x)
STORE_NAME (y)
LOAD_CONST (None)
RETURN_VALUE
LOAD_CONST (1)
STORE_NAME (x)
LOAD_CONST (2)
STORE_NAME (y)
LOAD_CONST (None)
RETURN_VALUE
Модуль dis
Пример. Мы хотим узнать, какая конструкция выполняется быстрее:
x, y = 1, 2
15 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
x = 1
y = 2
LOAD_CONST ((1, 2))
UNPACK_SEQUENCE 2
STORE_NAME (x)
STORE_NAME (y)
LOAD_CONST (None)
RETURN_VALUE
LOAD_CONST (1)
STORE_NAME (x)
LOAD_CONST (2)
STORE_NAME (y)
LOAD_CONST (None)
RETURN_VALUE
Модуль dis
Пример. Мы хотим узнать, какая конструкция выполняется быстрее:
Видно, что байт-код отличается на две конструкции, в первом
случае - загрузка кортежа в стек и распаковка в стек, во втором -
две загрузки целых чисел в стек.
x, y = 1, 2
16 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
x = 1
y = 2
LOAD_CONST ((1, 2))
UNPACK_SEQUENCE 2
STORE_NAME (x)
STORE_NAME (y)
LOAD_CONST (None)
RETURN_VALUE
LOAD_CONST (1)
STORE_NAME (x)
LOAD_CONST (2)
STORE_NAME (y)
LOAD_CONST (None)
RETURN_VALUE
Модуль dis
Пример. Мы хотим узнать, какая конструкция выполняется быстрее:
Интуитивно понятно, что загрузка кортежа в стек медленней
загрузки числа в стек, и распаковка кортежа в стек медленней
загрузки одного значения в стек.
x, y = 1, 2
17 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
x = 1
y = 2
LOAD_CONST ((1, 2))
UNPACK_SEQUENCE 2
STORE_NAME (x)
STORE_NAME (y)
LOAD_CONST (None)
RETURN_VALUE
LOAD_CONST (1)
STORE_NAME (x)
LOAD_CONST (2)
STORE_NAME (y)
LOAD_CONST (None)
RETURN_VALUE
Модуль dis
Пример. Мы хотим узнать, какая конструкция выполняется быстрее:
Поэтому видно, что второй код быстрее первого. Но, если не видно,
то есть timeit.
x, y = 1, 2
18 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
Модуль timeit
19 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
Модуль timeit
Использование (в REPL или в python-коде):
>>> from timeit import timeit
>>>
>>> timeit("x, y = 1, 2", number=100000000)
3.349976803001482
>>>
>>> timeit("x = 1; y = 1", number=100000000)
3.125208465033211
20 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
Модуль timeit
Использование (в ipython):
In [1]: %timeit a, b, c, d = 1, 2, 3, 4
10000000 loops, best of 3: 45.1 ns per loop
In [2]: %timeit a = 1; b = 2; c = 3; d = 4
10000000 loops, best of 3: 47.7 ns per loop
In [3]:
21 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
Модуль timeit
Использование (в режиме командной строки):
$ python3 -m timeit -n 1000000 -r 100 "x = 1; y = 2; z = 3"
1000000 loops, best of 100: 0.0385 usec per loop
$
$ python3 -m timeit -n 1000000 -r 100 "x, y, z = 1, 2, 3"
1000000 loops, best of 100: 0.0388 usec per loop
22 / 216
1. Микро-
оптимизации
- Инструменты
Инструменты, используемые при
микрооптимизациях
Модуль timeit
Использование (в режиме командной строки):
$ python3 -m timeit -n 1000000 -r 100 "x = 1; y = 2; z = 3"
1000000 loops, best of 100: 0.0385 usec per loop
$
$ python3 -m timeit -n 1000000 -r 100 "x, y, z = 1, 2, 3"
1000000 loops, best of 100: 0.0388 usec per loop
Подробнее: docs.python.org/3/library/timeit.html
23 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
1. Замена умножения сложением
24 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
1. Замена умножения сложением
>>> # int
>>> from timeit import timeit
>>>
>>> timeit("x = x * 2", setup="x = 2")
21.935253892996116
>>> timeit("x = x + x", setup="x = 2")
18.347866550000617
25 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
1. Замена умножения сложением
>>> # int
>>> from timeit import timeit
>>>
>>> timeit("x = x * 2", setup="x = 2")
21.935253892996116
>>> timeit("x = x + x", setup="x = 2")
18.347866550000617
>>> # float
>>> from timeit import timeit
>>>
>>> timeit("x = x * 2", setup="x = 3.14", number=100000000)
8.331406126002548
>>> timeit("x = x + x", setup="x = 3.14", number=100000000)
4.393627463025041
26 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
1. Замена умножения сложением
>>> # int
>>> from timeit import timeit
>>>
>>> timeit("x = x * 2", setup="x = 2")
21.935253892996116
>>> timeit("x = x + x", setup="x = 2")
18.347866550000617
>>> # float
>>> from timeit import timeit
>>>
>>> timeit("x = x * 2", setup="x = 3.14", number=100000000)
8.331406126002548
>>> timeit("x = x + x", setup="x = 3.14", number=100000000)
4.393627463025041
Сравнение:
x * 2 x + x приростприрост
int 21.94 18.35 16.5%
float 8.33 4.39 47.3%
27 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
2. Замена возведения в степень
умножением
28 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
2. Замена возведения в степень
умножением
>>> # int
>>> timeit("x = x ** 2", setup="x = 2", number=30)
8.314083544013556
>>> timeit("x = x * x", setup="x = 2", number=30)
7.056395357009023
29 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
2. Замена возведения в степень
умножением
>>> # int
>>> timeit("x = x ** 2", setup="x = 2", number=30)
8.314083544013556
>>> timeit("x = x * x", setup="x = 2", number=30)
7.056395357009023
>>> # float
>>> timeit("x = x ** 2", setup="x = 0.5", number=100000000)
5.864706993103027
>>> timeit("x = x * x", setup="x = 0.5", number=100000000)
3.877152919769287
30 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
2. Замена возведения в степень
умножением
>>> # int
>>> timeit("x = x ** 2", setup="x = 2", number=30)
8.314083544013556
>>> timeit("x = x * x", setup="x = 2", number=30)
7.056395357009023
>>> # float
>>> timeit("x = x ** 2", setup="x = 0.5", number=100000000)
5.864706993103027
>>> timeit("x = x * x", setup="x = 0.5", number=100000000)
3.877152919769287
Сравнение:
x ** 2 x * x приростприрост
int 8.31 7.06 15.0%
float 5.86 3.88 33.8%
31 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
3. Замена "константных переменных" их
значениями (литералами).
32 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
3. Замена "константных переменных" их
значениями (литералами).
Иначе говоря, популярная оптимизация под названием constant
propagation ("протяжка" констант).
33 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
3. Замена "константных переменных" их
значениями (литералами).
«Модифицируй это!» или «Больше магии Python с
помощью изменения AST»
vk.com/wall-96469126_1029
34 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
35 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
In [1]: x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
In [2]: y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
In [3]: %timeit z = (x == y)
10000000 loops, best of 3: 85.3 ns per loop
In [4]: %timeit z = (x == y)
10000000 loops, best of 3: 85.1 ns per loop
In [5]: # ???
In [6]: # ???
In [7]: # ???
In [8]: %timeit z = (x == y)
10000000 loops, best of 3: 57.3 ns per loop
In [9]: %timeit z = (x == y)
10000000 loops, best of 3: 57.4 ns per loop
36 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
In [1]: x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
In [2]: y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
In [3]: %timeit z = (x == y)
10000000 loops, best of 3: 85.3 ns per loop
In [4]: %timeit z = (x == y)
10000000 loops, best of 3: 85.1 ns per loop
In [5]: import sys
In [6]: x = sys.intern(x)
In [7]: y = sys.intern(y)
In [8]: %timeit z = (x == y)
10000000 loops, best of 3: 57.3 ns per loop
In [9]: %timeit z = (x == y)
10000000 loops, best of 3: 57.4 ns per loop
37 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
>>> x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
>>> y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
>>>
>>> x == y, x is y
(True, False)
>>> id(x), id(y)
(4376204752, 4376204848)
38 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
>>> x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
>>> y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
>>>
>>> x == y, x is y
(True, False)
>>> id(x), id(y)
(4376204752, 4376204848)
>>>
>>> from sys import intern
>>> x, y = intern(x), intern(y)
39 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
>>> x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
>>> y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_"""
>>>
>>> x == y, x is y
(True, False)
>>> id(x), id(y)
(4376204752, 4376204848)
>>>
>>> from sys import intern
>>> x, y = intern(x), intern(y)
>>>
>>> x == y, x is y
(True, True)
>>> id(x), id(y)
(4376204752, 4376204752)
40 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
41 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
Интернирование делает строки синглтонами, то есть для
каждой уникальной строки существует только один
экземпляр.
42 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
Интернирование делает строки синглтонами, то есть для
каждой уникальной строки существует только один
экземпляр.
Происходит автоматически для односимвольных строк.
43 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
Интернирование делает строки синглтонами, то есть для
каждой уникальной строки существует только один
экземпляр.
Происходит автоматически для односимвольных строк.
Происходит автоматически для идентификаторов.
44 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
Интернирование делает строки синглтонами, то есть для
каждой уникальной строки существует только один
экземпляр.
Происходит автоматически для односимвольных строк.
Происходит автоматически для идентификаторов.
Аналогичный механизм используется для чисел от -5 до 256,
эти числа также являются синглтонами.
45 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
Интернирование делает строки синглтонами, то есть для
каждой уникальной строки существует только один
экземпляр.
Происходит автоматически для односимвольных строк.
Происходит автоматически для идентификаторов.
Аналогичный механизм используется для чисел от -5 до 256,
эти числа также являются синглтонами.
В качестве операторов сравнения интернированных строк
можно использовать is и is not, что даст прирост скорости
сравнения.
46 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
The internals of Python string interning
guilload.com/python-string-interning/
47 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
4. "Интернирование" строк / string
interning.
Python string objects implementation
www.laurentluce.com/posts/python-string-objects-implementation/
48 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
5. "Диспатчинг" вместо каскадов условий /
dispatching
49 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
5. "Диспатчинг" вместо каскадов условий /
dispatching
Компенсируем отсутствие case использованием словарей.
50 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
5. "Диспатчинг" вместо каскадов условий /
dispatching
Компенсируем отсутствие case использованием словарей.
Рассмотрим пример:
r = 0
for i in range(10000000):
x = i % 10
if x == 0: pass
elif x == 1: r = r + 1
elif x == 2: r = r + 2
elif x == 3: r = r + 3
elif x == 4: r = r + 4
elif x == 5: r = r + 5
elif x == 6: r = r + 6
elif x == 7: r = r + 7
elif x == 8: r = r + 8
elif x == 9: r = r + 9
51 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
5. "Диспатчинг" вместо каскадов условий /
dispatching
Компенсируем отсутствие case использованием словарей.
Рассмотрим пример:
r = 0
for i in range(10000000):
x = i % 10
if x == 0: pass
elif x == 1: r = r + 1
elif x == 2: r = r + 2
elif x == 3: r = r + 3
elif x == 4: r = r + 4
elif x == 5: r = r + 5
elif x == 6: r = r + 6
elif x == 7: r = r + 7
elif x == 8: r = r + 8
elif x == 9: r = r + 9
Время выполнения: 4.513951063156128
52 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
5. "Диспатчинг" вместо каскадов условий /
dispatching
Теперь пробуем сделать то же самое с помощью словаря.
53 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
5. "Диспатчинг" вместо каскадов условий /
dispatching
Теперь пробуем сделать то же самое с помощью словаря.
dispatch_table = { 0: lambda r: r
, 1: lambda r: r + 1
, 2: lambda r: r + 2
, 3: lambda r: r + 3
, 4: lambda r: r + 4
, 5: lambda r: r + 5
, 6: lambda r: r + 6
, 7: lambda r: r + 7
, 8: lambda r: r + 8
, 9: lambda r: r + 9
}
r = 0
for i in range(10000000):
r = dispatch_table[i % 10](r)
54 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
5. "Диспатчинг" вместо каскадов условий /
dispatching
Теперь пробуем сделать то же самое с помощью словаря.
dispatch_table = { 0: lambda r: r
, 1: lambda r: r + 1
, 2: lambda r: r + 2
, 3: lambda r: r + 3
, 4: lambda r: r + 4
, 5: lambda r: r + 5
, 6: lambda r: r + 6
, 7: lambda r: r + 7
, 8: lambda r: r + 8
, 9: lambda r: r + 9
}
r = 0
for i in range(10000000):
r = dispatch_table[i % 10](r)
Время выполнения: 3.8208770751953125.
55 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
5. "Диспатчинг" вместо каскадов условий /
dispatching
Теперь пробуем сделать то же самое с помощью словаря.
dispatch_table = { 0: lambda r: r
, 1: lambda r: r + 1
, 2: lambda r: r + 2
, 3: lambda r: r + 3
, 4: lambda r: r + 4
, 5: lambda r: r + 5
, 6: lambda r: r + 6
, 7: lambda r: r + 7
, 8: lambda r: r + 8
, 9: lambda r: r + 9
}
r = 0
for i in range(10000000):
r = dispatch_table[i % 10](r)
Время выполнения: 3.8208770751953125.
Таким образом время выполнения снизилось на 15%.
56 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
6. Приведение типов
57 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
6. Приведение типов
>>> from timeit import timeit
>>>
>>> timeit("a = (x >= 3.14)", setup="x = 10", number=100000000)
>>> 8.488232829986373
58 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
6. Приведение типов
>>> from timeit import timeit
>>>
>>> timeit("a = (x >= 3.14)", setup="x = 10", number=100000000)
>>> 8.488232829986373
>>>
>>> timeit("a = (x >= 3.14)", setup="x = 10.0", number=100000000)
>>> 4.145244649000233
59 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
6. Приведение типов
>>> from timeit import timeit
>>>
>>> timeit("a = (x >= 3.14)", setup="x = 10", number=100000000)
>>> 8.488232829986373
>>>
>>> timeit("a = (x >= 3.14)", setup="x = 10.0", number=100000000)
>>> 4.145244649000233
Прирост скорости 51%.
60 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
7. Форматирование строк
In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590"
In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243"
In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50"
In [4]:
61 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
7. Форматирование строк
In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590"
In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243"
In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50"
In [4]:
In [5]: %timeit "." + x + ".." + y + "..." + z + "...."
1000000 loops, best of 3: 453 ns per loop
In [6]:
62 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
7. Форматирование строк
In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590"
In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243"
In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50"
In [4]:
In [5]: %timeit "." + x + ".." + y + "..." + z + "...."
1000000 loops, best of 3: 453 ns per loop
In [6]:
In [7]: %timeit ".{}..{}...{}....".format(x, y, z)
1000000 loops, best of 3: 615 ns per loop
In [8]:
63 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
7. Форматирование строк
In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590"
In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243"
In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50"
In [4]:
In [5]: %timeit "." + x + ".." + y + "..." + z + "...."
1000000 loops, best of 3: 453 ns per loop
In [6]:
In [7]: %timeit ".{}..{}...{}....".format(x, y, z)
1000000 loops, best of 3: 615 ns per loop
In [8]:
In [9]: %timeit "".join((".", x, "..", y, "...", z, "...."))
1000000 loops, best of 3: 287 ns per loop
In [10]:
64 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
7. Форматирование строк
In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590"
In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243"
In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50"
In [4]:
In [5]: %timeit "." + x + ".." + y + "..." + z + "...."
1000000 loops, best of 3: 453 ns per loop
In [6]:
In [7]: %timeit ".{}..{}...{}....".format(x, y, z)
1000000 loops, best of 3: 615 ns per loop
In [8]:
In [9]: %timeit "".join((".", x, "..", y, "...", z, "...."))
1000000 loops, best of 3: 287 ns per loop
In [10]: # ???
65 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
7. Форматирование строк
In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590"
In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243"
In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50"
In [4]:
In [5]: %timeit "." + x + ".." + y + "..." + z + "...."
1000000 loops, best of 3: 453 ns per loop
In [6]:
In [7]: %timeit ".{}..{}...{}....".format(x, y, z)
1000000 loops, best of 3: 615 ns per loop
In [8]:
In [9]: %timeit "".join((".", x, "..", y, "...", z, "...."))
1000000 loops, best of 3: 287 ns per loop
In [10]:
In [11]: %timeit ".{0}..{1}...{2}....".format(x, y, z)
1000000 loops, best of 3: 204 ns per loop
66 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
if x in [1, 2, 3]:
x += 41 + 1
if x in (1, 2, 3):
x += 42
8. Peephole-оптимизация
Какой код выполняется быстрее?
67 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
if x in [1, 2, 3]:
x += 41 + 1
if x in (1, 2, 3):
x += 42
LOAD_NAME (x)
LOAD_CONST ((1, 2, 3))
COMPARE_OP (in)
POP_JUMP_IF_FALSE 25
LOAD_NAME (x)
LOAD_CONST (42)
INPLACE_ADD
STORE_NAME (x)
JUMP_FORWARD (to 25)
LOAD_CONST (None)
RETURN_VALUE
LOAD_NAME (x)
LOAD_CONST ((1, 2, 3))
COMPARE_OP (in)
POP_JUMP_IF_FALSE 25
LOAD_NAME (x)
LOAD_CONST (42)
INPLACE_ADD
STORE_NAME (x)
JUMP_FORWARD (to 25)
LOAD_CONST (None)
RETURN_VALUE
8. Peephole-оптимизация
Какой код выполняется быстрее?
Воспользуемся модулем dis:
68 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
if x in [1, 2, 3]:
x += 41 + 1
if x in (1, 2, 3):
x += 42
LOAD_NAME (x)
LOAD_CONST ((1, 2, 3))
COMPARE_OP (in)
POP_JUMP_IF_FALSE 25
LOAD_NAME (x)
LOAD_CONST (42)
INPLACE_ADD
STORE_NAME (x)
JUMP_FORWARD (to 25)
LOAD_CONST (None)
RETURN_VALUE
LOAD_NAME (x)
LOAD_CONST ((1, 2, 3))
COMPARE_OP (in)
POP_JUMP_IF_FALSE 25
LOAD_NAME (x)
LOAD_CONST (42)
INPLACE_ADD
STORE_NAME (x)
JUMP_FORWARD (to 25)
LOAD_CONST (None)
RETURN_VALUE
8. Peephole-оптимизация
Какой код выполняется быстрее?
Воспользуемся модулем dis:
Байт-код полностью совпадает.
69 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
x = ( 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3 )
8. Peephole-оптимизация
Какой код выполняется быстрее?
x = (1, 2, 3) * 6
.
.
70 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
x = ( 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3 )
8. Peephole-оптимизация
Какой код выполняется быстрее?
LOAD_CONST (( 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
))
STORE_NAME (x)
LOAD_CONST (None)
RETURN_VALUE
LOAD_CONST (( 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
))
STORE_NAME (x)
LOAD_CONST (None)
RETURN_VALUE
x = (1, 2, 3) * 6
.
.
71 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
x = ( 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3 )
8. Peephole-оптимизация
Какой код выполняется быстрее?
LOAD_CONST (( 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
))
STORE_NAME (x)
LOAD_CONST (None)
RETURN_VALUE
LOAD_CONST (( 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
, 1, 2, 3
))
STORE_NAME (x)
LOAD_CONST (None)
RETURN_VALUE
Байт-код снова полностью совпадает.
x = (1, 2, 3) * 6
.
.
72 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
x = ( 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3 )
8. Peephole-оптимизация
Какой код выполняется быстрее?
x = (1, 2, 3) * 7
.
.
.
73 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
x = ( 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3 )
8. Peephole-оптимизация
Какой код выполняется быстрее?
x = (1, 2, 3) * 10 # ???
x = (1, 2, 3) * 7
.
.
.
74 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
x = ( 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3 )
8. Peephole-оптимизация
Какой код выполняется быстрее?
x = (1, 2, 3) * 10 # ???
x = (1, 2, 3) * 100 # ???
x = (1, 2, 3) * 7
.
.
.
75 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
x = ( 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3, 1, 2, 3
, 1, 2, 3 )
8. Peephole-оптимизация
Какой код выполняется быстрее?
x = (1, 2, 3) * 10 # ???
x = (1, 2, 3) * 100 # ???
x = (1, 2, 3) * 1000000 # ???
x = (1, 2, 3) * 7
.
.
.
76 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
sec_in_week = 7 * 24 * 60 * 60 sec_in_week = 604800
8. Peephole-оптимизация
Вы должны понимать, что оптимизации вроде
бесполезны, так как компилятор делает их сам.
77 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
- Другие
микрооптимизации
Примеры других микрооптимизаций
78 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
- Другие
микрооптимизации
Примеры других микрооптимизаций
for i in my_list:
yield i
yield from my_list
79 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
- Другие
микрооптимизации
Примеры других микрооптимизаций
for i in my_list:
yield i
func(1)
func(2)
func(3)
yield from my_list
for i in (1, 2, 3):
func(i)
.
80 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
- Другие
микрооптимизации
Примеры других микрооптимизаций
for i in my_list:
yield i
func(1)
func(2)
func(3)
x if x else y x or y
yield from my_list
for i in (1, 2, 3):
func(i)
.
81 / 216
1. Микро-
оптимизации
- Инструменты
- Замена умножения
сложением
- Замена возведения в
степень умножением
- "Протяжка" констант
- "Интернирование" строк
- "Диспатчинг"
- Приведение типов
- Форматирование строк
- Peephole
- Другие
микрооптимизации
Примеры других микрооптимизаций
for i in my_list:
yield i
func(1)
func(2)
func(3)
x if x else y x or y
x == None
y != None
x is None
y is not None
yield from my_list
for i in (1, 2, 3):
func(i)
.
82 / 216
Часть 2
Оптимизации
83 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
Для начала рассмотрим пример, который будем
модифицировать.
84 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
Для начала рассмотрим пример, который будем
модифицировать.
class Test(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def calc(self, p):
return (self.x + self.y * p) / self.z
85 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
Для начала рассмотрим пример, который будем
модифицировать.
class Test(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
for i in range(10000000):
result += test.calc(i)
86 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
Для начала рассмотрим пример, который будем
модифицировать.
class Test(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
for i in range(10000000):
result += test.calc(i)
87 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
Для начала рассмотрим пример, который будем
модифицировать.
class Test(object):
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
for i in range(10000000):
result += test.calc(i)
88 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
Для начала рассмотрим пример, который будем
модифицировать.
class Test(object):
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
for i in range(10000000):
result += test.calc(i)
Время выполнения данного кода: 5.3768229484558105
89 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
1. Слоты
90 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
1. Слоты
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
for i in range(10000000):
result += test.calc(i)
91 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
1. Слоты
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
for i in range(10000000):
result += test.calc(i)
Время выполнения данного кода: 4.434956073760986
92 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
1. Слоты
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
for i in range(10000000):
result += test.calc(i)
Время выполнения данного кода: 4.434956073760986
Прирост производительности относительно изначального варианта:
17.5%
93 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
1. Слоты
class Test(object):
__slots__ = "x", "y", "z", "__dict__"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
for i in range(10000000):
result += test.calc(i)
Время выполнения данного кода: 4.434956073760986
Прирост производительности относительно изначального варианта:
17.5%
94 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
2. Устраняем поиск метода (lookup)
95 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
2. Устраняем поиск метода (lookup)
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
calc = test.calc
for i in range(10000000):
result += calc(i)
96 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
2. Устраняем поиск метода (lookup)
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
calc = test.calc
for i in range(10000000):
result += calc(i)
Время выполнения: 4.027298927307129
97 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
2. Устраняем поиск метода (lookup)
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
calc = test.calc
for i in range(10000000):
result += calc(i)
Время выполнения: 4.027298927307129
Прирост производительности:
относительно предыдущего варианта: 9.2%
98 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
2. Устраняем поиск метода (lookup)
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
result = 0
test = Test(123, 456, 789)
calc = test.calc
for i in range(10000000):
result += calc(i)
Время выполнения: 4.027298927307129
Прирост производительности:
относительно предыдущего варианта: 9.2%
относительно изначального варианта: 25.1%
99 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
3. Избавляемся от глобальных переменных
100 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
3. Избавляемся от глобальных переменных
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
def run():
result = 0
test = Test(123, 456, 789)
calc = test.calc
for i in range(10000000):
result += calc(i)
run()
101 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
3. Избавляемся от глобальных переменных
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
def run():
result = 0
test = Test(123, 456, 789)
calc = test.calc
for i in range(10000000):
result += calc(i)
run()
Время выполнения: 3.262315034866333
102 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
3. Избавляемся от глобальных переменных
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
def run():
result = 0
test = Test(123, 456, 789)
calc = test.calc
for i in range(10000000):
result += calc(i)
run()
Время выполнения: 3.262315034866333
Прирост производительности:
относительно предыдущего варианта: 19%
103 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
3. Избавляемся от глобальных переменных
class Test(object):
__slots__ = "x", "y", "z"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def calc(self, p):
return (self.x + self.y * p) / self.z
def run():
result = 0
test = Test(123, 456, 789)
calc = test.calc
for i in range(10000000):
result += calc(i)
run()
Время выполнения: 3.262315034866333
Прирост производительности:
относительно предыдущего варианта: 19%
относительно первого варианта: 39.3%
104 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
4. Используем замыкания
105 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
4. Используем замыкания
def Test(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
result = 0
calc = Test(123, 456, 789)
for i in range(10000000):
result += calc(i)
run()
106 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
4. Используем замыкания
def Test(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
result = 0
calc = Test(123, 456, 789)
for i in range(10000000):
result += calc(i)
run()
Время выполнения: 2.652660846710205
107 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
4. Используем замыкания
def Test(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
result = 0
calc = Test(123, 456, 789)
for i in range(10000000):
result += calc(i)
run()
Время выполнения: 2.652660846710205
Прирост производительности:
относительно предыдущего варианта: 18.7%
108 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
4. Используем замыкания
def Test(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
result = 0
calc = Test(123, 456, 789)
for i in range(10000000):
result += calc(i)
run()
Время выполнения: 2.652660846710205
Прирост производительности:
относительно предыдущего варианта: 18.7%
относительно первого варианта: 50.7%
109 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
5. Используем списочную обработку вместо циклов:
map, list comprehensions, sum, и т.п...
110 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
5. Используем списочную обработку вместо циклов:
map, list comprehensions, sum, и т.п...
def Test(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
calc = Test(123, 456, 789)
result = sum(map(calc, range(10000000)))
run()
111 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
5. Используем списочную обработку вместо циклов:
map, list comprehensions, sum, и т.п...
def Test(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
calc = Test(123, 456, 789)
result = sum(map(calc, range(10000000)))
run()
Время выполнения: 2.4091830253601074
112 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
5. Используем списочную обработку вместо циклов:
map, list comprehensions, sum, и т.п...
def Test(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
calc = Test(123, 456, 789)
result = sum(map(calc, range(10000000)))
run()
Время выполнения: 2.4091830253601074
Прирост производительности:
относительно предыдущего варианта: 9.2%
113 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
5. Используем списочную обработку вместо циклов:
map, list comprehensions, sum, и т.п...
def Test(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
calc = Test(123, 456, 789)
result = sum(map(calc, range(10000000)))
run()
Время выполнения: 2.4091830253601074
Прирост производительности:
относительно предыдущего варианта: 9.2%
относительно первого варианта: 55.2%
114 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- ????
И вроде бы пора остановится, но...
115 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- ????
И вроде бы пора остановится, но...
Мы ухудшили гибкость и красоту кода, избавившись от ООП.
Хотелось бы сохранить полноценный класс, при этом получив
скорость замыканий.
116 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Замыкания v2
Замыкания в методах класса
117 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Замыкания v2
Замыкания в методах класса
class Test(object):
__slots__ = "x", "y", "z", "calc"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
self.calc = self._calc_gen(x, y, z)
@staticmethod
def _calc_gen(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
calc = Test(123, 456, 789).calc
result = sum(map(calc, range(10000000)))
run()
118 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Замыкания v2
Замыкания в методах класса
class Test(object):
__slots__ = "x", "y", "z", "calc"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
self.calc = self._calc_gen(x, y, z)
@staticmethod
def _calc_gen(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
calc = Test(123, 456, 789).calc
result = sum(map(calc, range(10000000)))
run()
Время выполнения: 2.4088900089263916
119 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Замыкания v2
Замыкания в методах класса
class Test(object):
__slots__ = "x", "y", "z", "calc"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
self.calc = self._calc_gen(x, y, z)
@staticmethod
def _calc_gen(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
calc = Test(123, 456, 789).calc
result = sum(map(calc, range(10000000)))
run()
Время выполнения: 2.4088900089263916
Прирост производительности:
относительно предыдущего варианта: 0%
120 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Замыкания v2
Замыкания в методах класса
class Test(object):
__slots__ = "x", "y", "z", "calc"
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
self.calc = self._calc_gen(x, y, z)
@staticmethod
def _calc_gen(x, y, z):
def calc(p):
return (x + y * p) / z
return calc
def run():
calc = Test(123, 456, 789).calc
result = sum(map(calc, range(10000000)))
run()
Время выполнения: 2.4088900089263916
Прирост производительности:
относительно предыдущего варианта: 0%
относительно первоначального варианта: 55.2%
121 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Замыкания v2
Замыкания в методах класса
class Test(object):
....
def _get_x(self): return self._x
def _get_y(self): return self._y
def _get_z(self): return self._z
def _set_x(self, x):
self._x = x
self.calc = self._calc_gen(x, self._y, self._z)
def _set_y(self, y):
self._y = y
self.calc = self._calc_gen(self._x, y, self._z)
def _set_z(self, z):
self._z = z
self.calc = self._calc_gen(self._x, self._y, z)
x, y, z = ( property(fget=_get_x, fset=_set_x)
, property(fget=_get_y, fset=_set_y)
, property(fget=_get_z, fset=_set_z) )
...
122 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Сравнительный анализ
Сводная таблица с результатами
Описание время пред.* перв.**
Изначальный вариант 5.38
С использованием слотов 4.43 17.5% 17.5%
Вынос поиска метода за цикл 4.03 9.2% 25.1%
Избавление от глобальных переменных 3.26 19.0% 39.3%
Сохранение параметров в замыкании 2.65 18.7% 50.7%
Использование sum и map 2.41 9.2% 55.2%
Замыкания в методах класса 2.41 0% 55.2%
* - прирост производительности относительно предыдущего варианта,
** - относительно первоначального варианта
123 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Сравнительный анализ
- Инструменты
Инструменты и материалы, используемые при
оптимизации
124 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Сравнительный анализ
- Инструменты
Инструменты и материалы, используемые при
оптимизации
Сложность стандартных операций в Python
wiki.python.org/moin/TimeComplexity
125 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Сравнительный анализ
- Инструменты
Инструменты и материалы, используемые при
оптимизации
Сложность операций в Python (подробнее)
www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt
126 / 216
1. Микро-
оптимизации
2. Оптимизации
- Вступление
- Слоты
- Поиск метода
- Глобальные переменные
- Замыкания
- Списочная обработка
- Сравнительный анализ
- Инструменты
Инструменты и материалы, используемые при
оптимизации
Библиотека big_O
github.com/pberkes/big_O
Позволяет оценивать сложность (в "Big O"-нотации) выполнения
python-кода на основе времени выполнения в зависимости от
входных параметров.
127 / 216
Часть 3
"Мегаоптимизации"
128 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Мы будем говорить о манипуляцих с кодом,
кодогенерации и дополнительных инструментах, не
подразумевающих смену платформы.
но, для начала...
129 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Забудьте всё, о чем мы говорили ранее!
130 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Забудьте всё, о чем мы говорили ранее!
131 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Забудьте всё, о чем мы говорили ранее!
132 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Представьте, что все оптимизации,
которые возможно автоматизировать (а
это очень многие) производились бы
автоматически при добавлении всего
нескольких строк кода в ваш проект.
133 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Представьте, что все оптимизации,
которые возможно автоматизировать (а
это очень многие) производились бы
автоматически при добавлении всего
нескольких строк кода в ваш проект.
И давайте порассуждаем на тему статических
оптимизаторов для python.
134 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Статические оптимизаторы
Тезисы:
135 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Статические оптимизаторы
Тезисы:
Позволят автоматически и прозрачно для пользователя
производить над кодом различные оптимизации (в том числе
перечисленные в предыдущих частях презентации), при этом,
не "уродуя" исходный код.
136 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Статические оптимизаторы
Тезисы:
Позволят автоматически и прозрачно для пользователя
производить над кодом различные оптимизации (в том числе
перечисленные в предыдущих частях презентации), при этом,
не "уродуя" исходный код.
Могут быть основаны на анализе и модификации AST и/или
байт-кода.
137 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Статические оптимизаторы
Тезисы:
Позволят автоматически и прозрачно для пользователя
производить над кодом различные оптимизации (в том числе
перечисленные в предыдущих частях презентации), при этом,
не "уродуя" исходный код.
Могут быть основаны на анализе и модификации AST и/или
байт-кода.
Наличие таковых как минимум странно для динамического
языка.
138 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Статические оптимизаторы
Тезисы:
Позволят автоматически и прозрачно для пользователя
производить над кодом различные оптимизации (в том числе
перечисленные в предыдущих частях презентации), при этом,
не "уродуя" исходный код.
Могут быть основаны на анализе и модификации AST и/или
байт-кода.
Наличие таковых как минимум странно для динамического
языка.
Для python их существование невозможно без нарушения
семантики языка.
139 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Статические оптимизаторы
Тезисы:
Позволят автоматически и прозрачно для пользователя
производить над кодом различные оптимизации (в том числе
перечисленные в предыдущих частях презентации), при этом,
не "уродуя" исходный код.
Могут быть основаны на анализе и модификации AST и/или
байт-кода.
Наличие таковых как минимум странно для динамического
языка.
Для python их существование невозможно без нарушения
семантики языка.
Для того, чтобы возможно было их использовать, необходимо
наложить некоторые ограничения на оптимизируемый код.
140 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Статические оптимизаторы
Тезисы:
Позволят автоматически и прозрачно для пользователя
производить над кодом различные оптимизации (в том числе
перечисленные в предыдущих частях презентации), при этом,
не "уродуя" исходный код.
Могут быть основаны на анализе и модификации AST и/или
байт-кода.
Наличие таковых как минимум странно для динамического
языка.
Для python их существование невозможно без нарушения
семантики языка.
Для того, чтобы возможно было их использовать, необходимо
наложить некоторые ограничения на оптимизируемый код.
Пока нет готовых к полноценному использованию
статических оптимизаторов для python.
141 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Ограничения, налагаемые на код при использовании
статического оптимизатора:
142 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Ограничения, налагаемые на код при использовании
статического оптимизатора:
Должно быть очень много тестов, в идеале всё (или почти
всё) должно быть покрыть тестами.
143 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Ограничения, налагаемые на код при использовании
статического оптимизатора:
Должно быть очень много тестов, в идеале всё (или почти всё)
должно быть покрыть тестами.
Не должно быть других модификаторов AST и/или байт-кода.
144 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Ограничения, налагаемые на код при использовании
статического оптимизатора:
Должно быть очень много тестов, в идеале всё (или почти всё)
должно быть покрыть тестами.
Не должно быть других модификаторов AST и/или байт-кода.
Не должно быть динамически исполняемого кода (exec /
eval), влияющих на поток исполнения или состав объектов/
типов.
145 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Ограничения, налагаемые на код при использовании
статического оптимизатора:
Должно быть очень много тестов, в идеале всё (или почти всё)
должно быть покрыть тестами.
Не должно быть других модификаторов AST и/или байт-кода.
Не должно быть динамически исполняемого кода (exec /
eval), влияющих на поток исполнения или состав объектов/
типов.
Остальные ограничения сильно зависят от оптимизаторов и
оптимизаций, в качестве примеров:
146 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Ограничения, налагаемые на код при использовании
статического оптимизатора:
Должно быть очень много тестов, в идеале всё (или почти всё)
должно быть покрыть тестами.
Не должно быть других модификаторов AST и/или байт-кода.
Не должно быть динамически исполняемого кода (exec /
eval), влияющих на поток исполнения или состав объектов/
типов.
Остальные ограничения сильно зависят от оптимизаторов и
оптимизаций, в качестве примеров:
не должно быть подмены стандарных функций, типов и
модулей;
147 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
Ограничения, налагаемые на код при использовании
статического оптимизатора:
Должно быть очень много тестов, в идеале всё (или почти всё)
должно быть покрыть тестами.
Не должно быть других модификаторов AST и/или байт-кода.
Не должно быть динамически исполняемого кода (exec /
eval), влияющих на поток исполнения или состав объектов/
типов.
Остальные ограничения сильно зависят от оптимизаторов и
оптимизаций, в качестве примеров:
не должно быть подмены стандарных функций, типов и
модулей;
не должно быть перегрузки некоторых операторов для
использования со встроенными типами (литералами) *
* Например, сложение с числом какой-либо переменной не должно означать ничего, кроме
сложения с числом
148 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
astoptimizer
Первой известной попыткой создания статического оптимизатора
для python был проект astoptimizer
(pypi.python.org/pypi/astoptimizer).
Проект не был принят сообществом как раз из-за того, что нарушал
семантику кода, например, происходили замены вроде:
len("abc") -> 3,
при этом не учитывалось, что len можно было подменить и тогда
код становился некорректным.
149 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Статический оптимизатор для python, основанный на анализе и
модификации AST.
github.com/Amper/opyum
150 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Преимущества:
Command-line mode - отображает оптимизированный код на
основе исходного либо формирует diff между исходным:
151 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Преимущества:
Command-line mode - отображает оптимизированный код на
основе исходного либо формирует diff между исходным:
$ opyum diff example.py --app "ksdiff"
152 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Преимущества:
Command-line mode - отображает оптимизированный код на
основе исходного либо формирует diff между исходным:
$ opyum diff example.py --app "ksdiff"
153 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Преимущества:
Command-line mode - отображает оптимизированный код на
основе исходного либо формирует diff между исходным.
Простое использование в нескольких вариантах:
import opyum
opyum.activate()
# other imports
154 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Преимущества:
Command-line mode - отображает оптимизированный код на
основе исходного либо формирует diff между исходным.
Простое использование в нескольких вариантах:
import opyum
opyum.activate()
# other imports
@opyum.optimize
def function_for_optimize():
...
155 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Преимущества:
Command-line mode - отображает оптимизированный код на
основе исходного либо формирует diff между исходным.
Простое использование в нескольких вариантах:
import opyum
opyum.activate()
# other imports
@opyum.optimize
def function_for_optimize():
...
with opyum.activate:
# optimized imports
# other imports
156 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Преимущества:
Command-line mode - отображает оптимизированный код на
основе исходного либо формирует diff между исходным.
Простое использование в нескольких вариантах.
Расширяемость:
import opyum
class MyOptimization(opyum.ASTOptimization):
def visit_Node(self, node):
...
opyum.install(MyOptimization)
opyum.uninstall("CustomConstantPropagation")
157 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Преимущества:
Command-line mode - отображает оптимизированный код на
основе исходного либо формирует diff между исходным.
Простое использование в нескольких вариантах:
Расширяемость.
Автор :)
158 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Недостатки:
159 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Недостатки:
Те же, что и у astoptimizer (нарушение семантики языка).
160 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Недостатки:
Те же, что и у astoptimizer (нарушение семантики языка).
Ужасные-ужасные костыли в коде, которые позволяют
модифицировать байт-код на лету с помощью декораторов и
импорт-хуков.
161 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Недостатки:
Те же, что и у astoptimizer (нарушение семантики языка).
Ужасные-ужасные костыли в коде, которые позволяют
модифицировать байт-код на лету с помощью декораторов и
импорт-хуков.
Неоптимальность (выполняет отдельный проход по AST для
каждой оптмизации).
162 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Недостатки:
Те же, что и у astoptimizer (нарушение семантики языка).
Ужасные-ужасные костыли в коде, которые позволяют
модифицировать байт-код на лету с помощью декораторов и
импорт-хуков.
Неоптимальность (выполняет отдельный проход по AST для
каждой оптмизации).
Py3-only.
163 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Оптимизации, реализованные на текущий момент:
164 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Оптимизации, реализованные на текущий момент:
1. Свертка констант (constant folding).
165 / 216
1. Микро-
оптимизации
2. Оптимизации
3. "Мега-
оптимизации"
Вступление
Статические
оптимизаторы
opyum
Оптимизации, реализованные на текущий момент:
1. Свертка констант (constant folding).
2. Протяжка констант (constant propagation).
166 / 216
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python
Оптимизация производительности Python

More Related Content

What's hot

Лекция 1. Начало.
Лекция 1. Начало.Лекция 1. Начало.
Лекция 1. Начало.
Roman Brovko
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормоза
Alexander Shigin
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.
Roman Brovko
 
Лекция 8. Итераторы, генераторы и модуль itertools.
 Лекция 8. Итераторы, генераторы и модуль itertools. Лекция 8. Итераторы, генераторы и модуль itertools.
Лекция 8. Итераторы, генераторы и модуль itertools.
Roman Brovko
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка Django
Vladimir Rudnyh
 
Лекция 10. Классы 2.
Лекция 10. Классы 2.Лекция 10. Классы 2.
Лекция 10. Классы 2.
Roman Brovko
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.
Roman Brovko
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
Python Meetup
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.
Roman Brovko
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GIL
Roman Brovko
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
Яковенко Кирилл
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
victor-yastrebov
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
Sergey Platonov
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.
Roman Brovko
 
Лекция 6. Классы 1.
Лекция 6. Классы 1.Лекция 6. Классы 1.
Лекция 6. Классы 1.
Roman Brovko
 
Python dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееPython dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущее
delimitry
 
Об особенностях использования значимых типов в .NET
Об особенностях использования значимых типов в .NETОб особенностях использования значимых типов в .NET
Об особенностях использования значимых типов в .NET
Andrey Akinshin
 
Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.
Roman Brovko
 
Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.
Roman Brovko
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассов
Andrey Zakharevich
 

What's hot (20)

Лекция 1. Начало.
Лекция 1. Начало.Лекция 1. Начало.
Лекция 1. Начало.
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормоза
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.
 
Лекция 8. Итераторы, генераторы и модуль itertools.
 Лекция 8. Итераторы, генераторы и модуль itertools. Лекция 8. Итераторы, генераторы и модуль itertools.
Лекция 8. Итераторы, генераторы и модуль itertools.
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка Django
 
Лекция 10. Классы 2.
Лекция 10. Классы 2.Лекция 10. Классы 2.
Лекция 10. Классы 2.
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GIL
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.
 
Лекция 6. Классы 1.
Лекция 6. Классы 1.Лекция 6. Классы 1.
Лекция 6. Классы 1.
 
Python dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееPython dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущее
 
Об особенностях использования значимых типов в .NET
Об особенностях использования значимых типов в .NETОб особенностях использования значимых типов в .NET
Об особенностях использования значимых типов в .NET
 
Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.
 
Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.
 
Магия метаклассов
Магия метаклассовМагия метаклассов
Магия метаклассов
 

Similar to Оптимизация производительности Python

Yuriy Sherstyuk - Algorithms in Front End: from V8 to VDOM
Yuriy Sherstyuk - Algorithms in Front End: from V8 to VDOMYuriy Sherstyuk - Algorithms in Front End: from V8 to VDOM
Yuriy Sherstyuk - Algorithms in Front End: from V8 to VDOM
OdessaJS Conf
 
Simd
SimdSimd
Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)
Ontico
 
Распространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложенийРаспространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложений
Andrey Akinshin
 
Распространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложенийРаспространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложений
Mikhail Shcherbakov
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Fwdays
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Python
CodeFest
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Python
ru_Parallels
 
Сложности микробенчмаркинга
Сложности микробенчмаркингаСложности микробенчмаркинга
Сложности микробенчмаркинга
Andrey Akinshin
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
 
Организация процесса регулярной обработки больших объемов данных
Организация процесса регулярной обработки больших объемов данныхОрганизация процесса регулярной обработки больших объемов данных
Организация процесса регулярной обработки больших объемов данных
CodeFest
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кода
Tatyanazaxarova
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кода
Andrey Karpov
 
лекция 3. программирование циклов
лекция 3. программирование цикловлекция 3. программирование циклов
лекция 3. программирование цикловstudent_kai
 
CC HackQuest 2010 Full Disclosure (мастер-класс)
CC HackQuest 2010 Full Disclosure (мастер-класс)CC HackQuest 2010 Full Disclosure (мастер-класс)
CC HackQuest 2010 Full Disclosure (мастер-класс)Dmitry Evteev
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
Mikhail Kurnosov
 
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
Eugeniy Tyumentcev
 
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
etyumentcev
 
Aspect Oriented Approach
Aspect Oriented ApproachAspect Oriented Approach
Aspect Oriented Approach
Dmytro Chyzhykov
 
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Yandex
 

Similar to Оптимизация производительности Python (20)

Yuriy Sherstyuk - Algorithms in Front End: from V8 to VDOM
Yuriy Sherstyuk - Algorithms in Front End: from V8 to VDOMYuriy Sherstyuk - Algorithms in Front End: from V8 to VDOM
Yuriy Sherstyuk - Algorithms in Front End: from V8 to VDOM
 
Simd
SimdSimd
Simd
 
Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)
 
Распространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложенийРаспространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложений
 
Распространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложенийРаспространённые ошибки оценки производительности .NET-приложений
Распространённые ошибки оценки производительности .NET-приложений
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Python
 
Сверхоптимизация кода на Python
Сверхоптимизация кода на PythonСверхоптимизация кода на Python
Сверхоптимизация кода на Python
 
Сложности микробенчмаркинга
Сложности микробенчмаркингаСложности микробенчмаркинга
Сложности микробенчмаркинга
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
Организация процесса регулярной обработки больших объемов данных
Организация процесса регулярной обработки больших объемов данныхОрганизация процесса регулярной обработки больших объемов данных
Организация процесса регулярной обработки больших объемов данных
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кода
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кода
 
лекция 3. программирование циклов
лекция 3. программирование цикловлекция 3. программирование циклов
лекция 3. программирование циклов
 
CC HackQuest 2010 Full Disclosure (мастер-класс)
CC HackQuest 2010 Full Disclosure (мастер-класс)CC HackQuest 2010 Full Disclosure (мастер-класс)
CC HackQuest 2010 Full Disclosure (мастер-класс)
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
 
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
 
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
 
Aspect Oriented Approach
Aspect Oriented ApproachAspect Oriented Approach
Aspect Oriented Approach
 
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
 

More from PyNSK

Нейронные сети и Keras. Часть 1
Нейронные сети и Keras. Часть 1Нейронные сети и Keras. Часть 1
Нейронные сети и Keras. Часть 1
PyNSK
 
Нейронные сети и Keras. Часть 2
Нейронные сети и Keras. Часть 2Нейронные сети и Keras. Часть 2
Нейронные сети и Keras. Часть 2
PyNSK
 
Asyncio для процессинга распределенной базы данных
Asyncio для процессинга  распределенной базы данныхAsyncio для процессинга  распределенной базы данных
Asyncio для процессинга распределенной базы данных
PyNSK
 
Python для GameDev
Python для GameDevPython для GameDev
Python для GameDev
PyNSK
 
Python инструменты для нагрузочного тестирования
Python инструменты для нагрузочного тестированияPython инструменты для нагрузочного тестирования
Python инструменты для нагрузочного тестирования
PyNSK
 
Python, Django и корпоративные информационные системы
Python, Django и корпоративные информационные системыPython, Django и корпоративные информационные системы
Python, Django и корпоративные информационные системы
PyNSK
 
Настрой контент под пользователя!
Настрой контент под пользователя!Настрой контент под пользователя!
Настрой контент под пользователя!
PyNSK
 
Питон в малине
Питон в малинеПитон в малине
Питон в малине
PyNSK
 
Мой Python всегда со мной!
Мой Python всегда со мной!Мой Python всегда со мной!
Мой Python всегда со мной!
PyNSK
 
Как и зачем можно создать DSL на Python
Как и зачем можно создать DSL на PythonКак и зачем можно создать DSL на Python
Как и зачем можно создать DSL на Python
PyNSK
 
Чем Python плох для стартапа?
Чем Python плох для стартапа?Чем Python плох для стартапа?
Чем Python плох для стартапа?
PyNSK
 
Во внутренности Kivy
Во внутренности KivyВо внутренности Kivy
Во внутренности Kivy
PyNSK
 
Зоопарк python веб-фреймворков
Зоопарк python веб-фреймворковЗоопарк python веб-фреймворков
Зоопарк python веб-фреймворков
PyNSK
 
Как Python Дайджест работает с внешней статикой
Как Python Дайджест работает с внешней статикойКак Python Дайджест работает с внешней статикой
Как Python Дайджест работает с внешней статикой
PyNSK
 
Применение behave+webdriver для тестирования Web-проектов
Применение behave+webdriver для тестирования Web-проектовПрименение behave+webdriver для тестирования Web-проектов
Применение behave+webdriver для тестирования Web-проектов
PyNSK
 
Ctypes в игровых приложениях на python
Ctypes в игровых приложениях на pythonCtypes в игровых приложениях на python
Ctypes в игровых приложениях на python
PyNSK
 
Python инструменты решения типичных задач
Python  инструменты решения типичных задачPython  инструменты решения типичных задач
Python инструменты решения типичных задач
PyNSK
 
JSON-RPC или когда rest неудобен
JSON-RPC или когда rest неудобенJSON-RPC или когда rest неудобен
JSON-RPC или когда rest неудобен
PyNSK
 
TestRail. Некоторые возможности интеграции.
TestRail. Некоторые возможности интеграции.TestRail. Некоторые возможности интеграции.
TestRail. Некоторые возможности интеграции.
PyNSK
 
"Модифицируй это!" или "Больше магии Python с помощью изменения AST"
"Модифицируй это!" или "Больше магии Python с помощью изменения AST""Модифицируй это!" или "Больше магии Python с помощью изменения AST"
"Модифицируй это!" или "Больше магии Python с помощью изменения AST"
PyNSK
 

More from PyNSK (20)

Нейронные сети и Keras. Часть 1
Нейронные сети и Keras. Часть 1Нейронные сети и Keras. Часть 1
Нейронные сети и Keras. Часть 1
 
Нейронные сети и Keras. Часть 2
Нейронные сети и Keras. Часть 2Нейронные сети и Keras. Часть 2
Нейронные сети и Keras. Часть 2
 
Asyncio для процессинга распределенной базы данных
Asyncio для процессинга  распределенной базы данныхAsyncio для процессинга  распределенной базы данных
Asyncio для процессинга распределенной базы данных
 
Python для GameDev
Python для GameDevPython для GameDev
Python для GameDev
 
Python инструменты для нагрузочного тестирования
Python инструменты для нагрузочного тестированияPython инструменты для нагрузочного тестирования
Python инструменты для нагрузочного тестирования
 
Python, Django и корпоративные информационные системы
Python, Django и корпоративные информационные системыPython, Django и корпоративные информационные системы
Python, Django и корпоративные информационные системы
 
Настрой контент под пользователя!
Настрой контент под пользователя!Настрой контент под пользователя!
Настрой контент под пользователя!
 
Питон в малине
Питон в малинеПитон в малине
Питон в малине
 
Мой Python всегда со мной!
Мой Python всегда со мной!Мой Python всегда со мной!
Мой Python всегда со мной!
 
Как и зачем можно создать DSL на Python
Как и зачем можно создать DSL на PythonКак и зачем можно создать DSL на Python
Как и зачем можно создать DSL на Python
 
Чем Python плох для стартапа?
Чем Python плох для стартапа?Чем Python плох для стартапа?
Чем Python плох для стартапа?
 
Во внутренности Kivy
Во внутренности KivyВо внутренности Kivy
Во внутренности Kivy
 
Зоопарк python веб-фреймворков
Зоопарк python веб-фреймворковЗоопарк python веб-фреймворков
Зоопарк python веб-фреймворков
 
Как Python Дайджест работает с внешней статикой
Как Python Дайджест работает с внешней статикойКак Python Дайджест работает с внешней статикой
Как Python Дайджест работает с внешней статикой
 
Применение behave+webdriver для тестирования Web-проектов
Применение behave+webdriver для тестирования Web-проектовПрименение behave+webdriver для тестирования Web-проектов
Применение behave+webdriver для тестирования Web-проектов
 
Ctypes в игровых приложениях на python
Ctypes в игровых приложениях на pythonCtypes в игровых приложениях на python
Ctypes в игровых приложениях на python
 
Python инструменты решения типичных задач
Python  инструменты решения типичных задачPython  инструменты решения типичных задач
Python инструменты решения типичных задач
 
JSON-RPC или когда rest неудобен
JSON-RPC или когда rest неудобенJSON-RPC или когда rest неудобен
JSON-RPC или когда rest неудобен
 
TestRail. Некоторые возможности интеграции.
TestRail. Некоторые возможности интеграции.TestRail. Некоторые возможности интеграции.
TestRail. Некоторые возможности интеграции.
 
"Модифицируй это!" или "Больше магии Python с помощью изменения AST"
"Модифицируй это!" или "Больше магии Python с помощью изменения AST""Модифицируй это!" или "Больше магии Python с помощью изменения AST"
"Модифицируй это!" или "Больше магии Python с помощью изменения AST"
 

Оптимизация производительности Python

  • 2. О чём мы будем говорить? 2 / 216
  • 3. Мы не будем говорить: 3 / 216
  • 4. Мы не будем говорить: Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…) 4 / 216
  • 5. Мы не будем говорить: Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…) О распараллеливании алгоритмов 5 / 216
  • 6. Мы не будем говорить: Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…) О распараллеливании алгоритмов О переписывании кода на другие языки * * при этом мы все же немного поговорим о генерации кода на других языках на основе python- кода 6 / 216
  • 7. Мы не будем говорить: Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…) О распараллеливании алгоритмов О переписывании кода на другие языки * Об объективности и правильности приводимых в докладе тестов * при этом мы все же немного поговорим о генерации кода на других языках на основе python- кода 7 / 216
  • 8. Мы не будем говорить: Об «альтернативных» платформах (PyPy, MyPy, Jython, Iron Python, etc…) О распараллеливании алгоритмов О переписывании кода на другие языки * Об объективности и правильности приводимых в докладе тестов О том, что всё, о чем вы услышите, нужно применять с умом * при этом мы все же немного поговорим о генерации кода на других языках на основе python- кода 8 / 216
  • 10. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях 10 / 216
  • 11. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях Модуль dis 11 / 216
  • 12. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях Модуль dis Использование: >>> from dis import dis >>> dis("sec_in_week = 604800") 1 0 LOAD_CONST 6 (604800) 3 STORE_NAME 0 (sec_in_week) 6 LOAD_CONST 3 (None) 9 RETURN_VALUE 12 / 216
  • 13. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях Модуль dis Использование: >>> from dis import dis >>> dis("sec_in_week = 604800") 1 0 LOAD_CONST 6 (604800) 3 STORE_NAME 0 (sec_in_week) 6 LOAD_CONST 3 (None) 9 RETURN_VALUE Подробнее: docs.python.org/3/library/dis.html 13 / 216
  • 14. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях x = 1 y = 2 Модуль dis Пример. Мы хотим узнать, какая конструкция выполняется быстрее: x, y = 1, 2 14 / 216
  • 15. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях x = 1 y = 2 LOAD_CONST ((1, 2)) UNPACK_SEQUENCE 2 STORE_NAME (x) STORE_NAME (y) LOAD_CONST (None) RETURN_VALUE LOAD_CONST (1) STORE_NAME (x) LOAD_CONST (2) STORE_NAME (y) LOAD_CONST (None) RETURN_VALUE Модуль dis Пример. Мы хотим узнать, какая конструкция выполняется быстрее: x, y = 1, 2 15 / 216
  • 16. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях x = 1 y = 2 LOAD_CONST ((1, 2)) UNPACK_SEQUENCE 2 STORE_NAME (x) STORE_NAME (y) LOAD_CONST (None) RETURN_VALUE LOAD_CONST (1) STORE_NAME (x) LOAD_CONST (2) STORE_NAME (y) LOAD_CONST (None) RETURN_VALUE Модуль dis Пример. Мы хотим узнать, какая конструкция выполняется быстрее: Видно, что байт-код отличается на две конструкции, в первом случае - загрузка кортежа в стек и распаковка в стек, во втором - две загрузки целых чисел в стек. x, y = 1, 2 16 / 216
  • 17. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях x = 1 y = 2 LOAD_CONST ((1, 2)) UNPACK_SEQUENCE 2 STORE_NAME (x) STORE_NAME (y) LOAD_CONST (None) RETURN_VALUE LOAD_CONST (1) STORE_NAME (x) LOAD_CONST (2) STORE_NAME (y) LOAD_CONST (None) RETURN_VALUE Модуль dis Пример. Мы хотим узнать, какая конструкция выполняется быстрее: Интуитивно понятно, что загрузка кортежа в стек медленней загрузки числа в стек, и распаковка кортежа в стек медленней загрузки одного значения в стек. x, y = 1, 2 17 / 216
  • 18. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях x = 1 y = 2 LOAD_CONST ((1, 2)) UNPACK_SEQUENCE 2 STORE_NAME (x) STORE_NAME (y) LOAD_CONST (None) RETURN_VALUE LOAD_CONST (1) STORE_NAME (x) LOAD_CONST (2) STORE_NAME (y) LOAD_CONST (None) RETURN_VALUE Модуль dis Пример. Мы хотим узнать, какая конструкция выполняется быстрее: Поэтому видно, что второй код быстрее первого. Но, если не видно, то есть timeit. x, y = 1, 2 18 / 216
  • 19. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях Модуль timeit 19 / 216
  • 20. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях Модуль timeit Использование (в REPL или в python-коде): >>> from timeit import timeit >>> >>> timeit("x, y = 1, 2", number=100000000) 3.349976803001482 >>> >>> timeit("x = 1; y = 1", number=100000000) 3.125208465033211 20 / 216
  • 21. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях Модуль timeit Использование (в ipython): In [1]: %timeit a, b, c, d = 1, 2, 3, 4 10000000 loops, best of 3: 45.1 ns per loop In [2]: %timeit a = 1; b = 2; c = 3; d = 4 10000000 loops, best of 3: 47.7 ns per loop In [3]: 21 / 216
  • 22. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях Модуль timeit Использование (в режиме командной строки): $ python3 -m timeit -n 1000000 -r 100 "x = 1; y = 2; z = 3" 1000000 loops, best of 100: 0.0385 usec per loop $ $ python3 -m timeit -n 1000000 -r 100 "x, y, z = 1, 2, 3" 1000000 loops, best of 100: 0.0388 usec per loop 22 / 216
  • 23. 1. Микро- оптимизации - Инструменты Инструменты, используемые при микрооптимизациях Модуль timeit Использование (в режиме командной строки): $ python3 -m timeit -n 1000000 -r 100 "x = 1; y = 2; z = 3" 1000000 loops, best of 100: 0.0385 usec per loop $ $ python3 -m timeit -n 1000000 -r 100 "x, y, z = 1, 2, 3" 1000000 loops, best of 100: 0.0388 usec per loop Подробнее: docs.python.org/3/library/timeit.html 23 / 216
  • 24. 1. Микро- оптимизации - Инструменты - Замена умножения сложением 1. Замена умножения сложением 24 / 216
  • 25. 1. Микро- оптимизации - Инструменты - Замена умножения сложением 1. Замена умножения сложением >>> # int >>> from timeit import timeit >>> >>> timeit("x = x * 2", setup="x = 2") 21.935253892996116 >>> timeit("x = x + x", setup="x = 2") 18.347866550000617 25 / 216
  • 26. 1. Микро- оптимизации - Инструменты - Замена умножения сложением 1. Замена умножения сложением >>> # int >>> from timeit import timeit >>> >>> timeit("x = x * 2", setup="x = 2") 21.935253892996116 >>> timeit("x = x + x", setup="x = 2") 18.347866550000617 >>> # float >>> from timeit import timeit >>> >>> timeit("x = x * 2", setup="x = 3.14", number=100000000) 8.331406126002548 >>> timeit("x = x + x", setup="x = 3.14", number=100000000) 4.393627463025041 26 / 216
  • 27. 1. Микро- оптимизации - Инструменты - Замена умножения сложением 1. Замена умножения сложением >>> # int >>> from timeit import timeit >>> >>> timeit("x = x * 2", setup="x = 2") 21.935253892996116 >>> timeit("x = x + x", setup="x = 2") 18.347866550000617 >>> # float >>> from timeit import timeit >>> >>> timeit("x = x * 2", setup="x = 3.14", number=100000000) 8.331406126002548 >>> timeit("x = x + x", setup="x = 3.14", number=100000000) 4.393627463025041 Сравнение: x * 2 x + x приростприрост int 21.94 18.35 16.5% float 8.33 4.39 47.3% 27 / 216
  • 28. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением 2. Замена возведения в степень умножением 28 / 216
  • 29. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением 2. Замена возведения в степень умножением >>> # int >>> timeit("x = x ** 2", setup="x = 2", number=30) 8.314083544013556 >>> timeit("x = x * x", setup="x = 2", number=30) 7.056395357009023 29 / 216
  • 30. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением 2. Замена возведения в степень умножением >>> # int >>> timeit("x = x ** 2", setup="x = 2", number=30) 8.314083544013556 >>> timeit("x = x * x", setup="x = 2", number=30) 7.056395357009023 >>> # float >>> timeit("x = x ** 2", setup="x = 0.5", number=100000000) 5.864706993103027 >>> timeit("x = x * x", setup="x = 0.5", number=100000000) 3.877152919769287 30 / 216
  • 31. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением 2. Замена возведения в степень умножением >>> # int >>> timeit("x = x ** 2", setup="x = 2", number=30) 8.314083544013556 >>> timeit("x = x * x", setup="x = 2", number=30) 7.056395357009023 >>> # float >>> timeit("x = x ** 2", setup="x = 0.5", number=100000000) 5.864706993103027 >>> timeit("x = x * x", setup="x = 0.5", number=100000000) 3.877152919769287 Сравнение: x ** 2 x * x приростприрост int 8.31 7.06 15.0% float 5.86 3.88 33.8% 31 / 216
  • 32. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант 3. Замена "константных переменных" их значениями (литералами). 32 / 216
  • 33. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант 3. Замена "константных переменных" их значениями (литералами). Иначе говоря, популярная оптимизация под названием constant propagation ("протяжка" констант). 33 / 216
  • 34. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант 3. Замена "константных переменных" их значениями (литералами). «Модифицируй это!» или «Больше магии Python с помощью изменения AST» vk.com/wall-96469126_1029 34 / 216
  • 35. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. 35 / 216
  • 36. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. In [1]: x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" In [2]: y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" In [3]: %timeit z = (x == y) 10000000 loops, best of 3: 85.3 ns per loop In [4]: %timeit z = (x == y) 10000000 loops, best of 3: 85.1 ns per loop In [5]: # ??? In [6]: # ??? In [7]: # ??? In [8]: %timeit z = (x == y) 10000000 loops, best of 3: 57.3 ns per loop In [9]: %timeit z = (x == y) 10000000 loops, best of 3: 57.4 ns per loop 36 / 216
  • 37. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. In [1]: x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" In [2]: y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" In [3]: %timeit z = (x == y) 10000000 loops, best of 3: 85.3 ns per loop In [4]: %timeit z = (x == y) 10000000 loops, best of 3: 85.1 ns per loop In [5]: import sys In [6]: x = sys.intern(x) In [7]: y = sys.intern(y) In [8]: %timeit z = (x == y) 10000000 loops, best of 3: 57.3 ns per loop In [9]: %timeit z = (x == y) 10000000 loops, best of 3: 57.4 ns per loop 37 / 216
  • 38. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. >>> x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" >>> y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" >>> >>> x == y, x is y (True, False) >>> id(x), id(y) (4376204752, 4376204848) 38 / 216
  • 39. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. >>> x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" >>> y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" >>> >>> x == y, x is y (True, False) >>> id(x), id(y) (4376204752, 4376204848) >>> >>> from sys import intern >>> x, y = intern(x), intern(y) 39 / 216
  • 40. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. >>> x = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" >>> y = """()*YH)(8h3-p24f9h 98u34r-19843u_(*U _%^IG+_""" >>> >>> x == y, x is y (True, False) >>> id(x), id(y) (4376204752, 4376204848) >>> >>> from sys import intern >>> x, y = intern(x), intern(y) >>> >>> x == y, x is y (True, True) >>> id(x), id(y) (4376204752, 4376204752) 40 / 216
  • 41. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. 41 / 216
  • 42. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. Интернирование делает строки синглтонами, то есть для каждой уникальной строки существует только один экземпляр. 42 / 216
  • 43. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. Интернирование делает строки синглтонами, то есть для каждой уникальной строки существует только один экземпляр. Происходит автоматически для односимвольных строк. 43 / 216
  • 44. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. Интернирование делает строки синглтонами, то есть для каждой уникальной строки существует только один экземпляр. Происходит автоматически для односимвольных строк. Происходит автоматически для идентификаторов. 44 / 216
  • 45. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. Интернирование делает строки синглтонами, то есть для каждой уникальной строки существует только один экземпляр. Происходит автоматически для односимвольных строк. Происходит автоматически для идентификаторов. Аналогичный механизм используется для чисел от -5 до 256, эти числа также являются синглтонами. 45 / 216
  • 46. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. Интернирование делает строки синглтонами, то есть для каждой уникальной строки существует только один экземпляр. Происходит автоматически для односимвольных строк. Происходит автоматически для идентификаторов. Аналогичный механизм используется для чисел от -5 до 256, эти числа также являются синглтонами. В качестве операторов сравнения интернированных строк можно использовать is и is not, что даст прирост скорости сравнения. 46 / 216
  • 47. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. The internals of Python string interning guilload.com/python-string-interning/ 47 / 216
  • 48. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк 4. "Интернирование" строк / string interning. Python string objects implementation www.laurentluce.com/posts/python-string-objects-implementation/ 48 / 216
  • 49. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" 5. "Диспатчинг" вместо каскадов условий / dispatching 49 / 216
  • 50. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" 5. "Диспатчинг" вместо каскадов условий / dispatching Компенсируем отсутствие case использованием словарей. 50 / 216
  • 51. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" 5. "Диспатчинг" вместо каскадов условий / dispatching Компенсируем отсутствие case использованием словарей. Рассмотрим пример: r = 0 for i in range(10000000): x = i % 10 if x == 0: pass elif x == 1: r = r + 1 elif x == 2: r = r + 2 elif x == 3: r = r + 3 elif x == 4: r = r + 4 elif x == 5: r = r + 5 elif x == 6: r = r + 6 elif x == 7: r = r + 7 elif x == 8: r = r + 8 elif x == 9: r = r + 9 51 / 216
  • 52. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" 5. "Диспатчинг" вместо каскадов условий / dispatching Компенсируем отсутствие case использованием словарей. Рассмотрим пример: r = 0 for i in range(10000000): x = i % 10 if x == 0: pass elif x == 1: r = r + 1 elif x == 2: r = r + 2 elif x == 3: r = r + 3 elif x == 4: r = r + 4 elif x == 5: r = r + 5 elif x == 6: r = r + 6 elif x == 7: r = r + 7 elif x == 8: r = r + 8 elif x == 9: r = r + 9 Время выполнения: 4.513951063156128 52 / 216
  • 53. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" 5. "Диспатчинг" вместо каскадов условий / dispatching Теперь пробуем сделать то же самое с помощью словаря. 53 / 216
  • 54. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" 5. "Диспатчинг" вместо каскадов условий / dispatching Теперь пробуем сделать то же самое с помощью словаря. dispatch_table = { 0: lambda r: r , 1: lambda r: r + 1 , 2: lambda r: r + 2 , 3: lambda r: r + 3 , 4: lambda r: r + 4 , 5: lambda r: r + 5 , 6: lambda r: r + 6 , 7: lambda r: r + 7 , 8: lambda r: r + 8 , 9: lambda r: r + 9 } r = 0 for i in range(10000000): r = dispatch_table[i % 10](r) 54 / 216
  • 55. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" 5. "Диспатчинг" вместо каскадов условий / dispatching Теперь пробуем сделать то же самое с помощью словаря. dispatch_table = { 0: lambda r: r , 1: lambda r: r + 1 , 2: lambda r: r + 2 , 3: lambda r: r + 3 , 4: lambda r: r + 4 , 5: lambda r: r + 5 , 6: lambda r: r + 6 , 7: lambda r: r + 7 , 8: lambda r: r + 8 , 9: lambda r: r + 9 } r = 0 for i in range(10000000): r = dispatch_table[i % 10](r) Время выполнения: 3.8208770751953125. 55 / 216
  • 56. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" 5. "Диспатчинг" вместо каскадов условий / dispatching Теперь пробуем сделать то же самое с помощью словаря. dispatch_table = { 0: lambda r: r , 1: lambda r: r + 1 , 2: lambda r: r + 2 , 3: lambda r: r + 3 , 4: lambda r: r + 4 , 5: lambda r: r + 5 , 6: lambda r: r + 6 , 7: lambda r: r + 7 , 8: lambda r: r + 8 , 9: lambda r: r + 9 } r = 0 for i in range(10000000): r = dispatch_table[i % 10](r) Время выполнения: 3.8208770751953125. Таким образом время выполнения снизилось на 15%. 56 / 216
  • 57. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов 6. Приведение типов 57 / 216
  • 58. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов 6. Приведение типов >>> from timeit import timeit >>> >>> timeit("a = (x >= 3.14)", setup="x = 10", number=100000000) >>> 8.488232829986373 58 / 216
  • 59. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов 6. Приведение типов >>> from timeit import timeit >>> >>> timeit("a = (x >= 3.14)", setup="x = 10", number=100000000) >>> 8.488232829986373 >>> >>> timeit("a = (x >= 3.14)", setup="x = 10.0", number=100000000) >>> 4.145244649000233 59 / 216
  • 60. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов 6. Приведение типов >>> from timeit import timeit >>> >>> timeit("a = (x >= 3.14)", setup="x = 10", number=100000000) >>> 8.488232829986373 >>> >>> timeit("a = (x >= 3.14)", setup="x = 10.0", number=100000000) >>> 4.145244649000233 Прирост скорости 51%. 60 / 216
  • 61. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк 7. Форматирование строк In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590" In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243" In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50" In [4]: 61 / 216
  • 62. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк 7. Форматирование строк In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590" In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243" In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50" In [4]: In [5]: %timeit "." + x + ".." + y + "..." + z + "...." 1000000 loops, best of 3: 453 ns per loop In [6]: 62 / 216
  • 63. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк 7. Форматирование строк In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590" In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243" In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50" In [4]: In [5]: %timeit "." + x + ".." + y + "..." + z + "...." 1000000 loops, best of 3: 453 ns per loop In [6]: In [7]: %timeit ".{}..{}...{}....".format(x, y, z) 1000000 loops, best of 3: 615 ns per loop In [8]: 63 / 216
  • 64. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк 7. Форматирование строк In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590" In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243" In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50" In [4]: In [5]: %timeit "." + x + ".." + y + "..." + z + "...." 1000000 loops, best of 3: 453 ns per loop In [6]: In [7]: %timeit ".{}..{}...{}....".format(x, y, z) 1000000 loops, best of 3: 615 ns per loop In [8]: In [9]: %timeit "".join((".", x, "..", y, "...", z, "....")) 1000000 loops, best of 3: 287 ns per loop In [10]: 64 / 216
  • 65. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк 7. Форматирование строк In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590" In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243" In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50" In [4]: In [5]: %timeit "." + x + ".." + y + "..." + z + "...." 1000000 loops, best of 3: 453 ns per loop In [6]: In [7]: %timeit ".{}..{}...{}....".format(x, y, z) 1000000 loops, best of 3: 615 ns per loop In [8]: In [9]: %timeit "".join((".", x, "..", y, "...", z, "....")) 1000000 loops, best of 3: 287 ns per loop In [10]: # ??? 65 / 216
  • 66. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк 7. Форматирование строк In [1]: x = "4827 f245fy24958fu204g9u240gi5 540245t 24590" In [2]: y = "*() *Y)(u f-934u34 ut20349{)(I 09i 4309it243" In [3]: z = "p908u54 -98u _(*U -09u 3409340t9i340it-4t-50" In [4]: In [5]: %timeit "." + x + ".." + y + "..." + z + "...." 1000000 loops, best of 3: 453 ns per loop In [6]: In [7]: %timeit ".{}..{}...{}....".format(x, y, z) 1000000 loops, best of 3: 615 ns per loop In [8]: In [9]: %timeit "".join((".", x, "..", y, "...", z, "....")) 1000000 loops, best of 3: 287 ns per loop In [10]: In [11]: %timeit ".{0}..{1}...{2}....".format(x, y, z) 1000000 loops, best of 3: 204 ns per loop 66 / 216
  • 67. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole if x in [1, 2, 3]: x += 41 + 1 if x in (1, 2, 3): x += 42 8. Peephole-оптимизация Какой код выполняется быстрее? 67 / 216
  • 68. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole if x in [1, 2, 3]: x += 41 + 1 if x in (1, 2, 3): x += 42 LOAD_NAME (x) LOAD_CONST ((1, 2, 3)) COMPARE_OP (in) POP_JUMP_IF_FALSE 25 LOAD_NAME (x) LOAD_CONST (42) INPLACE_ADD STORE_NAME (x) JUMP_FORWARD (to 25) LOAD_CONST (None) RETURN_VALUE LOAD_NAME (x) LOAD_CONST ((1, 2, 3)) COMPARE_OP (in) POP_JUMP_IF_FALSE 25 LOAD_NAME (x) LOAD_CONST (42) INPLACE_ADD STORE_NAME (x) JUMP_FORWARD (to 25) LOAD_CONST (None) RETURN_VALUE 8. Peephole-оптимизация Какой код выполняется быстрее? Воспользуемся модулем dis: 68 / 216
  • 69. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole if x in [1, 2, 3]: x += 41 + 1 if x in (1, 2, 3): x += 42 LOAD_NAME (x) LOAD_CONST ((1, 2, 3)) COMPARE_OP (in) POP_JUMP_IF_FALSE 25 LOAD_NAME (x) LOAD_CONST (42) INPLACE_ADD STORE_NAME (x) JUMP_FORWARD (to 25) LOAD_CONST (None) RETURN_VALUE LOAD_NAME (x) LOAD_CONST ((1, 2, 3)) COMPARE_OP (in) POP_JUMP_IF_FALSE 25 LOAD_NAME (x) LOAD_CONST (42) INPLACE_ADD STORE_NAME (x) JUMP_FORWARD (to 25) LOAD_CONST (None) RETURN_VALUE 8. Peephole-оптимизация Какой код выполняется быстрее? Воспользуемся модулем dis: Байт-код полностью совпадает. 69 / 216
  • 70. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole x = ( 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 ) 8. Peephole-оптимизация Какой код выполняется быстрее? x = (1, 2, 3) * 6 . . 70 / 216
  • 71. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole x = ( 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 ) 8. Peephole-оптимизация Какой код выполняется быстрее? LOAD_CONST (( 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 )) STORE_NAME (x) LOAD_CONST (None) RETURN_VALUE LOAD_CONST (( 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 )) STORE_NAME (x) LOAD_CONST (None) RETURN_VALUE x = (1, 2, 3) * 6 . . 71 / 216
  • 72. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole x = ( 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 ) 8. Peephole-оптимизация Какой код выполняется быстрее? LOAD_CONST (( 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 )) STORE_NAME (x) LOAD_CONST (None) RETURN_VALUE LOAD_CONST (( 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 , 1, 2, 3 )) STORE_NAME (x) LOAD_CONST (None) RETURN_VALUE Байт-код снова полностью совпадает. x = (1, 2, 3) * 6 . . 72 / 216
  • 73. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole x = ( 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3 ) 8. Peephole-оптимизация Какой код выполняется быстрее? x = (1, 2, 3) * 7 . . . 73 / 216
  • 74. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole x = ( 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3 ) 8. Peephole-оптимизация Какой код выполняется быстрее? x = (1, 2, 3) * 10 # ??? x = (1, 2, 3) * 7 . . . 74 / 216
  • 75. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole x = ( 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3 ) 8. Peephole-оптимизация Какой код выполняется быстрее? x = (1, 2, 3) * 10 # ??? x = (1, 2, 3) * 100 # ??? x = (1, 2, 3) * 7 . . . 75 / 216
  • 76. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole x = ( 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3, 1, 2, 3 , 1, 2, 3 ) 8. Peephole-оптимизация Какой код выполняется быстрее? x = (1, 2, 3) * 10 # ??? x = (1, 2, 3) * 100 # ??? x = (1, 2, 3) * 1000000 # ??? x = (1, 2, 3) * 7 . . . 76 / 216
  • 77. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole sec_in_week = 7 * 24 * 60 * 60 sec_in_week = 604800 8. Peephole-оптимизация Вы должны понимать, что оптимизации вроде бесполезны, так как компилятор делает их сам. 77 / 216
  • 78. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole - Другие микрооптимизации Примеры других микрооптимизаций 78 / 216
  • 79. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole - Другие микрооптимизации Примеры других микрооптимизаций for i in my_list: yield i yield from my_list 79 / 216
  • 80. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole - Другие микрооптимизации Примеры других микрооптимизаций for i in my_list: yield i func(1) func(2) func(3) yield from my_list for i in (1, 2, 3): func(i) . 80 / 216
  • 81. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole - Другие микрооптимизации Примеры других микрооптимизаций for i in my_list: yield i func(1) func(2) func(3) x if x else y x or y yield from my_list for i in (1, 2, 3): func(i) . 81 / 216
  • 82. 1. Микро- оптимизации - Инструменты - Замена умножения сложением - Замена возведения в степень умножением - "Протяжка" констант - "Интернирование" строк - "Диспатчинг" - Приведение типов - Форматирование строк - Peephole - Другие микрооптимизации Примеры других микрооптимизаций for i in my_list: yield i func(1) func(2) func(3) x if x else y x or y x == None y != None x is None y is not None yield from my_list for i in (1, 2, 3): func(i) . 82 / 216
  • 84. 1. Микро- оптимизации 2. Оптимизации - Вступление Для начала рассмотрим пример, который будем модифицировать. 84 / 216
  • 85. 1. Микро- оптимизации 2. Оптимизации - Вступление Для начала рассмотрим пример, который будем модифицировать. class Test(object): def __init__(self, x, y, z): self.x = x self.y = y self.z = z def calc(self, p): return (self.x + self.y * p) / self.z 85 / 216
  • 86. 1. Микро- оптимизации 2. Оптимизации - Вступление Для начала рассмотрим пример, который будем модифицировать. class Test(object): def __init__(self, x, y, z): self.x = x self.y = y self.z = z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) for i in range(10000000): result += test.calc(i) 86 / 216
  • 87. 1. Микро- оптимизации 2. Оптимизации - Вступление Для начала рассмотрим пример, который будем модифицировать. class Test(object): def __init__(self, x, y, z): self.x = x self.y = y self.z = z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) for i in range(10000000): result += test.calc(i) 87 / 216
  • 88. 1. Микро- оптимизации 2. Оптимизации - Вступление Для начала рассмотрим пример, который будем модифицировать. class Test(object): def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) for i in range(10000000): result += test.calc(i) 88 / 216
  • 89. 1. Микро- оптимизации 2. Оптимизации - Вступление Для начала рассмотрим пример, который будем модифицировать. class Test(object): def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) for i in range(10000000): result += test.calc(i) Время выполнения данного кода: 5.3768229484558105 89 / 216
  • 90. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты 1. Слоты 90 / 216
  • 91. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты 1. Слоты class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) for i in range(10000000): result += test.calc(i) 91 / 216
  • 92. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты 1. Слоты class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) for i in range(10000000): result += test.calc(i) Время выполнения данного кода: 4.434956073760986 92 / 216
  • 93. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты 1. Слоты class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) for i in range(10000000): result += test.calc(i) Время выполнения данного кода: 4.434956073760986 Прирост производительности относительно изначального варианта: 17.5% 93 / 216
  • 94. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты 1. Слоты class Test(object): __slots__ = "x", "y", "z", "__dict__" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) for i in range(10000000): result += test.calc(i) Время выполнения данного кода: 4.434956073760986 Прирост производительности относительно изначального варианта: 17.5% 94 / 216
  • 95. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода 2. Устраняем поиск метода (lookup) 95 / 216
  • 96. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода 2. Устраняем поиск метода (lookup) class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) calc = test.calc for i in range(10000000): result += calc(i) 96 / 216
  • 97. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода 2. Устраняем поиск метода (lookup) class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) calc = test.calc for i in range(10000000): result += calc(i) Время выполнения: 4.027298927307129 97 / 216
  • 98. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода 2. Устраняем поиск метода (lookup) class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) calc = test.calc for i in range(10000000): result += calc(i) Время выполнения: 4.027298927307129 Прирост производительности: относительно предыдущего варианта: 9.2% 98 / 216
  • 99. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода 2. Устраняем поиск метода (lookup) class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z result = 0 test = Test(123, 456, 789) calc = test.calc for i in range(10000000): result += calc(i) Время выполнения: 4.027298927307129 Прирост производительности: относительно предыдущего варианта: 9.2% относительно изначального варианта: 25.1% 99 / 216
  • 100. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные 3. Избавляемся от глобальных переменных 100 / 216
  • 101. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные 3. Избавляемся от глобальных переменных class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z def run(): result = 0 test = Test(123, 456, 789) calc = test.calc for i in range(10000000): result += calc(i) run() 101 / 216
  • 102. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные 3. Избавляемся от глобальных переменных class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z def run(): result = 0 test = Test(123, 456, 789) calc = test.calc for i in range(10000000): result += calc(i) run() Время выполнения: 3.262315034866333 102 / 216
  • 103. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные 3. Избавляемся от глобальных переменных class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z def run(): result = 0 test = Test(123, 456, 789) calc = test.calc for i in range(10000000): result += calc(i) run() Время выполнения: 3.262315034866333 Прирост производительности: относительно предыдущего варианта: 19% 103 / 216
  • 104. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные 3. Избавляемся от глобальных переменных class Test(object): __slots__ = "x", "y", "z" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z def calc(self, p): return (self.x + self.y * p) / self.z def run(): result = 0 test = Test(123, 456, 789) calc = test.calc for i in range(10000000): result += calc(i) run() Время выполнения: 3.262315034866333 Прирост производительности: относительно предыдущего варианта: 19% относительно первого варианта: 39.3% 104 / 216
  • 105. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания 4. Используем замыкания 105 / 216
  • 106. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания 4. Используем замыкания def Test(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): result = 0 calc = Test(123, 456, 789) for i in range(10000000): result += calc(i) run() 106 / 216
  • 107. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания 4. Используем замыкания def Test(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): result = 0 calc = Test(123, 456, 789) for i in range(10000000): result += calc(i) run() Время выполнения: 2.652660846710205 107 / 216
  • 108. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания 4. Используем замыкания def Test(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): result = 0 calc = Test(123, 456, 789) for i in range(10000000): result += calc(i) run() Время выполнения: 2.652660846710205 Прирост производительности: относительно предыдущего варианта: 18.7% 108 / 216
  • 109. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания 4. Используем замыкания def Test(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): result = 0 calc = Test(123, 456, 789) for i in range(10000000): result += calc(i) run() Время выполнения: 2.652660846710205 Прирост производительности: относительно предыдущего варианта: 18.7% относительно первого варианта: 50.7% 109 / 216
  • 110. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка 5. Используем списочную обработку вместо циклов: map, list comprehensions, sum, и т.п... 110 / 216
  • 111. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка 5. Используем списочную обработку вместо циклов: map, list comprehensions, sum, и т.п... def Test(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): calc = Test(123, 456, 789) result = sum(map(calc, range(10000000))) run() 111 / 216
  • 112. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка 5. Используем списочную обработку вместо циклов: map, list comprehensions, sum, и т.п... def Test(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): calc = Test(123, 456, 789) result = sum(map(calc, range(10000000))) run() Время выполнения: 2.4091830253601074 112 / 216
  • 113. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка 5. Используем списочную обработку вместо циклов: map, list comprehensions, sum, и т.п... def Test(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): calc = Test(123, 456, 789) result = sum(map(calc, range(10000000))) run() Время выполнения: 2.4091830253601074 Прирост производительности: относительно предыдущего варианта: 9.2% 113 / 216
  • 114. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка 5. Используем списочную обработку вместо циклов: map, list comprehensions, sum, и т.п... def Test(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): calc = Test(123, 456, 789) result = sum(map(calc, range(10000000))) run() Время выполнения: 2.4091830253601074 Прирост производительности: относительно предыдущего варианта: 9.2% относительно первого варианта: 55.2% 114 / 216
  • 115. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - ???? И вроде бы пора остановится, но... 115 / 216
  • 116. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - ???? И вроде бы пора остановится, но... Мы ухудшили гибкость и красоту кода, избавившись от ООП. Хотелось бы сохранить полноценный класс, при этом получив скорость замыканий. 116 / 216
  • 117. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Замыкания v2 Замыкания в методах класса 117 / 216
  • 118. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Замыкания v2 Замыкания в методах класса class Test(object): __slots__ = "x", "y", "z", "calc" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z self.calc = self._calc_gen(x, y, z) @staticmethod def _calc_gen(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): calc = Test(123, 456, 789).calc result = sum(map(calc, range(10000000))) run() 118 / 216
  • 119. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Замыкания v2 Замыкания в методах класса class Test(object): __slots__ = "x", "y", "z", "calc" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z self.calc = self._calc_gen(x, y, z) @staticmethod def _calc_gen(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): calc = Test(123, 456, 789).calc result = sum(map(calc, range(10000000))) run() Время выполнения: 2.4088900089263916 119 / 216
  • 120. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Замыкания v2 Замыкания в методах класса class Test(object): __slots__ = "x", "y", "z", "calc" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z self.calc = self._calc_gen(x, y, z) @staticmethod def _calc_gen(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): calc = Test(123, 456, 789).calc result = sum(map(calc, range(10000000))) run() Время выполнения: 2.4088900089263916 Прирост производительности: относительно предыдущего варианта: 0% 120 / 216
  • 121. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Замыкания v2 Замыкания в методах класса class Test(object): __slots__ = "x", "y", "z", "calc" def __init__(self, x, y, z): self.x, self.y, self.z = x, y, z self.calc = self._calc_gen(x, y, z) @staticmethod def _calc_gen(x, y, z): def calc(p): return (x + y * p) / z return calc def run(): calc = Test(123, 456, 789).calc result = sum(map(calc, range(10000000))) run() Время выполнения: 2.4088900089263916 Прирост производительности: относительно предыдущего варианта: 0% относительно первоначального варианта: 55.2% 121 / 216
  • 122. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Замыкания v2 Замыкания в методах класса class Test(object): .... def _get_x(self): return self._x def _get_y(self): return self._y def _get_z(self): return self._z def _set_x(self, x): self._x = x self.calc = self._calc_gen(x, self._y, self._z) def _set_y(self, y): self._y = y self.calc = self._calc_gen(self._x, y, self._z) def _set_z(self, z): self._z = z self.calc = self._calc_gen(self._x, self._y, z) x, y, z = ( property(fget=_get_x, fset=_set_x) , property(fget=_get_y, fset=_set_y) , property(fget=_get_z, fset=_set_z) ) ... 122 / 216
  • 123. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Сравнительный анализ Сводная таблица с результатами Описание время пред.* перв.** Изначальный вариант 5.38 С использованием слотов 4.43 17.5% 17.5% Вынос поиска метода за цикл 4.03 9.2% 25.1% Избавление от глобальных переменных 3.26 19.0% 39.3% Сохранение параметров в замыкании 2.65 18.7% 50.7% Использование sum и map 2.41 9.2% 55.2% Замыкания в методах класса 2.41 0% 55.2% * - прирост производительности относительно предыдущего варианта, ** - относительно первоначального варианта 123 / 216
  • 124. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Сравнительный анализ - Инструменты Инструменты и материалы, используемые при оптимизации 124 / 216
  • 125. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Сравнительный анализ - Инструменты Инструменты и материалы, используемые при оптимизации Сложность стандартных операций в Python wiki.python.org/moin/TimeComplexity 125 / 216
  • 126. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Сравнительный анализ - Инструменты Инструменты и материалы, используемые при оптимизации Сложность операций в Python (подробнее) www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt 126 / 216
  • 127. 1. Микро- оптимизации 2. Оптимизации - Вступление - Слоты - Поиск метода - Глобальные переменные - Замыкания - Списочная обработка - Сравнительный анализ - Инструменты Инструменты и материалы, используемые при оптимизации Библиотека big_O github.com/pberkes/big_O Позволяет оценивать сложность (в "Big O"-нотации) выполнения python-кода на основе времени выполнения в зависимости от входных параметров. 127 / 216
  • 129. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Мы будем говорить о манипуляцих с кодом, кодогенерации и дополнительных инструментах, не подразумевающих смену платформы. но, для начала... 129 / 216
  • 130. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Забудьте всё, о чем мы говорили ранее! 130 / 216
  • 131. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Забудьте всё, о чем мы говорили ранее! 131 / 216
  • 132. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Забудьте всё, о чем мы говорили ранее! 132 / 216
  • 133. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Представьте, что все оптимизации, которые возможно автоматизировать (а это очень многие) производились бы автоматически при добавлении всего нескольких строк кода в ваш проект. 133 / 216
  • 134. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Представьте, что все оптимизации, которые возможно автоматизировать (а это очень многие) производились бы автоматически при добавлении всего нескольких строк кода в ваш проект. И давайте порассуждаем на тему статических оптимизаторов для python. 134 / 216
  • 135. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Статические оптимизаторы Тезисы: 135 / 216
  • 136. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Статические оптимизаторы Тезисы: Позволят автоматически и прозрачно для пользователя производить над кодом различные оптимизации (в том числе перечисленные в предыдущих частях презентации), при этом, не "уродуя" исходный код. 136 / 216
  • 137. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Статические оптимизаторы Тезисы: Позволят автоматически и прозрачно для пользователя производить над кодом различные оптимизации (в том числе перечисленные в предыдущих частях презентации), при этом, не "уродуя" исходный код. Могут быть основаны на анализе и модификации AST и/или байт-кода. 137 / 216
  • 138. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Статические оптимизаторы Тезисы: Позволят автоматически и прозрачно для пользователя производить над кодом различные оптимизации (в том числе перечисленные в предыдущих частях презентации), при этом, не "уродуя" исходный код. Могут быть основаны на анализе и модификации AST и/или байт-кода. Наличие таковых как минимум странно для динамического языка. 138 / 216
  • 139. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Статические оптимизаторы Тезисы: Позволят автоматически и прозрачно для пользователя производить над кодом различные оптимизации (в том числе перечисленные в предыдущих частях презентации), при этом, не "уродуя" исходный код. Могут быть основаны на анализе и модификации AST и/или байт-кода. Наличие таковых как минимум странно для динамического языка. Для python их существование невозможно без нарушения семантики языка. 139 / 216
  • 140. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Статические оптимизаторы Тезисы: Позволят автоматически и прозрачно для пользователя производить над кодом различные оптимизации (в том числе перечисленные в предыдущих частях презентации), при этом, не "уродуя" исходный код. Могут быть основаны на анализе и модификации AST и/или байт-кода. Наличие таковых как минимум странно для динамического языка. Для python их существование невозможно без нарушения семантики языка. Для того, чтобы возможно было их использовать, необходимо наложить некоторые ограничения на оптимизируемый код. 140 / 216
  • 141. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Статические оптимизаторы Тезисы: Позволят автоматически и прозрачно для пользователя производить над кодом различные оптимизации (в том числе перечисленные в предыдущих частях презентации), при этом, не "уродуя" исходный код. Могут быть основаны на анализе и модификации AST и/или байт-кода. Наличие таковых как минимум странно для динамического языка. Для python их существование невозможно без нарушения семантики языка. Для того, чтобы возможно было их использовать, необходимо наложить некоторые ограничения на оптимизируемый код. Пока нет готовых к полноценному использованию статических оптимизаторов для python. 141 / 216
  • 142. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Ограничения, налагаемые на код при использовании статического оптимизатора: 142 / 216
  • 143. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Ограничения, налагаемые на код при использовании статического оптимизатора: Должно быть очень много тестов, в идеале всё (или почти всё) должно быть покрыть тестами. 143 / 216
  • 144. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Ограничения, налагаемые на код при использовании статического оптимизатора: Должно быть очень много тестов, в идеале всё (или почти всё) должно быть покрыть тестами. Не должно быть других модификаторов AST и/или байт-кода. 144 / 216
  • 145. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Ограничения, налагаемые на код при использовании статического оптимизатора: Должно быть очень много тестов, в идеале всё (или почти всё) должно быть покрыть тестами. Не должно быть других модификаторов AST и/или байт-кода. Не должно быть динамически исполняемого кода (exec / eval), влияющих на поток исполнения или состав объектов/ типов. 145 / 216
  • 146. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Ограничения, налагаемые на код при использовании статического оптимизатора: Должно быть очень много тестов, в идеале всё (или почти всё) должно быть покрыть тестами. Не должно быть других модификаторов AST и/или байт-кода. Не должно быть динамически исполняемого кода (exec / eval), влияющих на поток исполнения или состав объектов/ типов. Остальные ограничения сильно зависят от оптимизаторов и оптимизаций, в качестве примеров: 146 / 216
  • 147. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Ограничения, налагаемые на код при использовании статического оптимизатора: Должно быть очень много тестов, в идеале всё (или почти всё) должно быть покрыть тестами. Не должно быть других модификаторов AST и/или байт-кода. Не должно быть динамически исполняемого кода (exec / eval), влияющих на поток исполнения или состав объектов/ типов. Остальные ограничения сильно зависят от оптимизаторов и оптимизаций, в качестве примеров: не должно быть подмены стандарных функций, типов и модулей; 147 / 216
  • 148. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы Ограничения, налагаемые на код при использовании статического оптимизатора: Должно быть очень много тестов, в идеале всё (или почти всё) должно быть покрыть тестами. Не должно быть других модификаторов AST и/или байт-кода. Не должно быть динамически исполняемого кода (exec / eval), влияющих на поток исполнения или состав объектов/ типов. Остальные ограничения сильно зависят от оптимизаторов и оптимизаций, в качестве примеров: не должно быть подмены стандарных функций, типов и модулей; не должно быть перегрузки некоторых операторов для использования со встроенными типами (литералами) * * Например, сложение с числом какой-либо переменной не должно означать ничего, кроме сложения с числом 148 / 216
  • 149. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы astoptimizer Первой известной попыткой создания статического оптимизатора для python был проект astoptimizer (pypi.python.org/pypi/astoptimizer). Проект не был принят сообществом как раз из-за того, что нарушал семантику кода, например, происходили замены вроде: len("abc") -> 3, при этом не учитывалось, что len можно было подменить и тогда код становился некорректным. 149 / 216
  • 150. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Статический оптимизатор для python, основанный на анализе и модификации AST. github.com/Amper/opyum 150 / 216
  • 151. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Преимущества: Command-line mode - отображает оптимизированный код на основе исходного либо формирует diff между исходным: 151 / 216
  • 152. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Преимущества: Command-line mode - отображает оптимизированный код на основе исходного либо формирует diff между исходным: $ opyum diff example.py --app "ksdiff" 152 / 216
  • 153. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Преимущества: Command-line mode - отображает оптимизированный код на основе исходного либо формирует diff между исходным: $ opyum diff example.py --app "ksdiff" 153 / 216
  • 154. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Преимущества: Command-line mode - отображает оптимизированный код на основе исходного либо формирует diff между исходным. Простое использование в нескольких вариантах: import opyum opyum.activate() # other imports 154 / 216
  • 155. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Преимущества: Command-line mode - отображает оптимизированный код на основе исходного либо формирует diff между исходным. Простое использование в нескольких вариантах: import opyum opyum.activate() # other imports @opyum.optimize def function_for_optimize(): ... 155 / 216
  • 156. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Преимущества: Command-line mode - отображает оптимизированный код на основе исходного либо формирует diff между исходным. Простое использование в нескольких вариантах: import opyum opyum.activate() # other imports @opyum.optimize def function_for_optimize(): ... with opyum.activate: # optimized imports # other imports 156 / 216
  • 157. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Преимущества: Command-line mode - отображает оптимизированный код на основе исходного либо формирует diff между исходным. Простое использование в нескольких вариантах. Расширяемость: import opyum class MyOptimization(opyum.ASTOptimization): def visit_Node(self, node): ... opyum.install(MyOptimization) opyum.uninstall("CustomConstantPropagation") 157 / 216
  • 158. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Преимущества: Command-line mode - отображает оптимизированный код на основе исходного либо формирует diff между исходным. Простое использование в нескольких вариантах: Расширяемость. Автор :) 158 / 216
  • 159. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Недостатки: 159 / 216
  • 160. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Недостатки: Те же, что и у astoptimizer (нарушение семантики языка). 160 / 216
  • 161. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Недостатки: Те же, что и у astoptimizer (нарушение семантики языка). Ужасные-ужасные костыли в коде, которые позволяют модифицировать байт-код на лету с помощью декораторов и импорт-хуков. 161 / 216
  • 162. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Недостатки: Те же, что и у astoptimizer (нарушение семантики языка). Ужасные-ужасные костыли в коде, которые позволяют модифицировать байт-код на лету с помощью декораторов и импорт-хуков. Неоптимальность (выполняет отдельный проход по AST для каждой оптмизации). 162 / 216
  • 163. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Недостатки: Те же, что и у astoptimizer (нарушение семантики языка). Ужасные-ужасные костыли в коде, которые позволяют модифицировать байт-код на лету с помощью декораторов и импорт-хуков. Неоптимальность (выполняет отдельный проход по AST для каждой оптмизации). Py3-only. 163 / 216
  • 164. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Оптимизации, реализованные на текущий момент: 164 / 216
  • 165. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Оптимизации, реализованные на текущий момент: 1. Свертка констант (constant folding). 165 / 216
  • 166. 1. Микро- оптимизации 2. Оптимизации 3. "Мега- оптимизации" Вступление Статические оптимизаторы opyum Оптимизации, реализованные на текущий момент: 1. Свертка констант (constant folding). 2. Протяжка констант (constant propagation). 166 / 216