Одна вещь, которую вы можете сделать, это вызвать функцию, которая имеет много кода и обращается к большому количеству памяти между вызовами к профилируемому элементу.Например, в псевдокоде (который в основном не зависит от языка):
// loop some number of times
{
//start timing
profile_func();
//stop timing
//add to total time
large_func(); // Uses lots of memory and has lots of code
}
// Compute time of profile func by dividing number of iterations by total time
Код в large_func () может быть бессмысленным кодом, как некоторый набор операций, повторяемых снова и снова.Ключевым моментом является то, что он или его код не оптимизируются при компиляции, так что он фактически очищает кэш кода и данных ЦП (а также кеш L2 и L3 (если имеется)).
Это очень важный тест для многих случаев.Это важно по той причине, что небольшие быстрые функции, которые часто профилируются изолированно, могут работать очень быстро, используя кэш-память ЦП, встраивание и регистрацию.Но часто в больших приложениях эти преимущества отсутствуют из-за контекста, в котором эти быстрые функции вызываются.
Например, простое профилирование функции путем запуска ее в течение миллиона итераций в узком цикле может показать, что функция выполняется, скажем, за 50 наносекунд.Затем вы запускаете его с помощью инфраструктуры, которую я показал выше, и внезапно его время работы может резко увеличиться до микросекунд, потому что он больше не может использовать тот факт, что у него есть весь процессор - его регистры и кэши, для себя.