Как я могу профилировать код C ++, работающий в Linux?

1433

У меня есть приложение на С++, работающее на Linux, которое я в процессе оптимизации. Как я могу определить, какие области моего кода работают медленно?

  • 25
    Если вы предоставите больше данных о вашем стеке разработки, вы можете получить лучшие ответы. Есть профилировщики от Intel и Sun, но вы должны использовать их компиляторы. Это вариант?
  • 2
    На него уже дан ответ по следующей ссылке: stackoverflow.com/questions/2497211/…
Показать ещё 4 комментария
Теги:
profiling

25 ответов

1142
Лучший ответ

Если ваша цель - использовать профилировщик, используйте один из предложенных.

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

Просто остановите его несколько раз и каждый раз смотрите на стек вызовов. Если есть какой-то код, который тратит часть процента времени, 20% или 50% или что-то еще, это вероятность того, что вы поймаете его в действии по каждому образцу. Так что это примерно процент образцов, на которых вы его увидите. Не требуется никаких просвещенных догадок. Если у вас есть догадка о том, в чем проблема, это докажет или опровергнет ее.

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

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

  • они не суммируются на уровне инструкций и
  • они дают путаные резюме при наличии рекурсии.

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

P.S. Это также можно сделать в многопоточных программах, если есть способ собрать образцы стека вызовов пула потоков в определенный момент времени, как есть в Java.

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

Добавлено: Это может быть не очевидно, но метод выборки стека работает одинаково хорошо в присутствии рекурсии. Причина в том, что время, которое было бы сохранено удалением команды, аппроксимируется фракцией содержащихся в ней выборок, независимо от количества раз, которое может произойти в пределах образца.

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

ДОБАВЛЕН: Позвольте мне объяснить байесовское объяснение того, как это работает. Предположим, что есть некоторая инструкция I (вызов или иначе), которая находится в стеке вызовов некоторая дробь f времени (и, следовательно, так дорого). Для простоты предположим, что мы не знаем, что такое f, но предположим, что это либо 0,1, 0,2, 0,3,... 0,9, 1,0, а предыдущая вероятность каждой из этих возможностей равна 0,1, поэтому все эти затраты одинаково вероятны априорно.

Тогда предположим, что мы берем только 2 образца стека, и мы видим инструкцию I для обоих образцов, обозначенных наблюдения o=2/2. Это дает нам новые оценки частоты f of I, в соответствии с этим:

Prior                                    
P(f=x) x  P(o=2/2|f=x) P(o=2/2&&f=x)  P(o=2/2&&f >= x)  P(f >= x)

0.1    1     1             0.1          0.1            0.25974026
0.1    0.9   0.81          0.081        0.181          0.47012987
0.1    0.8   0.64          0.064        0.245          0.636363636
0.1    0.7   0.49          0.049        0.294          0.763636364
0.1    0.6   0.36          0.036        0.33           0.857142857
0.1    0.5   0.25          0.025        0.355          0.922077922
0.1    0.4   0.16          0.016        0.371          0.963636364
0.1    0.3   0.09          0.009        0.38           0.987012987
0.1    0.2   0.04          0.004        0.384          0.997402597
0.1    0.1   0.01          0.001        0.385          1

                  P(o=2/2) 0.385                

В последнем столбце говорится, что, например, вероятность того, что f >= 0,5 составляет 92%, по сравнению с предшествующим допущением 60%.

Предположим, что предыдущие предположения различны. Предположим, что P (f = 0,1) составляет 0,991 (почти наверняка), а все остальные возможности практически невозможны (0,001). Другими словами, наша предварительная уверенность в том, что I дешево. Тогда получим:

Prior                                    
P(f=x) x  P(o=2/2|f=x) P(o=2/2&& f=x)  P(o=2/2&&f >= x)  P(f >= x)

0.001  1    1              0.001        0.001          0.072727273
0.001  0.9  0.81           0.00081      0.00181        0.131636364
0.001  0.8  0.64           0.00064      0.00245        0.178181818
0.001  0.7  0.49           0.00049      0.00294        0.213818182
0.001  0.6  0.36           0.00036      0.0033         0.24
0.001  0.5  0.25           0.00025      0.00355        0.258181818
0.001  0.4  0.16           0.00016      0.00371        0.269818182
0.001  0.3  0.09           0.00009      0.0038         0.276363636
0.001  0.2  0.04           0.00004      0.00384        0.279272727
0.991  0.1  0.01           0.00991      0.01375        1

                  P(o=2/2) 0.01375                

Теперь он говорит, что P (f >= 0,5) составляет 26%, по сравнению с предыдущим допущением 0,6%. Таким образом, Байес позволяет нам обновить нашу оценку вероятной стоимости I. Если объем данных невелик, он не говорит нам точно, какова стоимость, только то, что она достаточно велика, чтобы стоить исправления.

Еще один способ взглянуть на это называется Правило преемственности, Если вы переворачиваете монету 2 раза, и она поднимается вверх, оба раза, что это говорит о вероятном взвешивании монеты? Уважаемый способ ответить - сказать, что это бета-распределение со средним значением (количество ударов + 1)/(количество попыток + 2) = (2 + 1)/(2 + 2) = 75%.

(Ключ состоит в том, что мы видим I более одного раза. Если мы его видим только один раз, это не говорит нам о многом, кроме f > 0.)

Таким образом, даже очень небольшое количество образцов может рассказать нам многое о стоимости инструкций, которые он видит. (И они будут видеть их с частотой, в среднем, пропорционально их стоимости. Если взять n выборки, а f - стоимость, то I появится на образцах nf+/-sqrt(nf(1-f)). Пример, n=10, f=0.3, то есть 3+/-1.4 samples.)


ADDED, чтобы дать интуитивное ощущение разницы между выборкой и выборочной выборкой стека:
Теперь есть профайлеры, которые пробуют стек, даже на настенные часы, но то, что выходит, - это измерения (или горячая дорожка, или горячая точка, из которой можно легко скрыть "узкое место" ). То, что они не показывают вам (и они легко могли), это сами образцы. И если ваша цель - найти узкое место, то число их, которое вам нужно увидеть, в среднем составляет 2, разделенное на долю времени, которое требуется. Так что, если это займет 30% времени, в среднем отобразится 2/.3 = 6.7 образцов, и вероятность того, что 20 образцов покажет, равна 99,2%.

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

Изображение 1174

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

  • 0
    Я программист и работаю в среде, где важна производительность. Я должен сказать, что эта техника - очень хорошая техника (вот почему я собираюсь поддержать вас :). Но что вы можете сделать для рекурсивного программирования? Не много. Вот почему я придерживаюсь мнения, что рациональная количественная оценка - это хороший инструмент
  • 4
    Благодарю. На самом деле у него нет проблем с рекурсией. Если инструкция вызова появляется> 1 раз на выборке, это все еще только 1 выборка. Время, за которое инструкция стоит ~ = количество сэмплов.
Показать ещё 93 комментария
500

Вы можете использовать Valgrind со следующими параметрами

valgrind --tool=callgrind ./(Your binary)

Он будет генерировать файл с именем callgrind.out.x. Затем вы можете использовать инструмент kcachegrind для чтения этого файла. Это даст вам графический анализ вещей с результатами, например, какие из них стоят.

  • 37
    valgrind великолепен, но имейте в виду, что он замедлит вашу программу
  • 24
    Проверьте также Gprof2Dot для удивительного альтернативного способа визуализации вывода. ./gprof2dot.py -f callgrind callgrind.out.x | dot -Tsvg -o output.svg
Показать ещё 3 комментария
300

Я предполагаю, что вы используете GCC. Стандартным решением будет профиль с gprof.

Обязательно добавьте -pg в компиляцию перед профилированием:

cc -o myprog myprog.c utils.c -g -pg

Я еще не пробовал, но я хорошо слышал о google-perftools. Это определенно стоит попробовать.

Связанный с этим вопрос здесь.

Несколько других слов, если gprof не выполняет эту работу для вас: Valgrind, Intel VTune, Sun DTrace.

  • 3
    Я согласен, что gprof является текущим стандартом. Просто отметим, что Valgrind используется для профилирования утечек памяти и других связанных с памятью аспектов ваших программ, а не для оптимизации скорости.
  • 65
    Билл, в vaglrind suite вы можете найти callgrind и массив. Оба очень полезны для профилирования приложений
Показать ещё 3 комментария
208

Новые ядра (например, последние ядра Ubuntu) поставляются с новыми инструментами "perf" (apt-get install linux-tools) AKA perf_events.

Они поставляются с классическими пробоотборниками пробоотбора (man-страница), а также удивительным timechart!

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

Изображение 1175

  • 11
    Отличный инструмент! Можно ли как-нибудь получить типичный вид "бабочки", который начинается со стиля "main-> func1-> fun2"? Я не могу понять это ... perf report кажется, дает мне имена функций с родителями вызова ... (так что это своего рода перевернутая бабочка)
  • 0
    Уилл, может показывать график активности потока; с добавленной информацией о количестве процессоров? Я хочу видеть, когда и какой поток работал на каждом процессоре.
Показать ещё 4 комментария
108

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

Если вы не заботитесь о массивном ударе производительности (50x), Valgrind (Cachegrind) хорошо.

95

Вы можете использовать callgrind. Вместе с KCacheGrind он дает довольно хороший профилировщик. Кроме того, Intel VTune является бесплатным для образовательного использования в Linux. Вероятно, это лучший профайлер. Если у вас есть процессор AMD, используйте AMD Codeanalyst (сменил AMDs CodeXL), который также доступен для Linux; этот только приличный, но свободный.

63

Я бы использовал Valgrind и Callgrind в качестве базы для моего набора инструментов для профилирования. Важно знать, что Valgrind - это в основном виртуальная машина:

(wikipedia) Valgrind по сути является виртуальным машина, использующая точно в срок (JIT) методы компиляции, в том числе динамическая перекомпиляция. Ничего от исходная программа когда-либо запускается непосредственно на главном процессоре. Вместо этого Valgrind сначала переводит программа во временную, более простую форму промежуточное представление (IR), который является нейтральным от процессора, Форма на основе SSA. После преобразования, инструмент (см. ниже) можно свободно делать какие бы преобразования он ни хотел на IR, прежде чем Valgrind переводит IR обратно в машинный код и позволяет хост-процессор запускает его.

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

Еще один инструмент, основанный на Вальгринде, - это массив. Я использую его для использования памяти памяти кучи. Он отлично работает. Что он делает, так это то, что он дает вам снимки использования памяти - подробная информация WHAT содержит WHAT процент памяти, и ВОЗ положила его туда. Такая информация доступна в разные моменты времени запуска приложения.

50

Это ответ на ответ Nazgob Gprof.

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

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

  2. Граф вызовов путается указателями на функции. Пример. У меня есть функция multithread(), которая позволяет мне многопоточность указанной функции по указанному массиву (оба передаются как аргументы). Однако Gprof рассматривает все вызовы multithread() как эквивалентные для вычисления времени, затрачиваемого на детей. Поскольку некоторые функции, которые я передаю multithread(), занимают гораздо больше времени, чем другие, мои графики вызовов в основном бесполезны. (Тем, кто задается вопросом, является ли проблема с потоками: no, multithread() может быть необязательно, и в этом случае выполнял все последовательно только на вызывающем потоке).

  3. Он говорит здесь, что "... цифры ЧИСЛО-вызовов получены путем подсчета, не пробуя. Они абсолютно точны...". Тем не менее, я нахожу свой график вызовов, давая мне 5345859132 + 784984078 в качестве статистики звонка для моей самой вызываемой функции, где первым номером должны быть прямые вызовы, а также вторыми рекурсивными вызовами (которые все из себя). Поскольку это подразумевало, что у меня была ошибка, я вложил длинные (64-битные) счетчики в код и снова сделал тот же самый запуск. Мой счет: 5345859132 прямой и 78094395406 саморекурсивный вызов. Там много цифр, поэтому я укажу, что рекурсивные звонки, которые я измеряю, составляют 78 млрд, против 784 м от Gprof: коэффициент 100 раз. Оба прогона были однопоточными и неоптимизированными, один скомпилированный -g и другой -pg.

Это был GNU Gprof (GNU Binutils для Debian) 2.18.0.20080103, работающий под 64-разрядным Debian Lenny, если это кому-то помогает.

  • 0
    по-видимому, это может сделать выборку stackoverflow.com/a/11143125/32453
  • 0
    Да, это делает выборку, но не для числа вызовов. Интересно, что следование по вашей ссылке в конечном итоге привело меня к обновленной версии страницы руководства, на которую я ссылался в моем сообщении, по новому URL: sourceware.org/binutils/docs/gprof/… Это повторяет цитату в части (iii) моего ответа: но также говорит: «В многопоточных приложениях или однопоточных приложениях, которые связаны с многопоточными библиотеками, счетчик является только детерминированным, если функция подсчета является поточно-ориентированной. (Примечание: имейте в виду, что функция подсчета mcount в glibc не является поточной -безопасный)."
Показать ещё 1 комментарий
48

Ответ на запуск valgrind --tool=callgrind не является полным, без некоторых параметров. Обычно мы не хотим профилировать 10 минут медленного времени запуска под Valgrind и хотим профилировать нашу программу, когда она выполняет определенную задачу.

Так вот что я рекомендую. Сначала запустите программу:

valgrind --tool=callgrind --dump-instr=yes -v --instr-atstart=no ./binary > tmp

Теперь, когда он работает, и мы хотим начать профилирование, мы должны работать в другом окне:

callgrind_control -i on

Это включает профилирование. Чтобы отключить и остановить всю задачу, мы можем использовать:

callgrind_control -k

Теперь у нас есть файлы с именем callgrind.out. * в текущем каталоге. Для просмотра результатов профилирования используйте:

kcachegrind callgrind.out.*

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

  • 7
    Теперь по какой-то причине файлы callgrind.out. * Всегда были пустыми. Выполнение callgrind_control -d было полезно для принудительного сброса данных на диск.
  • 0
    Я запутался в этих инструкциях. Вы говорите, что во время работы программы мы можем выполнить callgrind_control в другом окне, чтобы включить / выключить профилирование? мне кажется, что было бы лучше разработать минимальную программу, включающую только то, что вы хотите профилировать, а затем профилировать всю программу.
Показать ещё 3 комментария
41

Oprofile - достойный бесплатный вариант, но мне повезло с помощью Zoom. Это коммерческий (бесплатный eval) профилировщик для Linux, который имеет графический интерфейс sweeet для просмотра горячих точек в исходном коде.

35

google-perftools является единственной разумной альтернативой Gprof Я нашел. Он довольно полезный, знакомый, и я считаю, что это время выборки, так что узкие места ввода-вывода выявлены, в дополнение к обычным узким местам, которые Gprof обнаруживает. Это также значительно менее инвазивное.

30

Вы можете посмотреть Gprof, профилировщик GNU.

Другим интересным инструментом может быть IBM Rational Quantify, но он не бесплатный.

29

Используйте Valgrind

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

28

В дополнение к Intel Vtune/AMD CodeAnalyst, perfmon2 - альтернатива OSS, для которой требуется исправленное ядро, чтобы открыть CPU счетчик производительности, и это даст вам различные показатели производительности, которые вы можете собрать.

perfmon2 по-прежнему специфичен для реализации, т.е. L2 промахи кэша называются по-разному на Intel Pentium III по сравнению с AMD64, и они начинают работу над perfmon3, что должно унифицировать API.

Но обычно Gprof будет работать достаточно хорошо, чтобы вы могли обнаружить медленный код.

26

Вы можете использовать сборщик/анализатор Sun Studio. Используя сбор может также использовать использование памяти памяти, потоки, MPI и т.д. Вы также получите хорошее представление временной шкалы вашей программы.

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

Вы можете получить этот (и другие очень полезные инструменты от Sun) в Oracle Solaris Studio 12.3.

23

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

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

19

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

Немного несвязанный, но Gprof сам может также выполнить профилирование выборки: Использовать callgrind как профилировщик выборки? ( "Плоский профиль основан в основном на выборке" )

И вы также можете использовать сигнал USR1 и др. для обратных трассировок нисходящих потоков.

18

Существует также LTTng. Я никогда не использовал этот, хотя я не могу сказать, насколько он работает. Но одно преимущество - это трассировка пользовательского пространства. В некоторых ситуациях, которые могут быть довольно приятными.

15

Вы можете проверить Gprof из проекта GNU.

Ниже приведены краткие руководства по началу работы:

13

Профайлер PCT использует подход выборки в стеке, рекомендованный другими респондентами, которые не предлагали конкретного инструмента.

Он может выполнять профилирование на уровне инструкций или на уровне процедур. Я использовал его для профилирования кода, отличного от C, в дополнение к коду C (я использовал его ранее для OCaml с интересными результатами).

8

Используйте Valgrind, callgrind и kcachegrind:

valgrind --tool=callgrind ./(Your binary)

генерирует callgrind.out.x. Прочитайте его с помощью kcachegrind.

Использовать gprof (add -pg):

cc -o myprog myprog.c utils.c -g -pg 

(не так хорошо для многопоточных, указателей функций)

Использовать google-perftools:

Использует выборку времени, выявляет узкие места ввода-вывода и процессора.

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

Другие: AMD Codeanalyst, OProfile, инструменты "perf" (apt-get install linux-tools)

7

Используйте SysProf; Это довольно хорошо, делая быстрое профилирование с минимальными хлопотами. Он показывает информацию о том, как много раз вызывалась функция, время, затрачиваемое на каждую процедуру, общее время, затрачиваемое на каждую функцию, и т.д. Просто установите, выполните начальную конфигурацию, а затем запустите приложение/службу (нет необходимости перекомпилировать instrument ваш код).

4

Для однопоточных программ вы можете использовать igprof, Ignominous Profiler: https://igprof.org/.

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

3

Вы можете попробовать профайлер AMD CodeXL. Он бесплатный и доступен для Linux.

Профайлер AMD CodeXL CPU заменяет более не поддерживаемый инструмент CodeAnalyst (который упоминался в ответе выше, указанном Anteru).

CodeXL поддерживает несколько методов профилирования CPU для процессоров AMD (для процессоров, отличных от AMD) поддерживается только профилирование профилей на основе времени.

Дополнительную информацию и ссылки для загрузки можно найти на странице веб-страницу AMD CodeXL.

2

Вот два метода, которые я использую для ускорения моего кода:

Для приложений с привязкой к ЦП:

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

Для связанных приложений ввода/вывода:

  • Используйте профилировщик в режиме RELEASE для определения сомнительных частей вашего кода.

N.B.

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

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

Для I/O-привязки профилировщик все еще может идентифицировать операции ввода-вывода в режиме RELEASE, поскольку операции ввода-вывода либо внешне связаны с общей библиотекой (большую часть времени), либо в в худшем случае, приведет к вектору прерывания sys-call (который также легко идентифицируется профилировщиком).

  • 1
    +1 Метод бедняка работает так же хорошо для привязки ввода / вывода, как и для привязки к процессору, и я рекомендую выполнять всю настройку производительности в режиме отладки. Когда вы закончите настройку, включите RELEASE. Это улучшит ситуацию, если программа в вашем коде связана с процессором. Вот грубое, но короткое видео процесса.
  • 3
    Я бы не использовал сборки DEBUG для профилирования производительности. Часто я видел, что критически важные для производительности части в режиме DEBUG полностью оптимизируются в режиме выпуска. Другая проблема - использование утверждений в отладочном коде, которые добавляют шум к производительности.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню