Совершенно очевидно, как визуализировать обычный стек вызовов и подсчитать внутреннее и внешнее время выполнения. Однако, если иметь дело с сопрограммами, стек вызовов может выглядеть довольно беспорядочно. Я имею в виду, что сопрограмма может передать выполнение не своему родителю, а другой сопрограмме (например, greenlet ). Есть ли какие-то общие способы сделать согласованные выходные данные профилирования для таких сценариев?
Существуют ли какие-то общие методы для профилирования кода на основе сопрограмм?
Ответы (1)
Подумайте об одном образце стека для всех потоков одновременно.
Что вам нужно знать, так это - кто кого ждет и почему. Обычно, если функция A находится выше B в стеке, это означает, что A ожидает возврата B, и причина в том, что A хотел, чтобы B что-то сделал. Если вы посмотрите на весь стек для одного потока, вы получите цепочку причин, по которым эта конкретная наносекунда тратится этим потоком. Если вы ищете скорость, вы ищете цепочки причин, которые в целом вам не нужны (потому что есть слабое звено). Это работает, даже если цепочка заканчивается вводом-выводом. Если это пользовательский ввод, он просто ждет пользователя. Но если это вывод, или дисковый ввод-вывод, или старая старая загрузка ЦП, вы можете сделать что-то, чтобы уменьшить его и получить прирост производительности (если вы видите ту же проблему на 2 или более образцах).
Что, если поток A ожидает поток B? Тогда то, что вы видите в нижней части стека A, — это функция, ожидающая другого потока. Вам нужно выяснить, какой поток B, и посмотреть на его стек, потому что чем дольше это занимает, тем дольше A. Так что это сложнее, но, конечно же, вы не боитесь этого.
Я говорю здесь о ручном профилировании, когда вы сами берете образцы в отладчике и уделяете все свое внимание каждому образцу. Инструменты профилирования склонны считать, что вы ленивы и вам нужны только цифры, и если из этих цифр ничего не выходит, вы будете счастливы, потому что ничего не нашли. На самом деле, если какая-то глупая ненужная деятельность занимает 30% времени, то в среднем количество сэмплов, которое вам нужно, чтобы увидеть его дважды, составляет 2/0,3 = 6,67 сэмплов (небольшое число), и вполне вероятно, что вы будете увидеть его, и профилировщик не будет. Это случайная пауза.