Почему существует разница между созданием класса в 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 гб баранов
- Как форматировать вывод печати в фиксированную ширину?
- Сценарий Python, чтобы делать что-то в одно и то же время каждый день
- поиск дубликатов в списке списков
- Получить последнее исключение в pdb
- AttributeError: объект 'module' не имеет атрибута 'strptime'
- Как использовать функцию обратного вызова в python?
- Как я могу сделать пирамиду for-loop более кратким в Python?
- Как перехватывать исключения у рабочих в многопроцессорности
- Булева проверка не работает в функции
- Найти общую подстроку между двумя строками
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 >>>
- Как проверить, является ли переменная целой или строкой?
- Как удалить словари с дублирующимися значениями из вложенного словаря
- Согласовать каждый элемент списка с каждым элементом второго списка
- Python3 vs Python2 производительность списка / генератора
- Как сделать итерируемый класс в Python, в котором разрешен только определенный тип?
- Url расшифровывает UTF-8 в Python
- Захват определенных индексов списка в Python
- Сравнение / объединение двух словарей
- Выбор остановочного списка?
- Вызов, если __name__ == '__main__': в одном модуле от функции в другом модуле
- вызов главной функции не выполняется в python
- повышение эффективности кода: стандартное отклонение на раздвижных окнах