Your SlideShare is downloading. ×
0
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 и его тормоза
Python и его тормоза
Python и его тормоза
Python и его тормоза
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Python и его тормоза

2,066

Published on

Доклад на pycamp kiev.

Доклад на pycamp kiev.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,066
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
32
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Python и его тормоза Можно ли заставить питон работать быстро Александр Шигин, shigin@rambler-co.ru Rambler, 2010
  • 2. О чем я буду говорить краткий рассказ о времени; простые примеры; быстрые простые примеры; глупые примеры; и еще глупости.
  • 3. Время Первый пример real time. $ time sleep 5 real 0m5.006s user 0m0.004s sys 0m0.008s
  • 4. Время Второй пример user time. $ time openssl rand > -out /dev/null 9000000 real 0m0.421s user 0m0.388s sys 0m0.004s
  • 5. Время Третий пример system time. $ time LANG=C dd if=/dev/zero > of=/dev/null count=900000 bs=1 900000+0 records in 900000+0 records out 900000 bytes (900 kB) copied, 0.413783 real 0m0.417s user 0m0.096s sys 0m0.312s
  • 6. Время Для процесса есть три времени: real, CPU, system. обычно нас интересует real time; но если мы запускаем много параллельных задач мы можем упереться в CPU (user) time; системное время в основном зависит от количества системных вызовов.
  • 7. Чуть-чуть чисел вызов функции по указателю (нс) C Python bi Python pure 4 140 270 [2.5] 130 260 [2.6] сумма массива из 400 целых чисел C Python bi Python pure 590 16 550 49 300 [2.5] 5 700 45 150 [2.6]
  • 8. Чуть-чуть числа про объекты создание чистого python объекта 210 нс; создание python объекта с пустым __slots__ 120 нс; создание embedded python объекта 150 нс.
  • 9. Создание объектов создание кортежа из двух элементов 31 нс; создание класса с двумя полями 690 нс; распаковка кортежа 130 нс; доступ к полю кортежа 105 нс; доступ к полю объекта 110 нс.
  • 10. Маленький пример Как лучше хранить неизменяемые пары чисел? Учебный пример нахождение центра масс. кортеж из трех чисел: x, y, масса; класс с тремя полями; словарь.
  • 11. Маленький пример: класс class P o s i t i o n : def __init__ ( s e l f , x , y , mass ) : self .x = x self .y = y s e l f . mass = mass x = [ P o s i ti o n (0 , 0 , 10) , P o si t i on (1 , 1 , 13) , Position (1 , 2 , 5)]
  • 12. Маленький пример: класс def g e t _ c e n t e r ( l s t ) : rx , ry , mass = 0 . 0 , 0 . 0 , 0 . 0 for i t e m in l s t : r x += i t e m . x ∗ i t e m . mass r y += i t e m . y ∗ i t e m . mass mass += i t e m . mass return P o s i t i o n ( r x / mass , r y / mass , mass ) Результат: 3900 нс
  • 13. Маленький пример: объекты новый класс ≈ 4100 нс; в 2.5 новый класс ≈ 4750 нс. __slots__ 2.6 ≈ 4050 нс, 2.5 4500 нс.
  • 14. Маленький пример: кортеж def g e t _ c e n t e r ( l s t ) : rx , ry , rm = 0 . 0 , 0 . 0 , 0 . 0 for x , y , mass in l s t : r x += x ∗ mass r y += y ∗ mass rm += mass return ( r x /rm , r y /rm , rm ) Результат: 2200 нс
  • 15. Маленький пример: словарь def g e t _ c e n t e r ( l s t ) : rx , ry , rm = 0 . 0 , 0 . 0 , 0 . 0 for i t e m in l s t : r x += i t e m [ ’ x ’ ] ∗ i t e m [ ’ mass ’ ] r y += i t e m [ ’ y ’ ] ∗ i t e m [ ’ mass ’ ] rm += i t e m [ ’ mass ’ ] return ( r x /rm , r y /rm , rm ) Результат: 2600 нс
  • 16. Маленький пример Итог: используйте кортежи. Меряем 2.5 2.6 старый класс 4050 3900 новый класс 4750 4130 со слотами 4490 4050 кортежи 2250 2210 словарь 2700 2630
  • 17. Глупый пример Смешные числа Фибоначи. Как лучше хранить текущую пару чисел? В этом примере мы будем изменять пару.
  • 18. Глупый пример: класс Первый вариант. class F : def __init__ ( s e l f , x , y ) : self .x = x self .y = y
  • 19. Глупый пример: класс Проверяем: x = F ( 1 , 1) t = x.y x.y = x.x + x.y x.x = t # так 4 раза Результат: 2830 нс
  • 20. Глупый пример: классы x.x, x.y = x.y, x.x + x.y немного медленнее; надо повторяться про новые классы?
  • 21. Глупый пример: кортеж Проверяем: x = 1, 1 x = x [1] , x [0] + x [1] # так 4 раза Результат: 1410 нс
  • 22. Глупый пример: словарь Проверяем: x = d i c t ( x =1, y=1) t = x [ ’y ’ ] x[ ’y ’ ] = x[ ’x ’ ] + x[ ’y ’ ] x[ ’x ’ ] = t # так 4 раза Результат: 2500 нс
  • 23. Глупый пример Итог: даже в этом случае используйте кортежи. Меряем 2.5 2.6 старый класс 2910 2835 новый класс 4630 3468 со слотами 4065 3212 кортежи 1550 1410 словарь 2810 2550
  • 24. Замыкания вызов замыкания 145 нс; возврат значения из замыкания 166 нс; создание замыкания 380 нс;
  • 25. Первый пример Создадим класс, экземпляры которого будут возвращать свой аргумент, увеличенный на некое число, которое мы передадим при создании класса. x = X( 1 4 ) x (15) # −> 29
  • 26. Первый пример старые классы class X: def __init__ ( s e l f , x ) : self .x = x def __call__ ( s e l f , x ) : return s e l f . x + x x = X(1); s = 0 # проверяем s += x ( 1 2 ) Результат: 650 нс
  • 27. Первый пример новый класс c l a s s X( o b j e c t ) : def __init__ ( s e l f , x ) : self .x = x def __call__ ( s e l f , x ) : return s e l f . x + x x = X(1); s = 0 # проверяем s += x ( 1 2 ) Результат: 650 → 404 нс
  • 28. "Старые" классы typedef struct { PyObject_HEAD PyObject ∗ cl_bases ; PyObject ∗cl_dict ; PyObject ∗cl_name ; PyObject ∗ cl_get / set / d e l a t t r ; } PyClassObject ;
  • 29. "Новые" классы typedef struct _ t y p e o b j e c t { PyObject_VAR_HEAD /∗ s k i p f i e l d s ∗/ h a s h f u n c tp_hash ; ternaryfunc tp_call ; /∗ s k i p f i e l d s ∗/ } PyTypeObject ;
  • 30. Первый пример странный результат class X: def __init__ ( s e l f , x ) : self .x = x def c a l l ( s e l f , x ) : return s e l f . x + x x = X(1); s = 0 # проверяем s += x . c a l l ( 1 2 ) Результат: 650 → 404 → 380 нс
  • 31. Первый пример замыкание def X( x ) : def i n n e r ( y ) : return x+y return i n n e r x = X(1); s = 0 # проверяем s += x ( 1 2 ) Результат: 650 → 404 → 380 → 228 нс
  • 32. Итераторы/генераторы просчитать генератором до 100 31 700 нс; просчитать итератором до 100 82 200 нс; itertools.count 7 400 нс; xrange(999) 7 500 нс. Проверка через list(islice(iterable, 100)).
  • 33. Чуть-чуть реальный пример Выделить тройки (uid, login, домашняя директория) из /etc/passwd. Это достаточно часть первого этапа обработки больших файлов.
  • 34. passwd: генератор def f u n c ( i a b l e ) : for l i n e in i a b l e : x = line . split ( ’ : ’) yield int (x [2]) , x [0] , x [5]
  • 35. passwd: итератор class func : def __init__ ( s e l f , i a b l e ) : self . iable = iable def __iter__ ( s e l f ) : return s e l f def n e x t ( s e l f ) : l i n e = s e l f . i a b l e . next () x = line . split ( ’ : ’) return i n t ( x [ 2 ] ) , x [ 0 ] , x [ 5 ]
  • 36. passwd: imap def f u n c ( l i n e ) : x = line . split ( ’ : ’) return i n t ( x [ 2 ] ) , x [ 0 ] , x [ 5 ]
  • 37. passwd Вывод: генераторы это не только удобно, но и быстро. 2.5 2.6 генератор 125 626 148 311 итератор 181 100 210 167 imap 146 084 167 703
  • 38. Некоторые общие вещи Некоторые способы ускорить встроенный код: interning; proxy-object; object cache.
  • 39. string interning Создание объекта требует дополнительных действий. Если мы используем одну и ту же строку постоянно, гораздо быстрее создать один раз python строку, а потом передавать ее в python API. Эта техника подходит не только для строк.
  • 40. string interning: пример while ( ( i t e m = P y I t e r _ N e x t ( i t e r a t o r ) ) != NULL) { PyObject ∗ f i e l d = PyObject_GetAttrString ( item , " t h " ) ; // PyObject ∗ f i e l d = // PyObject_GetAttr ( // item , i n t e r n e d _ t h ) ; ... Py_DECREF( i t e m ) ; }
  • 41. string interning: итог В вырожденных случаях C код будет медленнее чем Python код. python код 14 830 C-код, C строка 16 636 С-код, встроенная строка 8 862
  • 42. proxy object Если у вас есть развесистая структура нативных объектов, не надо для них всех создавать python объекты. Создание объектов по требованию экономит не только время создания родительского объекта, но и память.
  • 43. object cache Если объекты неизменяемые и одни объекты встречаются чаще чем другие, можно возвращать заранее созданные объекты. Хорошие примеры: целые числа, короткие строки, узел дерева без детей, единичные массивы.
  • 44. object cache создание 50 тысяч int(5) 450 мкс (9 нс); создание 50 тысяч int(5000) 760 мкс (15 нс); кеш объектов в данном случае дал прирост в 40%.
  • 45. Global Interpretor Lock Все видели картинку про два CPU bound треда? Картинка нагло украдена из статьи The Python GIL Visualized http://www.dabeaz.com/
  • 46. Global Interpretor Lock Во время работы встроенных функций можно разблокировать GIL, если мы не используем Python API. Хорошие примеры: py-lxml.
  • 47. Python API Сложно. Запутанно. Считать ссылки самому: Py_DECREF, Py_INCREF Брррр...
  • 48. Ужас w h i l e (( item = PyIter_Next ( i t e r a t o r )) != NULL) { PyObject ∗ f i e l d = PyObject_GetAttr ( item , i n t e r n e d _ t h ) ; i f ( f i e l d == NULL) { Py_DECREF( r e s u l t ) ; Py_DECREF( i t e m ) ; r e t u r n NULL ; } PyObject ∗nw = PyNumber_Add ( result , field ); Py_DECREF( r e s u l t ) ; ...
  • 49. Ужас d e f sum_th ( l s t ) : result = 0 for i in l s t : #! r e s u l t += i . t h #!!!111 return result Это гораздо проще!
  • 50. Cython Откомпилировав пример в Cython, я получил следующие результаты: Python код 14 830 C-код, C строка 16 636 С-код, встроенная строка 8 862 Cython код 7 067
  • 51. Выводы догнать Python’ом C не получиться; можно потерять 20% просто так; активно используя Cython можно неплохо ускорить программу; и мало потерять в выразительности.
  • 52. Спасибо за внимание.
  • 53. Вопросы?

×