Я пытаюсь выполнить выполнение функции, прежде чем пытаться ее оптимизировать. (Код Elixir, но я использую Erlang's :timer.tc
.)Почему функция работает быстрее, чем больше я ее называю?
Мой общий подход «запускайте его много раз, а затем вычислите среднюю продолжительность». Но среднее снижение резко больше, чем больше я запускаю его (до точки).
Пример:
some_func = fn ->
# not my actual function; it's a pure function,
# but exhibits the same speedup
:rand.uniform()
end
run_n_times = fn (count, func) ->
Enum.each(1..count, fn (_i) ->
func.()
end)
end
n = 20
{microseconds, :ok} = :timer.tc(run_n_times, [n, some_func])
IO.puts "#{microseconds/n} microseconds per call (#{microseconds} total for #{n} calls)"
выходов для увеличения значения n
, как это (слегка отформатирован):
174.8 microseconds per call (3496 total for 20 calls)
21.505 microseconds per call (4301 total for 200 calls)
4.5755 microseconds per call (9151 total for 2000 calls)
0.543415 microseconds per call (108683 total for 200000 calls)
0.578474 microseconds per call (578474 total for 1000000 calls)
0.5502955 microseconds per call (1100591 total for 2000000 calls)
0.556457 microseconds per call (2225828 total for 4000000 calls)
0.544754125 microseconds per call (4358033 total for 8000000 calls)
Почему функция работать быстрее, чем больше я это называю, и что это означает для бенчмаркинга? Например, существует ли правило большого пальца, как «запустить что-то> = 200 тыс. Раз для сравнения»?
Вы также должны добавить очень короткие эталонные пробеги (3,5 мс для 20 прогонов, 4,3 мс для 200, 9 мс на 2000 год), вы также можете наблюдать, что у процессора не хватает времени, чтобы проснуться из режимов малой мощности в современных высокочастотных системах на мобильных платформах. Тест должен, по крайней мере, принимать 100 мс, но предпочтительно несколько секунд. –