Анализ кода для эффективности?
Какие инструменты вы используете для определения эффективности кода? Используете ли вы домашние приложения, которые проводят статистически значимое количество тестов или какой-либо коммерческий продукт? Используете ли вы свои собственные знания для проверки определенных областей вашего кода или какого-либо инструмента, который анализирует ваш код для слабых мест?
Ответы
Ответ 1
Это называется profiling. Существует множество готовых инструментов, которые помогут вам определить, где узкие места в ваших приложениях, для всех видов разных языков. Например, набор инструментов TPTP для Java может показать вам, где узкие места производительности ограничены уровнем отдельных методов, если вы хотите, чтобы он, Конечно, иногда вам действительно нужно несколько раз прочитать системный таймер, чтобы получить общее представление о разделе кода.
Ответ 2
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
как short
, цикл утроился со скоростью!
Какой смысл? Если вы производите выборки в случайные моменты, пока программа медленная, ПК скажет вам, что она делает, но стек вызовов скажет вам, почему, и приведет вас к проблеме. Теперь, если проблема не очень плохая, вам может потребоваться несколько образцов. Любое утверждение, отображаемое в примере > 1, - это тот, с которым вы можете быть подозрительным. Обратите внимание, он точно определяет инструкции, инструкции, а не большие куски кода, подобные функциям. Этот метод может быть "быстрым и грязным", но он очень эффективен.
ДОБАВЛЕН: Если вы делаете это повторно, вы можете решить проблему после проблемы в одном и том же программном обеспечении. Например, если вы получаете ускорение в 3 раза, небольшие проблемы с производительностью, которые могут быть незначительными, до сих пор потребляют в 3 раза больше оставшегося времени. Это делает их намного легче ударить с образцами. Возможно, вам придется добавить временный внешний цикл, чтобы он работал достаточно долго, чтобы выполнить выборку. Таким образом, я видел составные коэффициенты ускорения более 40 раз.
Ответ 3
Профилисты очень полезны для просмотра кода, который вы тратите больше всего времени. Есть много инструментов для профилирования, обычно они специфичны для среды разработки платформы/разработки, в которой вы находитесь.
В небольших случаях я использовал простые таймеры в коде (системное время в конце действия - системное время в начале действия).
Одно важное правило: никогда не предполагайте, что оптимизация производительности, которую вы только что положили, будет работать быстрее. Всегда проверяйте!
Ответ 4
Я использую инструменты для этой работы. В противном случае мне было очень трудно сделать это своими руками... (ну это мое мнение, я никогда не пробовал на самом деле)
В Linux я использую Valgrind, который поставляется с некоторыми полезными инструментами для профилирования вашего кода. Что касается домашней страницы Valgrind:
Он работает на следующих платформах: X86/Linux, AMD64/Linux, PPC32/Linux, PPC64/Linux.
.. и он бесплатный (как в свободном пиве) и с открытым исходным кодом.
Пока я их не использовал, на другой платформе вы можете использовать Purify/Quantify (продукты IBM). Это коммерческие инструменты. Как сообщают об этом, они поставляются в пакете PurifyPlus, а Quantify поможет вам профилировать ваше приложение.
Что я использовал...: -)
Ответ 5
Честно говоря, я использую NUnit. Если у меня есть код, который слишком длинный или не кажется масштабированным, я пишу тест, имитирующий часть приложения, которое работает плохо. Затем я смотрю на то, чтобы сделать замену strth в коде, чтобы сократить время выполнения и убедиться, что я ничего не сломал.
Если это еще не дает вам то, что вам нужно, вам нужно найти и применить профайлер, но у вас есть хотя бы тестовый пример, на котором вы можете опробовать свои предположения без необходимости открывать/загружать приложение, отслеживать вызовы к элементам приложения, которые arent являются следствием этой задачи.
Ответ 6
Я использую Valgrind и его инструмент Callgrind. Это отличный инструмент. Valgrind - это в основном виртуальная машина:
Valgrind по сути является виртуальным машина, использующая точно в срок (JIT) методы компиляции, в том числе динамическая перекомпиляция. Ничего от исходная программа когда-либо запускается непосредственно на главном процессоре. Вместо этого Valgrind сначала переводит программа во временную, более простую форму промежуточное представление (IR), который является нейтральным от процессора, Форма на основе SSA. После преобразования, инструмент (см. ниже) можно свободно делать какие бы преобразования он ни хотел на IR, прежде чем Valgrind переводит IR обратно в машинный код и позволяет хост-процессор запускает его. Хотя он может использовать динамический перевод (что является, хост и целевые процессоры из разных архитектур), это не делает. Valgrind перекомпилирует двоичный файл код для запуска на хосте и цели (или симулированные) процессоры того же архитектура.
Callgrind - это профайлер, основанный на этом. Главное преимущество заключается в том, что вам не нужно запускать приложение в течение нескольких часов, чтобы получить надежный результат. Достаточно нескольких секунд, потому что Callgrind является не-зондирующим профилировщиком,
Еще один инструмент, основанный на Вальгринде, - это массив. Я использую его для использования памяти памяти кучи. Он отлично работает, он дает вам снимки использования памяти - подробная информация WHAT содержит WHAT процент памяти, и ВОЗ разместила его там.
Еще один инструмент Valgrind - DRD (и Helgrind). Я использую их для отслеживания мертвых блокировок и расчётов данных в моем коде, а также для злоупотребления API потока.
Ответ 7
Вопрос неоднозначен. Эффективен с точки зрения времени выполнения или памяти?
Контекст, в котором выполняется конкретный фрагмент кода, архитектура приложения и данные, которые могут быть выбраны на него, также являются факторами.
Кстати, кто-то упомянул "Очистить"; есть также его сестра productify.
Ответ 8
Я слышал хорошее слово о Yourkit для профилирования Java. Для веб-сайтов я пробовал JMeter, который имеет базовые функции для простого параметризованного профилирования.
Ответ 9
Для .NET я бы рекомендовал NDepend.