# `Beamchmark`
[🔗](https://github.com/membraneframework/beamchmark/blob/v1.4.2/lib/beamchmark.ex#L1)

Top level module providing `Beamchmark.run/2` and `Beamchmark.run_attached/2` API.

`Beamchmark` measures EVM performance while it is running user `Beamchmark.Scenario`.

# Metrics being measured

## Scheduler Utilization

At the moment, the main interest of `Beamchmark` is scheduler utilization which tells
how much given scheduler was busy.
Scheduler is busy when:
* Executing process code
* Executing linked-in driver or NIF code
* Executing BIFs, or any other runtime handling
* Garbage collecting
* Handling any other memory management

Scheduler utilization is measured using Erlang's [`:scheduler`](`:scheduler`) module which uses `:erlang.statistics/1`
under the hood and it is represented as a floating point value between 0.0 and 1.0 and percent.

`Beamchmark` measures following types of scheduler utilization:
* normal/cpu/io - average utilization of single scheduler of given type
* total normal/cpu/io - average utilization of all schedulers of given type. E.g total normal equals 1.0 when
each of normal schedulers have been active all the time
* total - average utilization of all schedulers
* weighted - average utilization of all schedulers weighted against maximum amount of available CPU time

For more information please refer to `:erlang.statistics/1` (under `:scheduler_wall_time`) or `:scheduler.utilization/1`.

## Other

Other metrics being measured:
* reductions - total reductions number
* context switches - total context switches number

# `options_t`

```elixir
@type options_t() :: [
  name: String.t(),
  duration: pos_integer(),
  cpu_interval: pos_integer(),
  memory_interval: pos_integer(),
  delay: non_neg_integer(),
  formatters: [Beamchmark.Formatter.t()],
  compare?: boolean(),
  output_dir: Path.t()
]
```

Configuration for `Beamchmark`.
* `name` - name of the benchmark. It can be used by formatters.
* `duration` - time in seconds `Beamchmark` will be benchmarking EVM. Defaults to `60` seconds.
* `cpu_interval` - time in milliseconds `Beamchmark` will be benchmarking cpu usage. Defaults to `1000` milliseconds. Needs to be greater than or equal to `interfere_timeout`.
* `memory_interval` - time in milliseconds `Beamchmark` will be benchmarking memory usage. Defaults to `1000` milliseconds. Needs to be greater than or equal to `interfere_timeout`.
* `delay` - time in seconds `Beamchmark` will wait after running scenario and before starting benchmarking. Defaults to `0` seconds.
* `formatters` - list of formatters that will be applied to the result. By default contains only `[Beamchmark.Formatters.Console]`.
* `compare?` - boolean indicating whether formatters should compare results for given scenario with the previous one. Defaults to `true.`
* `output_dir` - directory where results of benchmarking will be saved. Defaults to "`beamchmark`" directory under location provided by `System.tmp_dir!/0`.

# `run`

```elixir
@spec run(Beamchmark.Scenario.t(), options_t()) :: :ok
```

Runs scenario and benchmarks EVM performance.

If `compare?` option equals `true`, invocation of this function will also compare new measurements with the last ones.
Measurements will be compared only if they share the same scenario module, delay and duration.

# `run_attached`

```elixir
@spec run_attached(node(), options_t()) :: :ok
```

Executes `Beamchmark.run/2` on a given node.

This function can be used to measure performance of an already running node.
The node which we are connecting to has to be a distributed node.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
