Performance
Стоит понимать, что оптимизирующий компилятор OCaml'а хоть и имеет под собой достаточно теории, но всё равно не сравниться с LLVM или GCC.
Документация
Важно
Наблюдения описываются применительно к ванильному компилятору версии 5.2
. Для изучения результата компиляции использовался сервис godbolt.
Сборка с оптимизациями
Смотрите Release-сборка проекта и flambda.
Склейка строк
Если вам требуется склеить больше двух строк — не используйте оператор Stdlib.(^)
. Заместо него используйте модули Format
, Printf
или подобное.
Пример
(* Плохо! *)
let greet name =
(* Почему: две аллокации (по одной на каждую склейку) *)
print_endline @@ "Привет, " ^ name ^ "!"
(* Хорошо *)
let greet name =
(* Почему: примерно одна аллокация *)
Printf.printf "Привет, %s!\n" name
Компилятор никак не сворачивает строковые константы, то есть склейка констант производится в рантайме! Будьте осторожны.
Микрооптимизации
Использование буфера дает явный контроль над выделением памяти.
let greet name =
let buf = Buffer.create (16 + String.length name) in
Buffer.add_string buf "Привет, ";
Buffer.add_string buf name;
Buffer.add_string buf "!\n";
Buffer.output_buffer stdout buf
Частичное применение
Старайтесь не определять ваши функции через частичное применение. Функция это сложный объект, проще вернуть любое другое значение.
Пример
(* Генерирует больше кода! *)
let factorial =
let rec aux acc n = (* ... *)
in aux 1
(* Эффективно *)
let factorial n =
let rec aux acc n = (* ... *)
in aux 1 n