Вы слишком возражаете, если я немного расскажу о профилировании, что работает, а что нет?
Давайте составим искусственную программу, некоторые из утверждений которой выполняют работу, которую можно оптимизировать -т.е. они на самом деле не нужны.Это «узкие места».
Подпрограмма foo
запускает цикл с привязкой к процессору, который занимает одну секунду.Также предположим, что подпрограммы CALL и RETURN занимают незначительное или нулевое время по сравнению со всем остальным.
Подпрограмма bar
вызывает foo
10 раз, но 9 из них не нужны, чего вы не знаете впродвигаться вперед и не может сказать, пока ваше внимание не будет направлено туда.
Подпрограммы A
, B
, C
, ..., J
- это 10 подпрограмм, каждая из которых вызывает bar
один раз.
Процедура верхнего уровня main
вызывает каждый из A
- J
один раз.
Таким образом, общее дерево вызовов выглядит следующим образом:
main
A
bar
foo
foo
... total 10 times for 10 seconds
B
bar
foo
foo
...
...
J
...
(finished)
Сколько времени это займет?Очевидно, 100 секунд.
Теперь давайте рассмотрим стратегии профилирования.Стековые сэмплы (например, 1000 сэмплов) берутся через одинаковые интервалы.Да.foo
занимает 100% собственного времени.Это настоящая «горячая точка».Это поможет вам найти узкое место?Нет. Потому что его нет в foo
.
Что такое горячий путь?Итак, сэмплы стека выглядят так:
main -> A -> bar -> foo (100 сэмплов или 10%)
main -> B -> bar -> foo (100 сэмплов,или 10%)
...
main -> J -> bar -> foo (100 выборок или 10%)
Есть 10 горячих путей, ини один из них не выглядит достаточно большим, чтобы ускорить процесс.
ЕСЛИ ВЫ БЫЛИ УГЛЯТЬ, И ЕСЛИ ПРОФИЛЬ РАЗРЕШЕН, вы можете сделать bar
«корнем» своего дерева вызовов.Тогда вы увидите это:
bar -> foo (1000 samples, or 100%)
Тогда вы будете знать, что foo
и bar
каждый независимо друг от друга несут ответственность за 100% времени и, следовательно, являются местами для поиска оптимизации.Вы смотрите на foo
, но, конечно, вы знаете, что проблема не в этом.Затем вы смотрите на bar
и видите 10 звонков на foo
, и вы видите, что 9 из них не нужны.Проблема решена.
ЕСЛИ ВЫ НЕ ПРОИЗОШЛИ, ЧТОБЫ УГАДАТЬ, и вместо этого профилировщик просто показал вам процент выборок, содержащих каждую процедуру, вы увидите это:
main 100%
bar 100%
foo 100%
A 10%
B 10%
...
J 10%
Это говорит вамсмотреть на main
, bar
и foo
.Вы видите, что main
и foo
невинны.Вы смотрите, где bar
вызывает foo
, и вы видите проблему, поэтому она решена.
Еще яснее, если помимо показа вам функций, вам могут быть показаны строки, где эти функции вызываются,Таким образом, вы можете найти проблему независимо от того, насколько велики функции с точки зрения исходного текста.
СЕЙЧАС, давайте изменим foo
так, чтобы он выполнял sleep(oneSecond)
вместо привязки к процессору.Как это меняет ситуацию?
Что это значит, что настенные часы все равно занимают 100 секунд, но время ЦП равно нулю.Сэмплирование в сэмплере только для процессора покажет ничего .
Так что теперь вам предлагают попробовать инструментальные средства вместо сэмплирования.Содержится среди всего, что он говорит вам, он также сообщает вам проценты, показанные выше, так что в этом случае вы могли бы найти проблему, предполагая, что bar
не было очень большим.(Могут быть причины для написания небольших функций, но должно ли удовлетворение профилировщика быть одной из них?)
На самом деле, главное, что не так с сэмплером, это то, что он не может сэмплировать во время sleep
(или я/ O или другая блокировка), и он не показывает проценты строки кода, только проценты функции.
Кстати, 1000 выборок дают хорошие точные проценты.Предположим, вы взяли меньше образцов.Сколько вам на самом деле нужно найти узкое место?Что ж, поскольку узкое место в стеке находится в 90% случаев, если вы взяли только 10 образцов, это было бы примерно на 9 из них, так что вы все равно бы это увидели.Если вы взяли всего 3 образца, вероятность его появления на двух или более из них составляет 97,2%. **
Высокая частота выборки сильно переоценивается, когда ваша цель - найти узкие места.
В любом случае, поэтому я полагаюсь на случайную паузу .
** Как я получил 97,2 процента? Думайте об этом как о подбрасывании монеты 3 раза, очень несправедливой монеты, где «1» означает видеть узкое место. Есть 8 возможностей:
#1s probabality
0 0 0 0 0.1^3 * 0.9^0 = 0.001
0 0 1 1 0.1^2 * 0.9^1 = 0.009
0 1 0 1 0.1^2 * 0.9^1 = 0.009
0 1 1 2 0.1^1 * 0.9^2 = 0.081
1 0 0 1 0.1^2 * 0.9^1 = 0.009
1 0 1 2 0.1^1 * 0.9^2 = 0.081
1 1 0 2 0.1^1 * 0.9^2 = 0.081
1 1 1 3 0.1^0 * 0.9^3 = 0.729
, поэтому вероятность увидеть его 2 или 3 раза равна .081 * 3 + .729 = .972