У меня есть Python script в файле, для запуска которого требуется более 30 секунд. Я пытаюсь профилировать его, поскольку я хотел бы сократить это время резко.
Я пытаюсь профилировать script с помощью cProfile
, но по существу все, что мне кажется, говорит, что да, главная script заняла много времени, но не дает такого рода я ожидал. На терминале я печатаю что-то вроде:
cat my_script_input.txt | python -m cProfile -s time my_script.py
Получаемые результаты:
<my_script_output>
683121 function calls (682169 primitive calls) in 32.133 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1 31.980 31.980 32.133 32.133 my_script.py:18(<module>)
121089 0.050 0.000 0.050 0.000 {method 'split' of 'str' objects}
121090 0.038 0.000 0.049 0.000 fileinput.py:243(next)
2 0.027 0.014 0.036 0.018 {method 'sort' of 'list' objects}
121089 0.009 0.000 0.009 0.000 {method 'strip' of 'str' objects}
201534 0.009 0.000 0.009 0.000 {method 'append' of 'list' objects}
100858 0.009 0.000 0.009 0.000 my_script.py:51(<lambda>)
952 0.008 0.000 0.008 0.000 {method 'readlines' of 'file' objects}
1904/952 0.003 0.000 0.011 0.000 fileinput.py:292(readline)
14412 0.001 0.000 0.001 0.000 {method 'add' of 'set' objects}
182 0.000 0.000 0.000 0.000 {method 'join' of 'str' objects}
1 0.000 0.000 0.000 0.000 fileinput.py:80(<module>)
1 0.000 0.000 0.000 0.000 fileinput.py:197(__init__)
1 0.000 0.000 0.000 0.000 fileinput.py:266(nextfile)
1 0.000 0.000 0.000 0.000 {isinstance}
1 0.000 0.000 0.000 0.000 fileinput.py:91(input)
1 0.000 0.000 0.000 0.000 fileinput.py:184(FileInput)
1 0.000 0.000 0.000 0.000 fileinput.py:240(__iter__)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
Это, кажется, не говорит мне ничего полезного. Подавляющее большинство времени просто перечисляется как:
ncalls tottime percall cumtime percall filename:lineno(function)
1 31.980 31.980 32.133 32.133 my_script.py:18(<module>)
В my_script.py
строка 18 представляет собой не что иное, как закрытие """
комментария блока заголовка файла, так что это не означает, что весь объем работы сосредоточен в строке 18. script в целом в основном состоящий из линейной обработки, в основном с разделением строк, сортировкой и настройкой, поэтому я ожидал, что большую часть времени вы перейдете к одному или нескольким из этих действий. Как бы то ни было, все время, сгруппированные в результатах cProfile, встречающиеся на линии комментариев, не имеют никакого смысла или, по крайней мере, не проливают свет на то, что на самом деле потребляет все время.
EDIT: Я построил минимальный рабочий пример, похожий на мой вышеприведенный случай, чтобы продемонстрировать одно и то же поведение:
mwe.py
import fileinput
for line in fileinput.input():
for i in range(10):
y = int(line.strip()) + int(line.strip())
И назовите его с помощью:
perl -e 'for(1..1000000){print "$_\n"}' | python -m cProfile -s time mwe.py
Чтобы получить результат:
22002536 function calls (22001694 primitive calls) in 9.433 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1 8.004 8.004 9.433 9.433 mwe.py:1(<module>)
20000000 1.021 0.000 1.021 0.000 {method 'strip' of 'str' objects}
1000001 0.270 0.000 0.301 0.000 fileinput.py:243(next)
1000000 0.107 0.000 0.107 0.000 {range}
842 0.024 0.000 0.024 0.000 {method 'readlines' of 'file' objects}
1684/842 0.007 0.000 0.032 0.000 fileinput.py:292(readline)
1 0.000 0.000 0.000 0.000 fileinput.py:80(<module>)
1 0.000 0.000 0.000 0.000 fileinput.py:91(input)
1 0.000 0.000 0.000 0.000 fileinput.py:197(__init__)
1 0.000 0.000 0.000 0.000 fileinput.py:184(FileInput)
1 0.000 0.000 0.000 0.000 fileinput.py:266(nextfile)
1 0.000 0.000 0.000 0.000 {isinstance}
1 0.000 0.000 0.000 0.000 fileinput.py:240(__iter__)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
Я как-то неправильно использую cProfile?