SlideShare a Scribd company logo
1 of 53
Download to read offline
Python и его тормоза
Можно ли заставить питон работать быстро


  Александр Шигин, shigin@rambler-co.ru


             Rambler, 2010
О чем я буду говорить


     краткий рассказ о времени;
     простые примеры;
     быстрые простые примеры;
     глупые примеры;
     и еще глупости.
Время

 Первый пример    real time.
 $ time sleep 5

 real    0m5.006s
 user    0m0.004s
 sys 0m0.008s
Время

 Второй пример   user time.
 $ time openssl rand 
 > -out /dev/null 9000000

 real    0m0.421s
 user    0m0.388s
 sys 0m0.004s
Время
 Третий пример   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
Время
 Для процесса есть три времени:
 real, CPU, system.
     обычно нас интересует real time;
     но если мы запускаем много
     параллельных задач мы можем
     упереться в CPU (user) time;
     системное время в основном
     зависит от количества
     системных вызовов.
Чуть-чуть чисел

     вызов функции по указателю (нс)
           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]
Чуть-чуть числа про объекты


     создание чистого python объекта
     210 нс;
     создание python объекта с
     пустым __slots__ 120 нс;
     создание embedded python
     объекта 150 нс.
Создание объектов

     создание кортежа из двух
     элементов 31 нс;
     создание класса с двумя полями
     690 нс;
     распаковка кортежа 130 нс;
     доступ к полю кортежа 105 нс;
     доступ к полю объекта 110 нс.
Маленький пример

 Как лучше хранить неизменяемые
 пары чисел? Учебный пример
 нахождение центра масс.
    кортеж из трех чисел: x, y,
    масса;
    класс с тремя полями;
    словарь.
Маленький пример: класс


  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)]
Маленький пример: класс


  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 нс
Маленький пример: объекты



    новый класс ≈ 4100 нс;
    в 2.5 новый класс ≈ 4750 нс.
    __slots__ 2.6 ≈ 4050 нс, 2.5
    4500 нс.
Маленький пример: кортеж


  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 нс
Маленький пример: словарь


  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 нс
Маленький пример

 Итог: используйте кортежи.
           Меряем      2.5    2.6
      старый класс    4050   3900
       новый класс    4750   4130
        со слотами    4490   4050
           кортежи    2250   2210
            словарь   2700   2630
Глупый пример


  Смешные числа Фибоначи. Как
  лучше хранить текущую пару
  чисел?

  В этом примере мы будем изменять
  пару.
Глупый пример: класс


  Первый вариант.
  class F :
      def __init__ ( s e l f , x , y ) :
            self .x = x
            self .y = y
Глупый пример: класс

 Проверяем:
 x = F ( 1 , 1)
 t = x.y
 x.y = x.x + x.y
 x.x = t
 # так 4 раза
 Результат: 2830 нс
Глупый пример: классы



     x.x, x.y = x.y, x.x + x.y
     немного медленнее;
     надо повторяться про новые
     классы?
Глупый пример: кортеж


 Проверяем:
 x = 1, 1
 x = x [1] , x [0] + x [1]
 # так 4 раза
 Результат: 1410 нс
Глупый пример: словарь

 Проверяем:
 x = d i c t ( x =1, y=1)
 t = x [ ’y ’ ]
 x[ ’y ’ ] = x[ ’x ’ ] + x[ ’y ’ ]
 x[ ’x ’ ] = t
 # так 4 раза
 Результат: 2500 нс
Глупый пример
  Итог: даже в этом случае
  используйте кортежи.
            Меряем      2.5    2.6
       старый класс    2910   2835
        новый класс    4630   3468
         со слотами    4065   3212
            кортежи    1550   1410
             словарь   2810   2550
Замыкания



    вызов замыкания 145 нс;
    возврат значения из замыкания
    166 нс;
    создание замыкания 380 нс;
Первый пример

 Создадим класс, экземпляры
 которого будут возвращать свой
 аргумент, увеличенный на некое
 число, которое мы передадим при
 создании класса.
      x = X( 1 4 )
      x (15)       # −> 29
Первый пример           старые классы

  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 нс
Первый пример              новый класс

  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 нс
"Старые" классы


  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 ;
"Новые" классы


  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 ;
Первый пример               странный результат

  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 нс
Первый пример            замыкание

  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 нс
Итераторы/генераторы

      просчитать генератором до
      100 31 700 нс;
      просчитать итератором до
      100 82 200 нс;
      itertools.count 7 400 нс;
      xrange(999) 7 500 нс.
  Проверка через list(islice(iterable, 100)).
Чуть-чуть реальный пример


  Выделить тройки (uid, login,
  домашняя директория) из
  /etc/passwd.

  Это достаточно часть первого этапа
  обработки больших файлов.
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]
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 ]
passwd: imap




  def f u n c ( l i n e ) :
      x = line . split ( ’ : ’)
      return i n t ( x [ 2 ] ) , x [ 0 ] , x [ 5 ]
passwd

  Вывод: генераторы это не только
  удобно, но и быстро.
                     2.5     2.6
         генератор 125 626 148 311
          итератор 181 100 210 167
              imap 146 084 167 703
Некоторые общие вещи


  Некоторые способы ускорить
  встроенный код:
    interning;
    proxy-object;
    object cache.
string interning

      Создание объекта требует
      дополнительных действий.
      Если мы используем одну и ту
      же строку постоянно, гораздо
      быстрее создать один раз python
      строку, а потом передавать ее в
      python API.
      Эта техника подходит не только
      для строк.
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 ) ;
  }
string interning: итог

  В вырожденных случаях C код
  будет медленнее чем Python код.

                   python код 14 830
              C-код, C строка 16 636
    С-код, встроенная строка 8 862
proxy object

     Если у вас есть развесистая
     структура нативных
     объектов, не надо для них всех
     создавать python объекты.
     Создание объектов по
     требованию экономит не только
     время создания родительского
     объекта, но и память.
object cache

     Если объекты неизменяемые и
     одни объекты встречаются чаще
     чем другие, можно возвращать
     заранее созданные объекты.
     Хорошие примеры: целые числа,
     короткие строки, узел дерева без
     детей, единичные массивы.
object cache


     создание 50 тысяч int(5) 450
     мкс (9 нс);
     создание 50 тысяч int(5000)
     760 мкс (15 нс);
     кеш объектов в данном случае
     дал прирост в 40%.
Global Interpretor Lock

  Все видели картинку про два CPU
  bound треда?




  Картинка нагло украдена из статьи The Python GIL
  Visualized http://www.dabeaz.com/
Global Interpretor Lock


     Во время работы встроенных
     функций можно разблокировать
     GIL, если мы не используем
     Python API.
     Хорошие примеры: py-lxml.
Python API


     Сложно.
     Запутанно.
     Считать ссылки самому:
     Py_DECREF, Py_INCREF

  Брррр...
Ужас
 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 ) ;
          ...
Ужас


 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

 Это гораздо проще!
Cython

  Откомпилировав пример в Cython,
  я получил следующие результаты:
                 Python код 14 830
             C-код, C строка 16 636
   С-код, встроенная строка 8 862
              Cython код 7 067
Выводы

    догнать Python’ом C не
    получиться;
    можно потерять 20% просто так;
    активно используя Cython
    можно неплохо ускорить
    программу;
    и мало потерять в
    выразительности.
Спасибо за
внимание.
Вопросы?

More Related Content

What's hot

Лекция 10. Классы 2.
Лекция 10. Классы 2.Лекция 10. Классы 2.
Лекция 10. Классы 2.Roman Brovko
 
Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8. Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8. Dima Dzuba
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4 Dima Dzuba
 
Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Dima Dzuba
 
Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Roman Brovko
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.Roman Brovko
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка DjangoVladimir Rudnyh
 
Оптимизация производительности Python
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности PythonPyNSK
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.Roman Brovko
 
Лекция 6. Классы 1.
Лекция 6. Классы 1.Лекция 6. Классы 1.
Лекция 6. Классы 1.Roman Brovko
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Яковенко Кирилл
 
Лекция 1. Начало.
Лекция 1. Начало.Лекция 1. Начало.
Лекция 1. Начало.Roman Brovko
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Dima Dzuba
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILRoman Brovko
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptDenis Latushkin
 
Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?PyNSK
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Roman Brovko
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
 
Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.Roman Brovko
 
8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)Smolensk Computer Science Club
 

What's hot (20)

Лекция 10. Классы 2.
Лекция 10. Классы 2.Лекция 10. Классы 2.
Лекция 10. Классы 2.
 
Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8. Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8.
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
 
Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10
 
Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка Django
 
Оптимизация производительности Python
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности Python
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.
 
Лекция 6. Классы 1.
Лекция 6. Классы 1.Лекция 6. Классы 1.
Лекция 6. Классы 1.
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
 
Лекция 1. Начало.
Лекция 1. Начало.Лекция 1. Начало.
Лекция 1. Начало.
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
 
Лекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GILЛекция 13. Многопоточность и GIL
Лекция 13. Многопоточность и GIL
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в Javascript
 
Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?Магия в Python: Дескрипторы. Что это?
Магия в Python: Дескрипторы. Что это?
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.Лекция 7. Исключения и менеджеры контекста.
Лекция 7. Исключения и менеджеры контекста.
 
8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)
 

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

Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Yandex
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
C#. От основ к эффективному коду
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному кодуVasiliy Deynega
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in actionYuri Trukhin
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий solit
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кодаAndrey Karpov
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода Pavel Tsukanov
 
Математическое обоснование S.O.L.I.D принципов
Математическое обоснование S.O.L.I.D принциповМатематическое обоснование S.O.L.I.D принципов
Математическое обоснование S.O.L.I.D принциповetyumentcev
 
Haskell Lite - presentation for DevDay about Haskell language
Haskell Lite - presentation for DevDay about Haskell languageHaskell Lite - presentation for DevDay about Haskell language
Haskell Lite - presentation for DevDay about Haskell languageAlexander Granin
 
Haskell
HaskellHaskell
HaskellDevDay
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"LogeekNightUkraine
 
«QuickCheck в Python: проверка гипотез и поиск ошибок», Александр Шорин, Ramb...
«QuickCheck в Python: проверка гипотез и поиск ошибок», Александр Шорин, Ramb...«QuickCheck в Python: проверка гипотез и поиск ошибок», Александр Шорин, Ramb...
«QuickCheck в Python: проверка гипотез и поиск ошибок», Александр Шорин, Ramb...Mail.ru Group
 
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципыHappyDev
 
Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Tatyanazaxarova
 
Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Technopark
 
Мастер класс по алгоритмам. Часть 1
Мастер класс по алгоритмам. Часть 1Мастер класс по алгоритмам. Часть 1
Мастер класс по алгоритмам. Часть 1Pavel Egorov
 
Learning from Swift sources, Иван Сметанин
Learning from Swift sources, Иван СметанинLearning from Swift sources, Иван Сметанин
Learning from Swift sources, Иван СметанинMail.ru Group
 

Similar to Python и его тормоза (20)

Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
C#. От основ к эффективному коду
C#. От основ к эффективному кодуC#. От основ к эффективному коду
C#. От основ к эффективному коду
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in action
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 
Charming python sc2-8
Charming python sc2-8Charming python sc2-8
Charming python sc2-8
 
Bytecode
BytecodeBytecode
Bytecode
 
Математическое обоснование S.O.L.I.D принципов
Математическое обоснование S.O.L.I.D принциповМатематическое обоснование S.O.L.I.D принципов
Математическое обоснование S.O.L.I.D принципов
 
Haskell Lite - presentation for DevDay about Haskell language
Haskell Lite - presentation for DevDay about Haskell languageHaskell Lite - presentation for DevDay about Haskell language
Haskell Lite - presentation for DevDay about Haskell language
 
Haskell
HaskellHaskell
Haskell
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"
 
«QuickCheck в Python: проверка гипотез и поиск ошибок», Александр Шорин, Ramb...
«QuickCheck в Python: проверка гипотез и поиск ошибок», Александр Шорин, Ramb...«QuickCheck в Python: проверка гипотез и поиск ошибок», Александр Шорин, Ramb...
«QuickCheck в Python: проверка гипотез и поиск ошибок», Александр Шорин, Ramb...
 
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы
2014.12.06 04 Евгений Тюменцев — Откуда появились s.o.l.i.d. принципы
 
Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська Статический анализ: ошибки в медиаплеере и безглючная аська
Статический анализ: ошибки в медиаплеере и безглючная аська
 
Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1Алгоритмы и структуры данных осень 2013 лекция 1
Алгоритмы и структуры данных осень 2013 лекция 1
 
Рекурсия. Поиск
Рекурсия. ПоискРекурсия. Поиск
Рекурсия. Поиск
 
Мастер класс по алгоритмам. Часть 1
Мастер класс по алгоритмам. Часть 1Мастер класс по алгоритмам. Часть 1
Мастер класс по алгоритмам. Часть 1
 
Learning from Swift sources, Иван Сметанин
Learning from Swift sources, Иван СметанинLearning from Swift sources, Иван Сметанин
Learning from Swift sources, Иван Сметанин
 

Recently uploaded (9)

CVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdfCVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdf
 
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
 
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdfMalware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
 
Cyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdfCyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdf
 
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdfСИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
 
2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf
 
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
 
Ransomware_Q3 2023. The report [RU].pdf
Ransomware_Q3 2023.  The report [RU].pdfRansomware_Q3 2023.  The report [RU].pdf
Ransomware_Q3 2023. The report [RU].pdf
 
MS Navigating Incident Response [RU].pdf
MS Navigating Incident Response [RU].pdfMS Navigating Incident Response [RU].pdf
MS Navigating Incident Response [RU].pdf
 

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

  • 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 можно неплохо ускорить программу; и мало потерять в выразительности.