Какие ресурсы я могу использовать для изучения профилирования / оптимизации? - PullRequest
7 голосов
/ 15 февраля 2009

Я только что унаследовал проект C #, который работает медленно и должен будет начать его оптимизировать. Сначала я хотел узнать немного больше о профилировании / оптимизации, так как раньше мне не приходилось это делать. Итак, вопрос в том, с чего мне начать, какие книги / блоги / статьи можно читать?

Я знаю о профилировщиках .net, таких как профилировщик ANTS и т. Д., Но я не знаю, как их эффективно использовать. Я на самом деле не использовал его, просто позвольте ему запускаться на нескольких примерах приложений, чтобы поиграть с выводом.

Ответы [ 11 ]

14 голосов
/ 22 февраля 2009

Есть два шага для оптимизации кода.

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

Другими словами, вы получаете большое дерево вызовов, и вам просто нужно выследить большие номера. Обычно у вас очень мало функций, занимающих более 10% времени выполнения. Так что найдите их, и вы знаете, что для оптимизации.

Обратите внимание, что профилировщик не является ни обязательным, ни обязательно подходом best . Удивительно простой, но эффективный подход заключается в том, чтобы просто запустить программу в отладчике и в несколько квази-случайных моментов приостановить выполнение и посмотреть на стек вызовов. Сделайте это всего пару раз, и у вас будет отличное представление о том, на что тратится ваше время выполнения. @ Майк Данлавей, который прокомментировал этот ответ, подробно описал этот подход в другом месте.

Но теперь, когда вы знаете, на что тратится время выполнения, наступает сложная часть, как оптимизировать код.

Конечно, наиболее эффективным подходом часто является высокоуровневый. Должна ли проблема быть решена таким образом? Это должно быть решено вообще? Может ли он быть решен заранее, а результат кэширован, чтобы он мог быть доставлен мгновенно, когда остальная часть приложения нуждалась в этом? Существуют ли более эффективные алгоритмы решения проблемы?

Если вы можете применить такие высокоуровневые оптимизации, сделайте это, посмотрите, достаточно ли улучшилось это быстродействие, а если нет, снова профилируйте.

Рано или поздно вам, возможно, придется погрузиться в более низкоуровневые оптимизации. Это сложная территория, хотя. Современные компьютеры довольно сложны, и производительность, которую вы получаете от них, непроста. Стоимость ветки или вызова функции может широко варьироваться в зависимости от контекста. Добавление двух чисел может занять от 0 до 100 тактов в зависимости от того, были ли оба значения уже в регистрах ЦП, что выполняется в данный момент else и ряда других факторов. Таким образом, оптимизация на этом уровне требует (1) хорошего понимания того, как работает процессор, и (2) большого количества экспериментов и измерений. Вы можете легко внести изменение, которое, по вашему мнению, будет быстрее , но вы должны быть уверены в этом, поэтому измеряйте производительность до и после изменения.

Существует несколько общих практических правил, которые часто могут помочь при оптимизации:

I / O стоит дорого. Инструкции ЦП измеряются в долях наносекунды. Доступ к ОЗУ составляет от десятков до сотен наносекунд. Доступ с жесткого диска может занять десятки милли секунд. Так часто ввод / вывод замедляет работу вашего приложения. Выполняет ли ваше приложение несколько больших операций ввода-вывода (чтение файла размером 20 МБ в одном большом фрагменте) или бесчисленное количество небольших операций (чтение байтов с 2052 по 2073 из одного файла, а затем считывание нескольких байтов из другого файла)? Меньшее количество операций чтения может ускорить ваш ввод-вывод в несколько тысяч раз.

Pagefaults также включает доступ с жесткого диска. Страницы в памяти должны быть помещены в файл подкачки, а выгруженные страницы должны быть считаны обратно в память. Если это часто случается, это будет медленно. Вы можете улучшить месторасположение своих данных, чтобы одновременно понадобилось меньше страниц? Вы можете просто купить больше оперативной памяти для хост-компьютера, чтобы избежать необходимости выкладывать данные? (Как правило, аппаратные средства дешевы. Обновление компьютера - это совершенно приемлемая оптимизация, но убедитесь, что обновление будет иметь значение. Считывание с диска не будет намного быстрее, если купить более быстрый компьютер. И если все уместится в ОЗУ на вашей старой системе нет смысла покупать ее с 8-кратным объемом ОЗУ)

Ваша база данных также использует доступ с жесткого диска. Так что вы можете избежать кэширования большего количества данных в оперативной памяти и только изредка записывать их в базу данных? (Конечно, есть риск. Что произойдет, если приложение выйдет из строя?

А потом есть все любимые, нити. Современный процессор имеет от 2 до 16 доступных процессорных ядер. Вы используете их все? Вы выиграли бы от их использования? Существуют ли длительные операции, которые могут выполняться асинхронно? Приложение запускает операцию в отдельном потоке, а затем может немедленно возобновить нормальную работу, а не блокировать ее до завершения операции.

Так что, в основном, используйте профилировщик, чтобы понять ваше приложение. Как он тратит время выполнения, где он тратится? Является ли потребление памяти проблемой? Каковы шаблоны ввода / вывода (как для жесткого диска, так и для доступа к сети, а также для любого другого типа ввода / вывода)? ЦП просто постоянно работает или простоит в ожидании каких-то внешних событий, таких как ввод-вывод или таймеры?

А затем поймите как можно больше о компьютере, на котором он работает. Понять, какие ресурсы он имеет в наличии (кэш-память процессора, несколько ядер) и что каждый из них означает для производительности.

Это все довольно расплывчато, потому что уловки по оптимизации большого сервера баз данных будут очень отличаться от того, что вы бы сделали, чтобы оптимизировать какой-то алгоритм обработки больших чисел.

4 голосов
/ 15 февраля 2009

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

3 голосов
/ 15 февраля 2009

Если вы знакомы с ANTS (очень хорошим профилировщиком) и уже приобрели его, перейдите по ссылке сюда , чтобы получить краткое руководство по началу работы.

2 голосов
/ 22 февраля 2009

Если у вас есть Visual Studio Team System, я предлагаю использовать Профилировщик, который она содержит.
Находится в разделе «Анализ-> Профилировщик»
Использовать этот профилировщик очень просто. Вы можете просто погрузиться и посмотреть, что вы с этим делаете. Практика лучше, чем любая статья или книга, о которой вы прочтете.

Найти ваши первые пару узких мест просто, всего за несколько кликов. Их решение может быть немного сложнее, но опять же, оптимизация кода - это просто вопрос или практика и опыт.

1 голос
/ 26 февраля 2009

Я бы скачал несколько доступных инструментов профилирования (бесплатные пробные версии) и начал бы их использовать.

Я использовал реактивный мозг , и есть другие. ( муравьи, например , devpartner и MS)? , atomatedqa и т. Д.) У вас не должно быть особых проблем при их запуске. У них есть отчеты, которые дают вам много информации, и вы можете учиться довольно быстро, просто используя приложения.

Любой из них, вероятно, поможет вам, и приятно использовать испытания. Затем вы можете либо просто отложить решение о покупке инструмента, либо купить тот, который был наиболее полезным / простым в использовании. В целом, они экономят время и стоят денег, хотя некоторые могут быть дорогими. (Мне трудно работать с верхним, когда есть очень хорошие инструменты за гораздо меньшие деньги)

В первый день установки и запуска вы можете столкнуться с серьезными / серьезными проблемами с производительностью. Я знаю, что сделал.

удачи.

Просто скачайте несколько инструментов и запустите ваше приложение.

EDIT:

Что касается книг и обучения - в основном, лучший способ узнать о проблемах с кодом - это найти плохой код. Много раз полезно проводить проверки с опытными разработчиками.

как пример: я думаю, что Джоэл написал статью о том, что он сделал что-то вроде

для (int i = 0; i

довольно очевидно, что вы будете вызывать strlen (дорого) на каждой итерации цикла.

Вам нужно будет взглянуть на некоторый код после того, как профилировщик скажет вам, на что тратится время, и посмотреть, можно ли легко исправить код с помощью простых вещей, подобных этому, или необходимо внести изменения в дизайн алгоритмы.

1 голос
/ 24 февраля 2009

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

Если скорость является проблемой во всем приложении, вы, вероятно, не сможете сделать с ней слишком много, но, возможно, сможете внести несколько изменений ...

Ищите внутренние петли. Это спектакль смерти. Внутренний цикл может быть вызван чем-то таким простым, как индексация в связанном списке или выполнение вставки в список на основе массива. (После того, как у меня появилось окно со списком, которое заняло 10-20 минут, чтобы заполнить десятки тысяч записей, хотя это слишком много записей, хуже всего было то, что он сортировал их, вставляя каждую запись в список массивов).

Ищите случаи, когда вы выполняете длинные операции на основе нажатий клавиш. Это почти всегда следует делать вне основного потока.

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

1 голос
/ 22 февраля 2009

Существуют профилировщики и инструменты анализа производительности, но пока вы пытаетесь найти / купить / установить / изучить один, просто попробуйте хитрость старого времени ...

Запустите приложение в среде IDE, и пока оно медленное, нажмите кнопку «Пауза» и спросите его, что оно делает, и почему . Лучший способ ответить на этот вопрос - прочитать стек вызовов.

Если это в несколько раз медленнее, чем должно быть, например, в 10 раз, это означает, что 90% своего времени он тратит на что-то ненужное, и это вероятность, что вы поймаете его, делая это . Если вы повторите это несколько раз, вы можете подтвердить свои подозрения с любой точностью.

Так что вам не нужно дорогое / популярное, но нечеткое увеличительное стекло.

Так что найти причину медлительности не самая сложная часть, и обычно их несколько.

Сложность в том, что после того, как вы исправили несколько «низко висящих фруктов», вам, вероятно, придется столкнуться с тем фактом, что главной причиной медлительности является чрезмерный дизайн.

Удачи.

1 голос
/ 22 февраля 2009

Читать Блог Рико Мариани . До того, как его повысили в должности, он был главным специалистом по настройке производительности для .Net. Старые записи в его блоге содержат массу полезных советов. Я бы начал с самого начала и продолжил ваш путь вперед.

Это, плюс статьи, которые вы уже нашли (особенно первая ), должны помочь вам начать.

1 голос
/ 15 февраля 2009
0 голосов
/ 26 февраля 2009

Вы уже ударили ноготь по голове Профилировщиком. Все они, по крайней мере все, что я использовал, следуют одной и той же базовой методологии. Вы выбираете исполняемый файл и затем запускаете приложение.

Что вы делаете с выводом, так это находите методы, которые занимают больше всего времени. Это еще не все, но вы попросили хороший способ узнать, как оптимизировать код, поэтому долгосрочное выполнение подпрограмм - хорошее место для начала , ANTS, который вы упомянули, по умолчанию будет показывать долго выполняющиеся подпрограммы, как и большинство, если не все, другие.

Вы можете исключить методы контейнера, такие как Main (), если у вас нет большого количества кода (маловероятно).

В целом, я нахожу большинство отходов в трех областях:

  1. Loops
  2. Рекурсия
  3. Сетевая задержка

Область № 3 для базы данных, как правило, легко определить, если вы также профилируете свою базу данных, так как увидите количество попаданий. Лучший способ уменьшить задержку в сети, будь то база данных или нет (например, вызовы службы), - это общение в сообщениях, а не CRUD. Не запрашивайте каждую таблицу по одному. К сожалению, для решения часто требуются отдельные части многих общих слоев данных.

Рекурсия и циклы - очень похожие проблемы. Если вы хотите ударить по доллару, сначала нажмите на внутреннюю петлю.

В .NET вы также можете многое узнать об оптимизации, изучая базовый IL и исследуя IL ваших приложений с помощью таких инструментов, как Reflector. Это пустая трата времени, если это не основная часть описания вашей работы или что вы, вероятно, захотите посвятить будущей карьере. Быть пожарным - это хорошо, но быть программистом только для техобслуживания может быть очень скучно.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...