Каждый создатель программного обеспечения хорошо знает, что эталонные тесты очень важны. Они доказывают, что ваше программное обеспечение не только работает, но и хорошо масштабируется и правильно работает при перегрузке. Сравнительный анализ также может помочь вам узнать ограничения вашей программы. Мы проводили тесты Membrane с самого начала, но заметили, что измерения использования ЦП и памяти часто нам недостаточно. Это привело нас к созданию инструмента для измерения большего количества параметров. Поскольку большая часть программного обеспечения Membrane написана на Elixir, мы сосредоточились на конкретных параметрах Elixir, таких как использование планировщика, сокращения и количество переключений контекста. Так родился BEAMchmark.

BEAMchmark, как следует из названия, используется для тестирования BEAM (виртуальная машина Erlang), которая стоит за выполнением каждого приложения Elixir. Чтобы понять, чем BEAMchmark отличается от типичных тестовых сценариев, давайте кратко рассмотрим, как выполняются процессы Elixir.

Начнем с ОТП. OTP (Open Telecom Platform) — неотъемлемая часть дистрибутива Elixir, предоставляющая абстракции, используемые разработчиками для определения процессов, управления ими, настройки дерева наблюдения (для описания отношений между процессами) и передачи сообщений между процессами. Процессы в OTP могут выполняться одновременно, а также могут взаимодействовать друг с другом, поэтому они могут взаимодействовать друг с другом. Процессы иногда сравнивают с потоками, существующими в других языках, но они намного легче.

Часть BEAM, управляющая выполнением процессов, называется планировщиком, и его работа основана на редукциях (каждый вызов функции — это редукция). Он работает в непрерывном цикле, последовательно запуская процессы из очереди выполнения, но позволяя им делать только определенное количество сокращений на каждом этапе. Это позволяет BEAM запускать процессы одновременно даже с одним планировщиком. Процессы, которые не завершили выполнение, но только что достигли предела сокращения, все еще находятся в очереди выполнения, даже если они не влияют на ЦП. Вот почему измерение производительности BEAM иногда может быть более точным для приложений Elixir, чем измерение чистого использования ЦП.

BEAMchmark сообщает о проценте времени выполнения, когда конкретный планировщик занят. Он также может показать вам общее количество сокращений и количество переключений контекста (моменты, когда планировщик изменяет текущий запущенный процесс). Это очень важно, когда вам нужно наблюдать, как небольшие изменения влияют на производительность вашего приложения.

Чтобы вы могли легко увидеть, как он изменился, BEAMchmark также представляет результаты как разницу между текущим и предыдущим запуском скрипта:

Чтобы использовать BEAMchmark, вам нужно создать скрипт со сценарием, который вы хотите протестировать. Затем вы можете запустить свое приложение с указанными условиями, которые вы хотите протестировать.

Вы можете увеличивать нагрузку постепенно или просто посмотреть, как она будет вести себя с течением времени:

defmodule SimpleScenario do
  @moduledoc false

  @behaviour Beamchmark.Scenario

  @impl true
  def run() do
    1..1_000
    |> Stream.cycle()
    |> Stream.each(fn i -> Integer.pow(i, 2) end)
  end
end

Beamchmark.run(SimpleScenario, duration: 5, delay: 1)

Мы используем BEAMchmark во время работы над производительностью библиотек Membrane, и это помогло нам увидеть то, чего мы раньше не замечали. И теперь вы можете сделать то же самое со своими приложениями. Вы можете найти BEAMchmark здесь: https://github.com/membraneframework/beamchmark. Это открытый исходный код, как и все другие элементы Membrane, так что возьмите его и используйте, чтобы сделать свое программное обеспечение лучше.