Почему такая большая разница во времени GC в двух реализациях - PullRequest
0 голосов
/ 18 октября 2011

имеют две реализации алгоритма:

average(List) -> sum(List) / len(List).

sum([]) -> 0;
sum([Head | Tail]) -> Head + sum(Tail).

len([]) -> 0;
len([_ | Tail]) -> 1 + len(Tail).



average1(List) -> average_acc(List, 0,0).

average_acc([], Sum, Length) -> Sum / Length;
average_acc([H | T], Sum, Length) -> average_acc(T, Sum + H, Length + 1).

и вывод для событий трассировки GC gc_start gc_end (запуск и остановка gc):

здесь каждое следующее значение для процесса является суммой предыдущего значения и времени последнего gc

в среднем: 5189 средний: 14480 средний: 15118

Среднее1: 594

Почему такая большая разница?

PS. Я использую настенные часы.

1 Ответ

2 голосов
/ 18 октября 2011
  1. Не следует использовать время настенных часов (флаг timestamp), чтобы измерить, что берет GC, потому что даже GC не перепланирован в потоке планировщика Erlang, а сам поток может быть перепланирован базовой ОС. Таким образом, вы должны использовать cpu_timestamp вместо.
  2. Ваш average/1 использует sum/1 и count/1 реализацию, где оба не являются хвостовыми рекурсивами , поэтому вы выделяете 2*N стековых фреймов, что сильно влияет на производительность average1/1, использующим хвост рекурсивный average_acc/3. Так что average1/1 работает точно так же, как цикл в других языках.

Edit:

  1. Отредактировано согласно заявлению Йолы о том, что он использует флаг timestamp для сообщений трассировки.
...