Этот ответ изначально содержал два разных решения: первое было основано на исправлении обезьян, а второе не работает для Python 3.7 и более поздних версий. Мы надеемся, что эта новая версия представляет собой лучший и более надежный подход.
Во-первых, стандартные инструменты измерения времени, такие как время, можно использовать для определения времени процессора программа, которая обычно нас интересует при тестировании производительности асинхронного приложения. Эти измерения также можно выполнить в python с помощью time.process_time() а> функция:
import time
real_time = time.time()
cpu_time = time.process_time()
time.sleep(1.)
sum(range(10**6))
real_time = time.time() - real_time
cpu_time = time.process_time() - cpu_time
print(f"CPU time: {cpu_time:.2f} s, Real time: {real_time:.2f} s")
См. ниже аналогичный вывод, полученный обоими методами:
$ /usr/bin/time -f "CPU time: %U s, Real time: %e s" python demo.py
CPU time: 0.02 s, Real time: 1.02 s # python output
CPU time: 0.03 s, Real time: 1.04 s # `time` output
В асинхронном приложении может случиться так, что какая-то синхронная часть программы в конечном итоге выполнит блокирующий вызов, эффективно предотвращая запуск других задач в цикле обработки событий. Таким образом, мы можем захотеть записывать отдельно время ожидания цикла обработки событий от времени, затрачиваемого другими задачами ввода-вывода.
Этого можно добиться путем создания подкласса селектора по умолчанию для выполнения некоторых операций по времени. операции и с помощью пользовательской политики цикла событий, чтобы установить все вверх. Этот фрагмент кода предоставляет такую политику вместе с менеджером контекста для печати различных метрик времени.
async def main():
print("~ Correct IO management ~")
with print_timing():
await asyncio.sleep(1)
sum(range(10**6))
print()
print("~ Incorrect IO management ~")
with print_timing():
time.sleep(0.2)
await asyncio.sleep(0.8)
sum(range(10**6))
print()
asyncio.set_event_loop_policy(TimedEventLoopPolicy())
asyncio.run(main(), debug=True)
Обратите внимание на разницу между этими двумя прогонами:
~ Correct IO management ~
CPU time: 0.016 s
Select time: 1.001 s
Other IO time: 0.000 s
Real time: 1.017 s
~ Incorrect IO management ~
CPU time: 0.016 s
Select time: 0.800 s
Other IO time: 0.200 s
Real time: 1.017 s
Также обратите внимание, что режим отладки asyncio может обнаруживать эти блокирующие операции:
Executing <Handle <TaskWakeupMethWrapper object at 0x7fd4835864f8>(<Future finis...events.py:396>) created at ~/miniconda/lib/python3.7/asyncio/futures.py:288> took 0.243 seconds
person
Vincent
schedule
16.01.2016