Почему существует разница между созданием класса в python 2.7 и производительности python 3.4

from timeit import Timer as T def calc(n): return T("class CLS(object): pass").timeit(n) print(calc(90000)) print(calc(90000)) print(calc(90000)) # python3.4 1.1714721370008192 1.0723806529986177 1.111804607000522 # python2.7 15.7533519268 16.7191421986 16.8397979736 

Почему существует такая разница в времени создания класса с использованием разных версий python? Протестировано на той же машине:

  • i5-3450 CPU @ 3,10 ГГц
  • 8 гб баранов

2 Solutions collect form web for “Почему существует разница между созданием класса в python 2.7 и производительности python 3.4”

timeit отключает сборщик мусора, который в противном случае нарушает циклы, которые сохраняют объект класса живым. Таким образом, ни один из классов не освобождается, пока не закончится.

object.__subclasses__() ссылается на эти классы через внутренний набор слабых ссылок. Старая реализация tp_subclasses на основе списка tp_subclasses поиск по всему списку каждый раз, чтобы найти мертвую ссылку, которую можно заменить. Этот процесс занимает больше времени с каждым дополнительным подклассом. С другой стороны, новый дизайн на основе dict в 3.4 может добавить ссылку в постоянное время. См. Вопрос 17936 .


Спасибо @MichaelYounkin за то, что он указывает, что это также медленно в 3.2. Первоначально я попытался сократить разницу в производительности до изменения в распределении малогабаритных объектов между 2.x и 3.x, но после прочтения его комментария я обнаружил, что даже 3.3 был значительно медленнее 3.4. Поэтому я просмотрел файл-файл typeobject.c, чтобы просмотреть последние изменения.

Ну, проблема, похоже, связана с классами старого стиля и нового стиля в python 2.7.

В python 3.4 вы можете видеть, что разница между использованием объекта и его использованием – это просто загрузка символа (не такая значимая):

 C:\TEMP>C:\Python34\python.exe Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> >>> def a(): ... class A(object): pass ... >>> def b(): ... class B(): pass ... >>> import dis >>> dis.dis(a) 2 0 LOAD_BUILD_CLASS 1 LOAD_CONST 1 (<code object A at 0x020B8F20, file "<stdin>", line 2>) 4 LOAD_CONST 2 ('A') 7 MAKE_FUNCTION 0 10 LOAD_CONST 2 ('A') 13 LOAD_GLOBAL 0 (object) # Extra step, not that expensive. 16 CALL_FUNCTION 3 (3 positional, 0 keyword pair) 19 STORE_FAST 0 (A) 22 LOAD_CONST 0 (None) 25 RETURN_VALUE >>> dis.dis(b) 2 0 LOAD_BUILD_CLASS 1 LOAD_CONST 1 (<code object B at 0x020B8D40, file "<stdin>", line 2>) 4 LOAD_CONST 2 ('B') 7 MAKE_FUNCTION 0 10 LOAD_CONST 2 ('B') 13 CALL_FUNCTION 2 (2 positional, 0 keyword pair) 16 STORE_FAST 0 (B) 19 LOAD_CONST 0 (None) 22 RETURN_VALUE >>> 

Хотя на Python 2.7 у вас есть еще один шаг, который включает LOAD_TUPLE:

 C:\Users\jsargiot\Downloads\so>C:\Python27\python.exe Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> >>> def a(): ... class A(object): pass ... >>> def b(): ... class B(): pass ... >>> import dis >>> dis.dis(a) 2 0 LOAD_CONST 1 ('A') 3 LOAD_GLOBAL 0 (object) # First extra step (just like 3.4) 6 BUILD_TUPLE 1 # Second extra step, expensive 9 LOAD_CONST 2 (<code object A at 01EAEA88, file "<stdin>", line 2>) 12 MAKE_FUNCTION 0 15 CALL_FUNCTION 0 18 BUILD_CLASS 19 STORE_FAST 0 (A) 22 LOAD_CONST 0 (None) 25 RETURN_VALUE >>> dis.dis(b) 2 0 LOAD_CONST 1 ('B') 3 LOAD_CONST 3 (()) 6 LOAD_CONST 2 (<code object B at 01EB8EC0, file "<stdin>", line 2>) 9 MAKE_FUNCTION 0 12 CALL_FUNCTION 0 15 BUILD_CLASS 16 STORE_FAST 0 (B) 19 LOAD_CONST 0 (None) 22 RETURN_VALUE >>> 
  • Python проверяет, существует ли функция без попытки
  • Python перебирает строку и сопоставляет ее с шаблоном подстановки
  • повышение эффективности кода: стандартное отклонение на раздвижных окнах
  • Объединить переименование словаря Python в список словарей
  • Как проверить, является ли переменная целой или строкой?
  • Быстрое преобразование временных меток для расчета продолжительности
  • Понимание __getattribute__
  • Сортировка в python - как отсортировать список, содержащий буквенно-цифровые значения?
  • Python - лучший язык программирования в мире.