Какова связь между временем процессора, измеряемым профилировщиком Python, и реальным, временем пользователя и sys?

Использование встроенного профилировщика python с запуском скрипта в одном процессоре (и без многопоточности)

time python -m cProfile myscript.py 

время процессора, сообщенное профилировщиком, составляет 345,710 секунды процессора

 24184348 function calls (24183732 primitive calls) in 345.710 CPU seconds 

и реальное , пользовательское и sys время:

 real 5m45.926s user 1m59.340s sys 0m39.452s 

Как вы можете видеть, время процессора почти в реальном времени (345.710 = 5m45.710s).

Итак, учитывая этот результат, можно ли предположить, что время процессора, указанное профилировщиком, включает в себя временные срезы, используемые другими процессами и время, которое процесс тратит на блокировку? т. е. время процессорного времени профайлера – это не время процесса (пользователь + sys), а время настенных часов, как это объясняется в « Что означает« реальный »,« пользователь »и« sys »в выводе времени (1)?

Большое спасибо заранее

  • Запросы Django ORM не позволяют выбирать новые объекты
  • Варианты использования для __del__
  • Возможные значения из sys.platform?
  • Реализовать доступ к списку как индекс в Python
  • Как создать Pandas DataFrame из строки
  • Как запросить отличные результаты в mongodb с помощью python?
  • Понимание различий в производительности
  • Функция Iterator (iter ()) в Python
  • 3 Solutions collect form web for “Какова связь между временем процессора, измеряемым профилировщиком Python, и реальным, временем пользователя и sys?”

    Это прекрасно отвечает на детали реальных, пользовательских и sys-таймингов. Цитировать:

    • «Реальный» – это время настенных часов – время от начала до конца вызова. Это все прошедшее время, включая срезы времени, используемые другими процессами и время, которое процесс тратит на блокировку (например, если он ожидает завершения ввода-вывода).

    • «Пользователь» – это количество времени процессора, затраченного в коде пользовательского режима (вне ядра) внутри процесса. Это только фактическое время процессора, используемое при выполнении процесса. Другие процессы и время, которые процесс тратит на блокировку, не учитываются в этой цифре.

    • «Sys» – это количество процессорного времени, затраченного на ядро ​​в процессе. Это означает выполнение времени процессора, затраченного на системные вызовы в ядре, в отличие от кода библиотеки, который все еще работает в пользовательском пространстве. Подобно «пользователю», это только процессорное время, используемое процессом.

    Из приведенного выше объяснения это похоже на то, что время User + Sys должно быть равным секундам CPU. Вместо этого он ближе к «реальному» времени. Странный!

    Для этого есть справедливое объяснение. Время «Пользователь» не включает секунды ЦП, затраченные на операции ввода-вывода в процессе. Это просто измеряет время процессора, затрачиваемое на код пользовательского режима в памяти . Эмпирическое правило:

    real time = user + sys + время ввода / вывода + время запуска интерпретатора + время компиляции байткода

    Чтобы проверить это, я сделал urllib2.urlopen(urllib2.Request(url)) вызывающий интенсивный ввод-вывод. Вот результаты:

      100792 function calls (98867 primitive calls) in 2.076 CPU seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 512 0.719 0.001 0.719 0.001 {method 'recv' of '_socket.socket' objects} 1 0.464 0.464 0.473 0.473 {_socket.getaddrinfo} 1 0.352 0.352 0.352 0.352 <string>:1(connect) 1 0.248 0.248 0.348 0.348 common_functions.py:1(<module>) 1 0.022 0.022 0.075 0.075 __init__.py:2(<module>) 1 0.017 0.017 0.030 0.030 urllib.py:1442(getproxies_macosx_sysconf) 330/67 0.012 0.000 0.031 0.000 sre_parse.py:385(_parse) real 0m2.255s user 0m0.352s sys 0m0.093s 

    Здесь в операциях ввода-вывода (в основном _socket.socket и _socket.getaddrinfo ) потреблялось 2.076- (0.352 + 0.093), т. Е. 1,631 процессорных сек. Остальное время, 2.255-2.076, были потрачены на холодный старт кода.

    Надеюсь, это было полезно.

    Обновление . В нескольких ядрах, где несколько процессоров работают параллельно, случай немного отличается. Общее количество секунд CPU, о которых сообщает cProfile, – это сумма времени, затрачиваемого всеми процессорами в отдельности. Например, в двухъядерной системе, если один процессор работает в течение 10 секунд. Параллельно другой процессор работает в течение 15 секунд. Общее количество секунд CPU будет составлять 25 секунд. Хотя время в реальном времени может составлять всего 15 секунд. Следовательно, время процессора может быть больше, чем в режиме реального времени в многоядерных системах. Поскольку процессоры работают параллельно

    Я был озадачен той же проблемой.

    Ответ заключается в том, что cProfile использует время разгона. И его результат был исторически ошибочным, но теперь он исправлен («CPU» в «CPU seconds» был удален). Я не знаю точно, когда, но Python 2.6.6 в Debian 6.0 имеет ошибку, а Python 2.7.3 в Debian 7.0 в порядке.

    Это вызывает недоумение, поскольку большинство профилировщиков учитывают время, затрачиваемое на процессор, а не время настенного времени. Но это «дешевый» профилировщик.

    Документ http://docs.python.org/2/library/profile.html#limitations объясняет – непонятно – что время основано на методах тикающего разгона, а не метода getrusage () или ptrace.

    Если вы проверите код ( http://hg.python.org/cpython/file/44f455e6163d/Modules/_lsprof.c ), вы можете проверить, что он основан на QueryPerformanceFrequency / gettimeofday.

    Джерримус прав о том, что тайм-ауты «время» и «время» не могут совпадать, поскольку cProfile запускается только после компиляции кода. Но кроме того, его «реальное» уравнение является фиктивным.

    Разница между wallclock и user + sys может лежать во множестве разных факторов, таких как ввод-вывод от имени вашего процесса или от имени любых других процессов, включая само ядро ​​(свопинг, ведение журнала и т. Д.) Или время процессора, затрачиваемое на другие процессов или ожидания чего-либо от имени вашего процесса, который не может быть учтен, потому что это удаленный ressource (сетевой или косвенный через NFS или iSCSI) и т. д. Вы называете это.

    Профайлер Python по умолчанию измеряет время стены, но может быть сделан для измерения времени процессора с использованием пользовательской функции таймера. Следующие работы работают под Linux, но не Windows (поскольку time.clock измеряет время на стене в Windows):

     import cProfile import time def idleWait(): time.sleep(10) def busyWait(): t = time.time() + 10 while time.time() < t: pass def target(): idleWait() busyWait() print "Wall time:" p = cProfile.Profile() p.runcall(target) p.print_stats() print "CPU time:" p = cProfile.Profile(time.clock) p.runcall(target) p.print_stats() 

    Первый прогон профиля покажет 20 секунд, и примерно половина из них потрачена time.sleep . Второй показывает 10 секунд, и ни один из них не провел time.sleep .

    Python - лучший язык программирования в мире.