Функциональное профилирование проблем - Visual Studio 2010 Ultimate - PullRequest
8 голосов
/ 03 апреля 2011

Я пытаюсь профилировать свое приложение, чтобы отслеживать эффекты функции, как до, так и после рефакторинга.Я выполнил анализ своего приложения и, просмотрев сводку, заметил, что в списке Hot Path не упоминается ни одна из используемых мной функций, он упоминает только функции вплоть до Application.Run ()

Я довольно новичок в профилировании и хотел бы узнать, как я могу получить больше информации о Горячем пути, как показано в документации MSDN ;

MSDNПример:

MSDN Example

Мои результаты:

Hot Path Summary

Я заметил вОкно вывода. Есть много сообщений, касающихся сбоя при загрузке символов, некоторые из них приведены ниже:

Failed to load symbols for C:\Windows\system32\USP10.dll.  
Failed to load symbols for C:\Windows\system32\CRYPTSP.dll.
Failed to load symbols for (Omitted)\WindowsFormsApplication1\bin\Debug\System.Data.SQLite.dll.
Failed to load symbols for C:\Windows\system32\GDI32.dll.  
Failed to load symbols for C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2\comctl32.dll.
Failed to load symbols for C:\Windows\system32\msvcrt.dll. 
Failed to load symbols for C:\Windows\Microsoft.NET\Framework\v4.0.30319\nlssorting.dll.
Failed to load symbols for C:\Windows\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll.  Failed to load symbols for
C:\Windows\Microsoft.Net\assembly\GAC_32\System.Transactions\v4.0_4.0.0.0__b77a5c561934e089\System.Transactions.dll.
Unable to open file to serialize symbols: Error VSP1737: File could not be opened due to sharing violation: - D:\(Omitted)\WindowsFormsApplication1110402.vsp

(отформатирован с использованием инструмента кода, чтобы его можно было прочитать)

Спасибо за любые указатели.

Ответы [ 2 ]

13 голосов
/ 03 апреля 2011

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

По умолчанию для анализа выборок включена функция " Just My Code ", которая скрывает функции, поступающие в стекиз непользовательских модулей (он будет отображать глубину 1 непользовательских функций, если вызывается пользовательской функцией; в вашем случае Application.Run).Функции, исходящие от модулей без загруженных символов или от модулей, о которых известно, что они принадлежат Microsoft, будут исключены.«Горячий путь» в сводном представлении указывает на то, что в самом дорогом стеке не было ничего из того, что профилировщик считает вашим кодом (кроме Main).Пример из MSDN показывает больше функций, потому что функции PeopleTrax.* и PeopleNS.* происходят из «кода пользователя».«Просто мой код» можно отключить, нажав ссылку «Показать весь код» в сводном представлении, но я бы не рекомендовал делать это здесь.

Посмотрите на « Функции, выполняющиеБольшая индивидуальная работа"в сводном представлении.При этом отображаются функции, которые имеют наибольшее число исключительных выборок и, следовательно, в зависимости от сценария профилирования являются наиболее дорогими функциями для вызова.Вы должны увидеть больше ваших функций (или функций, вызываемых вашими функциями) здесь.Кроме того, в представлении « Функции » и « Дерево вызовов » может отображаться более подробная информация (в верхней части отчета есть раскрывающийся список для выбора текущего представления).

Что касается ваших символьных предупреждений, большинство из них ожидаются, потому что они являются модулями Microsoft (не включая System.Data.SQLite.dll).Хотя вам не нужны символы для этих модулей для правильного анализа отчета, если вы выбрали «Серверы символов Microsoft» в «Сервис -> Параметры -> Отладка -> Символы» и снова открыли отчет, символы для этих модулей должны загрузить,Обратите внимание, что открытие отчета в первый раз займет гораздо больше времени, поскольку символы необходимо загружать и кэшировать.

Другое предупреждение о невозможности сериализации символов в файле отчета - результат файла.не может быть записано, потому что оно открыто чем-то другим, что мешает записи.Сериализация символов - это оптимизация, которая позволяет профилировщику загружать информацию символов непосредственно из файла отчета при следующем анализе.Без сериализации символов анализ просто должен выполнить тот же объем работы, что и при первом открытии отчета.

И, наконец, вы также можете попробовать инструментарий вместо выборкив настройках сеанса профилирования.Инструментарий изменяет модули, которые вы указываете для сбора данных при каждом вызове функции (имейте в виду, что это может привести к гораздо большему размеру файла .vsp).Инструментарий идеально подходит для фокусирования на времени определенных фрагментов кода, тогда как выборка идеально подходит для общего сбора данных профилирования с низкими издержками.

6 голосов
/ 06 апреля 2011

Вы слишком возражаете, если я немного расскажу о профилировании, что работает, а что нет?

Давайте составим искусственную программу, некоторые из утверждений которой выполняют работу, которую можно оптимизировать -т.е. они на самом деле не нужны.Это «узкие места».

Подпрограмма 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

...