Skip to content

Performance

Стоит понимать, что оптимизирующий компилятор OCaml'а хоть и имеет под собой достаточно теории, но всё равно не сравниться с LLVM или GCC.

Документация

Важно

Наблюдения описываются применительно к ванильному компилятору версии 5.2. Для изучения результата компиляции использовался сервис godbolt.

Сборка с оптимизациями

Смотрите Release-сборка проекта и flambda.

Склейка строк

Если вам требуется склеить больше двух строк — не используйте оператор Stdlib.(^). Заместо него используйте модули Format, Printf или подобное.

Пример

ocaml
(* Плохо! *)
let greet name = 
  (* Почему: две аллокации (по одной на каждую склейку) *)
  print_endline @@ "Привет, " ^ name ^ "!"

(* Хорошо *)
let greet name = 
  (* Почему: примерно одна аллокация *)
  Printf.printf "Привет, %s!\n" name

Компилятор никак не сворачивает строковые константы, то есть склейка констант производится в рантайме! Будьте осторожны.

Микрооптимизации

Использование буфера дает явный контроль над выделением памяти.

ocaml
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

Частичное применение

Старайтесь не определять ваши функции через частичное применение. Функция это сложный объект, проще вернуть любое другое значение.

Пример

ocaml
(* Генерирует больше кода! *)
let factorial = 
  let rec aux acc n = (* ... *)
  in aux 1

(* Эффективно *)
let factorial n = 
  let rec aux acc n = (* ... *)
  in aux 1 n

Memory management

Ахтунг

Эта секция требует больше подробностей и большей квалификации в устройстве рантайма.

Наблюдение потребления памяти для OCaml 5

Складывается ощущение, что сборщик мусора очень не охотно собирает мусор, так как при растущих на грузках программу, её потребление памяти начинаются неограниченно увеличиваться, а когда нагрузки нет, то она оставляет при себе весь объём памяти.

Inlining

Компилятор умеет понимать, когда стоит заинлайнить ту или иную функцию, но если вы хотите явно потребовать этого, то для этого используйте аттрибут.

Аттрибут inline при определении функции, говорящая, что эта функция должна быть заинлайнена, но для этого не должна быть частично применённой.

ocaml
let[@inline] add x y = x + y

Аттрибут inlined может использоваться при применение функции, что бы заинлайнить конкретную функцию, но для этого она не должна быть частично применённой.

ocaml
let _ = (add[@inlined]) 10 0