216
Оптимизация производительности Python Александр Маршалов / [email protected] 1 / 216

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

  • Upload
    pynsk

  • View
    382

  • Download
    0

Embed Size (px)

Citation preview

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

Александр Маршалов / [email protected]

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 = 1y = 2

Модуль dis

Пример. Мы хотим узнать, какая конструкция выполняется быстрее:

x, y = 1, 2 .

14 / 216

1. Микро-оптимизации

- Инструменты

Инструменты, используемые примикрооптимизациях

x = 1y = 2

LOAD_CONST ((1, 2))UNPACK_SEQUENCE 2STORE_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 = 1y = 2

LOAD_CONST ((1, 2))UNPACK_SEQUENCE 2STORE_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 = 1y = 2

LOAD_CONST ((1, 2))UNPACK_SEQUENCE 2STORE_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 = 1y = 2

LOAD_CONST ((1, 2))UNPACK_SEQUENCE 2STORE_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, 410000000 loops, best of 3: 45.1 ns per loop

In [2]: %timeit a = 1; b = 2; c = 3; d = 410000000 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. Замена "константных переменных" ихзначениями (литералами).

Иначе говоря, популярная оптимизация под названием constantpropagation ("протяжка" констант).

33 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

3. Замена "константных переменных" ихзначениями (литералами).

«Модифицируй это!» или «Больше магии Python спомощью изменения AST»

vk.com/wall-96469126_102934 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

35 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

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. "Интернирование" строк / stringinterning.

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. "Интернирование" строк / stringinterning.

>>> 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. "Интернирование" строк / stringinterning.

>>> 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. "Интернирование" строк / stringinterning.

>>> 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. "Интернирование" строк / stringinterning.

41 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

Интернирование делает строки синглтонами, то есть длякаждой уникальной строки существует только одинэкземпляр.

42 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

Интернирование делает строки синглтонами, то есть длякаждой уникальной строки существует только одинэкземпляр.

Происходит автоматически для односимвольных строк.

43 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

Интернирование делает строки синглтонами, то есть длякаждой уникальной строки существует только одинэкземпляр.

Происходит автоматически для односимвольных строк.

Происходит автоматически для идентификаторов.

44 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

Интернирование делает строки синглтонами, то есть длякаждой уникальной строки существует только одинэкземпляр.

Происходит автоматически для односимвольных строк.

Происходит автоматически для идентификаторов.

Аналогичный механизм используется для чисел от -5 до 256,эти числа также являются синглтонами.

45 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

Интернирование делает строки синглтонами, то есть длякаждой уникальной строки существует только одинэкземпляр.

Происходит автоматически для односимвольных строк.

Происходит автоматически для идентификаторов.

Аналогичный механизм используется для чисел от -5 до 256,эти числа также являются синглтонами.

В качестве операторов сравнения интернированных строкможно использовать is и is not, что даст прирост скоростисравнения.

46 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

The internals of Python string interning

guilload.com/python-string-interning/

47 / 216

1. Микро-оптимизации

- Инструменты

- Замена умножениясложением

- Замена возведения встепень умножением

- "Протяжка" констант

- "Интернирование" строк

4. "Интернирование" строк / stringinterning.

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 = 0for 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 = 0for 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 = 0for 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 = 0for 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 = 0for 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 25LOAD_NAME (x)LOAD_CONST (42)INPLACE_ADDSTORE_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 25LOAD_NAME (x)LOAD_CONST (42)INPLACE_ADDSTORE_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 25LOAD_NAME (x)LOAD_CONST (42)INPLACE_ADDSTORE_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 25LOAD_NAME (x)LOAD_CONST (42)INPLACE_ADDSTORE_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 == Noney != None

x is Noney 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 = 0test = 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 opyumopyum.activate()

# other imports

154 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

opyum

Преимущества:

Command-line mode - отображает оптимизированный код наоснове исходного либо формирует diff между исходным.

Простое использование в нескольких вариантах:

import opyumopyum.activate()

# other imports

@opyum.optimizedef function_for_optimize(): ...

155 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

opyum

Преимущества:

Command-line mode - отображает оптимизированный код наоснове исходного либо формирует diff между исходным.

Простое использование в нескольких вариантах:

import opyumopyum.activate()

# other imports

@opyum.optimizedef 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

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

opyum

Оптимизации, реализованные на текущий момент:

1. Свертка констант (constant folding).

2. Протяжка констант (constant propagation).

3. Удаление "мертвого" кода (dead code elimination).

167 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

opyum

Оптимизации, реализованные на текущий момент:

1. Свертка констант (constant folding).

2. Протяжка констант (constant propagation).

3. Удаление "мертвого" кода (dead code elimination).

4. Проставление позиций в форматировании строк.

168 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

opyum

Оптимизации, реализованные на текущий момент:

1. Свертка констант (constant folding).

2. Протяжка констант (constant propagation).

3. Удаление "мертвого" кода (dead code elimination).

4. Проставление позиций в форматировании строк.

5. Замена умножения сложением.

169 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

opyum

Оптимизации, реализованные на текущий момент:

1. Свертка констант (constant folding).

2. Протяжка констант (constant propagation).

3. Удаление "мертвого" кода (dead code elimination).

4. Проставление позиций в форматировании строк.

5. Замена умножения сложением.

6. Замена возведения в степень умножением.

170 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

opyum

Оптимизации, реализованные на текущий момент:

1. Свертка констант (constant folding).

2. Протяжка констант (constant propagation).

3. Удаление "мертвого" кода (dead code elimination).

4. Проставление позиций в форматировании строк.

5. Замена умножения сложением.

6. Замена возведения в степень умножением.

7. Замена yield на yield from.

171 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

opyum

Оптимизации, реализованные на текущий момент:

1. Свертка констант (constant folding).

2. Протяжка констант (constant propagation).

3. Удаление "мертвого" кода (dead code elimination).

4. Проставление позиций в форматировании строк.

5. Замена умножения сложением.

6. Замена возведения в степень умножением.

7. Замена yield на yield from.

8. Сохранение глобальных функций в замыкании.

172 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Очень амбициозный проект, имеющий, как мне кажется, большоебудущее.

faster-cpython.readthedocs.org/fat_python.html

173 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Проект включает в себя несколько элементов:

174 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Проект включает в себя несколько элементов:

Статический оптимизатор (fatoptimizer) для Python 3.6

175 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Проект включает в себя несколько элементов:

Статический оптимизатор (fatoptimizer) для Python 3.6

Модуль fat, реализующий концепцию "охранников" (guards).

176 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Проект включает в себя несколько элементов:

Статический оптимизатор (fatoptimizer) для Python 3.6

Модуль fat, реализующий концепцию "охранников" (guards).

PEP-ы:PEP 509: Add a private version to dict;

PEP 510: Specialized functions with guards;

PEP 511: API for AST transformers.

177 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Проект включает в себя несколько элементов:

Статический оптимизатор (fatoptimizer) для Python 3.6

Модуль fat, реализующий концепцию "охранников" (guards).

PEP-ы:PEP 509: Add a private version to dict;

PEP 510: Specialized functions with guards;

PEP 511: API for AST transformers.

Патчи для Python 3.6, реализующие вышеуказанные PEP.

178 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Проект включает в себя несколько элементов:

Статический оптимизатор (fatoptimizer) для Python 3.6

Модуль fat, реализующий концепцию "охранников" (guards).

PEP-ы:PEP 509: Add a private version to dict;

PEP 510: Specialized functions with guards;

PEP 511: API for AST transformers.

Патчи для Python 3.6, реализующие вышеуказанные PEP.

Это попытка реализовать статический оптимизатор для Python безпроблем, возникающих в astoptimizer и opyum.

179 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Преимущества:

180 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Преимущества:

Почти не нарушает семантику Python ("сомнительные"оптимизации отключены в умолчательной конфигурации).

181 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Преимущества:

Почти не нарушает семантику Python ("сомнительные"оптимизации отключены в умолчательной конфигурации).

PEP 0511, который значительно сократит количество"странного" кода в проектах, использующих модификациюAST.

182 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Преимущества:

Почти не нарушает семантику Python ("сомнительные"оптимизации отключены в умолчательной конфигурации).

PEP 0511, который значительно сократит количество"странного" кода в проектах, использующих модификациюAST.

Оптимальность (не выполняет отдельный проход по AST длякаждой оптимизации).

183 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Преимущества:

Почти не нарушает семантику Python ("сомнительные"оптимизации отключены в умолчательной конфигурации).

PEP 0511, который значительно сократит количество"странного" кода в проектах, использующих модификациюAST.

Оптимальность (не выполняет отдельный проход по AST длякаждой оптимизации).

Хорошая документация.

184 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Недостатки:

185 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Недостатки:

На текущий момент работает только на Python 3.6 соспециальными патчами.

186 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Недостатки:

На текущий момент работает только на Python 3.6 соспециальными патчами.

PEP пока в состоянии draft и могут быть не приняты.

187 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Недостатки:

На текущий момент работает только на Python 3.6 соспециальными патчами.

PEP пока в состоянии draft и могут быть не приняты.

Нерасширяемость (не позволяет дописывать кастомныеоптимизации).

188 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Оптимизации:

189 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Оптимизации:

1. Свертка констант / constant folding (в том числе заменавызовов "чистых" функций над константами на их значения).

190 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Оптимизации:

1. Свертка констант / constant folding (в том числе заменавызовов "чистых" функций над константами на их значения).

2. Разворачивание циклов и списковых включений / loopunrolling.

191 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Оптимизации:

1. Свертка констант / constant folding (в том числе заменавызовов "чистых" функций над константами на их значения).

2. Разворачивание циклов и списковых включений / loopunrolling.

3. Распространение костант / constant propagation.

192 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Оптимизации:

1. Свертка констант / constant folding (в том числе заменавызовов "чистых" функций над константами на их значения).

2. Разворачивание циклов и списковых включений / loopunrolling.

3. Распространение костант / constant propagation.

4. Удаление мертвого кода / dead code elimination.

193 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Оптимизации:

1. Свертка констант / constant folding (в том числе заменавызовов "чистых" функций над константами на их значения).

2. Разворачивание циклов и списковых включений / loopunrolling.

3. Распространение костант / constant propagation.

4. Удаление мертвого кода / dead code elimination.

5. Получение встроенных функций как констант (LOAD_GLOBALв байт-коде заменяется на LOAD_CONST).

194 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Оптимизации:

1. Свертка констант / constant folding (в том числе заменавызовов "чистых" функций над константами на их значения).

2. Разворачивание циклов и списковых включений / loopunrolling.

3. Распространение костант / constant propagation.

4. Удаление мертвого кода / dead code elimination.

5. Получение встроенных функций как констант (LOAD_GLOBAL вбайт-коде заменяется на LOAD_CONST).

6. Инлайнинг функций / function inlining.

195 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

FAT Python

Презентация от автора:

FAT Python - New static optimizer for CPython 3.6

https://fosdem.org/2016/schedule/event/fat_python/

196 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

Автоматическая оптимизация алгоритмов в Python спомощью быстрого возведения матриц в степень.

github.com/borzunov/cpmoptimize

197 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

Подходит для расчетов, основанных на рекурентном соотношениии/или простых арифметических операциях в циклах.

При этом используется модификация байт-кода.

В качестве примера: Числа фиббоначи, Сумма степеней числа.

Подробнее:

Статья: habrahabr.ru/post/236689/

Презентация: www.slideshare.net/daryazubova96/ltjh-cpmoptimize

Статья, из которой родился алгоритм: habrahabr.ru/post/148901/

198 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

def func1(n): r = 0 k = 1 for i in xrange(n): r += k k *= 2 return r

199 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

def func1(n): r = 0 k = 1 for i in xrange(n): r += k k *= 2 return r

def func2(n): return sum(2 ** i for i in xrange(n))

200 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

def func1(n): r = 0 k = 1 for i in xrange(n): r += k k *= 2 return r

def func2(n): return sum(2 ** i for i in xrange(n))

def func3(n): return reduce(lambda x, y: x * y + 1, (2, ) * (n - 1), 1)

201 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

def func1(n): r = 0 k = 1 for i in xrange(n): r += k k *= 2 return r

def func2(n): return sum(2 ** i for i in xrange(n))

def func3(n): return reduce(lambda x, y: x * y + 1, (2, ) * (n - 1), 1)

func4 = cpmoptimize()(func1) # декоратор

202 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

In [1]: %timeit [func1(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 422 ms per loop

In [2]: 'func1: 422 ms' # for

203 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

In [1]: %timeit [func1(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 422 ms per loop

In [2]: 'func1: 422 ms' # for

In [3]: %timeit [func2(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 14.5 s per loop

In [4]: 'func2: 14.5 s' # sum

204 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

In [1]: %timeit [func1(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 422 ms per loop

In [2]: 'func1: 422 ms' # for

In [3]: %timeit [func2(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 14.5 s per loop

In [4]: 'func2: 14.5 s' # sum

In [5]: %timeit [func3(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 378 ms per loop

In [6]: 'func3: 378 ms' # reduce

205 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

In [1]: %timeit [func1(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 422 ms per loop

In [2]: 'func1: 422 ms' # for

In [3]: %timeit [func2(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 14.5 s per loop

In [4]: 'func2: 14.5 s' # sum

In [5]: %timeit [func3(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 378 ms per loop

In [6]: 'func3: 378 ms' # reduce

In [7]: %timeit [func4(10 ** n) for n in xrange(1, 6)]100 loops, best of 3: 3.43 ms per loop

In [8]: 'func4: 3.43 ms' # for + cpmoptimize

206 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

cpmoptimize

In [1]: %timeit [func1(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 422 ms per loop

In [2]: 'func1: 422 ms' # for

In [3]: %timeit [func2(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 14.5 s per loop

In [4]: 'func2: 14.5 s' # sum

In [5]: %timeit [func3(10 ** n) for n in xrange(1, 6)]1 loops, best of 3: 378 ms per loop

In [6]: 'func3: 378 ms' # reduce

In [7]: %timeit [func4(10 ** n) for n in xrange(1, 6)]100 loops, best of 3: 3.43 ms per loop

In [8]: 'func4: 3.43 ms' # for + cpmoptimize

С использованием cpmoptimize получаем код в 110 раз быстреесамого быстрого pure-python варианта.

207 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

numba

numba

NumPy aware dynamic Python compiler using LLVM

numba.pydata.org

208 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

numba

numba

Использует LLVM для JIT-компиляции.

from numba import jitfrom numpy import arange

# jit decorator tells Numba to compile this function.# The argument types will be inferred by Numba when # function is called.

@jitdef sum2d(arr): M, N = arr.shape result = 0.0 for i in range(M): for j in range(N): result += arr[i, j] return result

a = arange(9).reshape(3, 3)print(sum2d(a))

209 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

numba

pythran

pythran

A claimless python to c++ converter

github.com/serge-sans-paille/pythran

210 / 216

1. Микро-оптимизации

2. Оптимизации

3. "Мега-оптимизации"

Вступление

Статическиеоптимизаторы

cpmoptimize

numba

pythran

nuitka

nuitka

Компилятор python в с++.

nuitka.net

211 / 216

Спасибо за внимание!

Готов выслушать ваши вопросы, пожелания,предложения, замечания, исправления, угрозы и

проклятия.

А так же их можно задать по почте:

[email protected]

212 / 216

Ссылки и материалы

213 / 216

Ссылки

доклады и статьи на тему оптимизации Python-кода:

Сверхоптимизация кода на Python - Иван РемизовHigh Performance Python - Marc GarciaExpensive lessons in Python performance tuning - Alex RubinsteynPython performance optimization - CLiPSProfiling Python in Production - Eben FreemanOptimizing Python in the Real World: NumPy, Numba, and the NUFFT - Jake VanderplasMicro-Optimizations in Python Code: Speeding Up Lookups - James SaryerwinnieHow to Make Python Faster Without Trying That Much - Saulius Lukauskas

214 / 216

Ссылки

проекты, связанные с оптимизацией Python-кода:

fatoptimizer - static optimizer specializing functions with guards for Python 3.6.opyum - статический оптимизатор python-кода.cpmoptimize - decorator for automatic algorithm optimization via fast matrixexponentiation.numexpr - fast numerical array expression evaluator for Python, NumPy, PyTables,pandas, bcolz and more.numba - NumPy aware dynamic Python compiler using LLVM.pythran - a claimless python to c++ converter.theano - python library that allows you to define, optimize, and evaluate mathematicalexpressions involving multi-dimensional arrays efficiently.nuitka - python to c++ compiler.big_O - python module to estimate big-O time complexity from execution time.pyston - an open-source Python implementation using JIT techniques.cython - optimising static compiler for both the Python programming language and theextended Cython programming language (based on Pyrex).

215 / 216

Ссылки

обучающие материалы:

The internals of Python string interningPython string objects implementationМодуль disМодуль timeitСложность стандартных операций в PythonСложность операций в Python (подробнее)Python internals: how callables workPython Performance Tips

216 / 216