Анализ кода на эффективность?

какие инструменты вы используете для определения эффективности кода? Используете ли вы домашние приложения, которые запускают статистически значимое количество тестов, или какой-то коммерческий продукт? Используете ли вы собственные знания для тестирования определенных областей кода или какой-то инструмент, который анализирует код на наличие слабых мест?

9 ответов


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


INSERTED: давайте посмотрим на "статистическую значимость".

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

каким-то образом программа случайно останавливается в определенный момент времени, и ее состояние исследуется. Остановится ли он в этом 90% времени, которое будет сохранено, если инструкция может быть "обнулена"? Конечно - с 90% вероятностью, и инструкция будет точно указано на стеке, ожидая завершения своей "работы".

на самом деле, если вы остановите его случайно 20 раз, эта инструкция будет в стеке в среднем 18 раз, со стандартным отклонением +/- 1,3 раза.

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

предположим, что процент небольшой, например 10% или 5%. тот же принцип применяется.

на самом деле, независимо от того, как немногие образцы взяты, любая инструкция, которая находится на >1 образце, статистически значима и является "горячей точкой", "узким местом" или как вы хотите это назвать. Если бы вы могли удалить его, назвать его меньше или как-то уменьшить его, это будет сохранить значительное время. (Некоторые вы не можете, как "call _main", но другие вы можете. Тебе просто нужно найти их.)

конечно мой код никогда не был бы таким глупым, не так ли? Ну а потом доказать.

хорошо, теперь вернемся к истории . . .

оригинальный ответ: я слышал о профилировщиках, когда-то, и я думал, что они должны быть довольно аккуратными, но у меня не было доступа к ним/ИТ. Я работал над встроенным процессором (чипом intel 8086), который, казалось, ужасно долго рисовал некоторые числа с плавающей запятой на экране дисплея. Аппаратные ребята предложили предоставить из своих чипов таймера, чтобы я мог видеть, как дела шли долго. Однако в один из выходных я запустил его с эмулятором Intel "Blue Box" в цепи и запустил его. Пока он был медленным, я задавался вопросом: "Что, черт возьми, он делает?". Поэтому я просто остановил его, чтобы узнать. Компьютер находился в библиотеке с плавающей запятой (не было чипа FP). Это не было сюрпризом, так как он рисовал числа с плавающей запятой, но я хотел знать больше. Поэтому я (с трудом) прочитал шестнадцатеричную память, чтобы следовать стеку вызовов. Знаешь что? Это было в процессе принятия число, которое нужно нарисовать, деление его на 10, преобразование в целое, преобразование обратно в float, вычитание и так далее, просто, чтобы получить следующую цифру рисовать. Излишне говорить, что были лучшие способы сделать это, что приводит к ускорению примерно в 10 раз. это было найдено с один (1) образец!

в другой раз, на чипе 68K, была некоторая медлительность. Опять же, профилировщик был недоступен, но отладчик "adb" был, поэтому, пока он был медленным, я остановил его несколько раз. Компьютер был в математической библиотеке, на самом деле в 32-разрядной процедуре умножения целых чисел. Глядя вверх по стеку, я нашел этот код:

struct {...} a[...];

int i;
for (i = 0; i < ...; ++i){ ... a[i] ... }

там нет вызова, чтобы умножить там - что происходит? Оказывается, для a[i] компилятор должен умножить i по размеру элемента массива. С i 32 бита (в этом компиляторе) он генерирует вызов 32-разрядной процедуры умножения и точек стека, которые вызывают инструкцию. От объявление i as short, петля утроилась в скорости!

какой смысл? Если вы берете образцы в случайные моменты времени, когда программа работает медленно, ПК скажет вам, что он делает, но стек вызовов скажет вам почему, и привести вас прямо к проблеме. Теперь, если проблема действительно серьезная, необходимо взять несколько образцов. Любое заявление, которое появляется на > 1 образце, является тем, которое вы можете подозревать. Обратите внимание, он указывает заявления, - инструкции даже не большие куски кода как функции. эта техника может быть "быстрым и грязным", но это очень эффективно.

добавлено: если вы делаете это повторно, то вы можете разрешить проблему после проблемы в таком же программном обеспечении. Например, если вы получаете ускорение в 3 раза, небольшие проблемы с производительностью, которые могут быть ничтожны перед потребляют в 3 раза больше оставшегося времени. Что делает их гораздо легче попасть с образцами. Вы можете добавьте временный внешний цикл, чтобы он работал достаточно долго для выборки. Таким образом, я видел сложные факторы ускорения более чем в 40 раз!--59-->.


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

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

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


честно говоря, я использую NUnit. Если у меня есть код, который занимает слишком много времени или не масштабируется, я пишу тест, имитирующий ту часть приложения, которая работает плохо. Затем я смотрю на создание замен strenth в коде, чтобы уменьшить время выполнения и проверить, что я ничего не сломал.

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


Я использую Valgrind и его инструмент Callgrind. Это отличный инструмент. Valgrind в основном виртуальная машина:

Valgrind по сути является виртуальным машина, использующая just-in-time (JIT) методы компиляции, включая динамическая перекомпиляция. Ничего от оригинальная программа не запускается непосредственно на хост-процессоре. Вместо этого Valgrind сначала переводит программа во временную, более простую форму называется промежуточное представление (IR), который является процессор-нейтральный, ССА-форм. После преобразования, инструмент (см. ниже) можно сделать бесплатно каким бы трансформациям она хотела бы на ИК, прежде чем Valgrind переводит ИК назад в машинный код и позволяет главный процессор запускает его. Даже если он может использовать динамический перевод (что is, хост и целевые процессоры для разных архитектур), он нет. Valgrind перекомпилирует двоичный код код для запуска на хосте и цели (или смоделированные) процессоры одного и того же архитектура.

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

другим инструментом, построенным на Valgrind, является массив. Я использую его для профилирования использования памяти кучи. Он отлично работает, он дает вам снимки использования памяти -- подробная информация, что содержит какой процент памяти, и кто положил его там.

еще один инструмент Valgrind -- DRD (и Helgrind). Я использую их для отслеживания мертвых блокировок и гонок данных в моем коде, а также злоупотребления API потоков.


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

в Linux я использую отчет, который поставляется с некоторыми полезными инструментами для профилирования кода. Что касается домашней страницы Valgrind:

Он работает на следующих платформах: X86/Linux, AMD64/Linux, PPC32/Linux, PPC64/Linux.

.. и это бесплатно (как в бесплатном пиве) и открыто источник.

хотя я не использовал их так много, на другой платформе вы можете использовать Очистить/Количественно (продукты IBM). Это коммерческие инструменты. Как сообщал Уилл, они поставляются в пакете PurifyPlus, и Quantify поможет вам в профилировании вашего приложения.

Это все, что я использовал... :-)


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

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


Я слышал хорошее слово о Yourkit для профилирования Java. Для веб-сайтов, я пробовал JMeter который имеет основную функциональность для простого параметризованного профилирования.


для .NET я бы рекомендовал вопросом, что происходит.