Как да използвам timeit за профилиране на Python код

По дизайн Python поставя удобството, четливостта и лекотата на използване пред производителността. Но това не означава, че трябва да се задоволите с бавен код на Python. Вероятно можете да направите нещо, за да го ускорите.

Сред наличните инструменти за профилиране на изпълнението на кода на Python, най-простият е timeitмодулът. timeitсе използва за измерване на скоростта на малки фрагменти от код - няколко реда, функция - чрез изпълнение на кода хиляди или дори милиони пъти и отчитане колко време са изпълнени тези екзекуции.

timeitе най-полезен за сравняване на два или три различни начина да направите нещо и да видите кой е най-бързият. Например, цикъл, който се изпълнява за хиляди итерации, е често срещано пречка за Python. Ако можете да намерите начин да ускорите изпълнението на този цикъл - да речем, като използвате вградени Python вместо ръчно написан код - можете да получите измеримо подобрение на производителността.

Прост пример за време на Python

Ето един прост пример за това как timeitработи:

def f1 (): за n в обхват (100): предайте def f2 (): n = 0, докато n <100: n + = 1, ако __name__ == "__main__": импортиране timeit print (timeit.timeit (f1, number = 100000)) print (timeit.timeit (f2, number = 100000)) 

Тази програма сравнява производителността на два начина за итерация през цикъл 100 пъти: чрез използване на вградената range функция на Python  ( f1) и чрез увеличаване на променлива ( f2). timeit изпълнява всеки от тези подходи 100 000 пъти и осигурява общо време на изпълнение за всеки. По подразбиране  timeit използва един милион изпълнения, но този пример показва как можете да зададете броя на изпълненията на всяка цифра, която изглежда подходяща.

Резултатите (от процесор Intel i7-3770K):

0,1252315

0,45453989999999994

Очевидно  range подходът е много по-бърз, с фактор около 3,75. Това не е изненадващо; използването на вграден Python обикновено дава по-добра производителност от ръчното манипулиране на Python обекти.

Използвайте Python timeit, като предадете низ

Друг начин за използване  timeit е предаването на низ, който се оценява като програма на Python:

време за импортиране

print (timeit.timeit ('за n в обхват (100): преминаване'))

Това може да се направи и от командния ред:

python -m timeit "за n в обхват (100): pass"

Като цяло обаче е по-лесно да използвате техниката, показана по-горе, тъй като не е нужно да слагате неудобно кода си в текстов низ.

Python timeit съвети

Колкото и да timeit е полезно  , имайте предвид тези предупреждения как да го използвате.

Избягвайте да използвате timeit за профилиране на цялата програма

Нищо не казва, че  не можете да  определите време за цяла програма  timeit. Един прост скрипт от 10 реда, например, не е лош кандидат за профилиране по този начин.

Но има по-добри инструменти за тази работа - например cProfile модулът на Python  , който генерира много по-подробна статистика за ефективността на цялата ви програма. timeit работи най-добре с един компонент или кодов фрагмент - отново функция или няколко реда код. Всичко повече от това обикновено ще генерира резултати, които са твърде шумни и непоследователни, за да ви дадат значима информация за ефективността.

Освен това, ако програмата, която профилирате, отнема много минути,  timeit няма да бъде от особена полза. Първо, ще отнеме твърде много време, за да стартирате кода повече от няколко пъти, така че събраните тайминги ще бъдат много груби. За двама други инструменти са по-подходящи за работата.

Извършвайте няколко пъти, изпълнява се на различни машини

Програмите не се изпълняват със същата скорост всеки път. Съвременните изчислителни среди въвеждат много несигурност - конкуренция с други програми за ресурси, поведение в кеша, планиране и т.н. timeit се опитва да компенсира това чрез изпълнение на кода ad infinitum, но все пак е добра идея да се обединят множество изпитания. Трябва да пуснете  timeit профил много пъти, да хвърлите най-лошите и най-добрите резултати и да осредните останалите.

И накрая, помага и провеждането на един и същ тест на различни системи: как ще се държи нещо свързано с диска на SSD спрямо конвенционален въртящ се твърд диск? Както при всеки друг въпрос относно производителността - не се досещайте, тествайте.