Я делаю некоторые акцизы на основе списка 99-проблем. Для P01, целью которого является найти последний элемент списка, моя реализация почти всегда превосходит List.last/1
, оставаясь неизменной. Разница составляет около 20%, но между исполнениями существует довольно много различий (иногда более 100%). Тесты выполняются на только что перезапущенной виртуальной машине, а функции называются 10, 100 и 1000 в списке из одного миллиона элементов.
Это моя реализация:
def p01([]), do: nil
def p01([h]), do: h
def p01([_ | r]), do: p01(r)
При ближайшем рассмотрении List.last/1
источник показывает, однако, 2 различия
- Директива компилятора
@compile :inline_list_funcs
, которая, как я понимаю, является директивой Erlang, применяемой только к текущему модулю. Я не уверен, реально ли это повлияет на мой короткий фрагмент кода
- Спецификация типа
@spec last([elem]) :: nil | elem when elem: var
Эти два изменения значительно приблизили время выполнения моей реализации к временам List.last/1
.
Q1 : Использует ли компилятор @spec...
для какой-либо оптимизации кода?
Q2 : побочный вопрос: в моих тестах функция стандартной библиотеки erlang :lists.last/1
всегда работала лучше, чем List.last/1
. Опять же, есть несколько вариаций между двумя прогонами, но разница довольно стабильна. Почему List.last/1
не простая оболочка для реализации Erlang?