---
name: "scheduler"
section: "3erl"
platform: "linux"
package: "erlang-manpages"
version: "1:25.2.3+dfsg-1+deb12u4"
release: "Debian 12 (Bookworm)"
platforms: ["linux"]
url: "https://new.carta.tech/scheduler/3erl"
---

# scheduler(3erl)

Measure scheduler utilization

## NAME

scheduler - Measure scheduler utilization

## DESCRIPTION

This module contains utility functions for easy measurement and calculation of scheduler utilization. It act as a wrapper around the more primitive API *erlang:statistics(scheduler\_wall\_time)*.

The simplest usage is to call the blocking *scheduler:utilization(Seconds)*.

For non blocking and/or continuous calculation of scheduler utilization, the recommended usage is:

- \*

  First call *erlang:system\_flag(scheduler\_wall\_time,true)* to enable scheduler wall time measurements.

- \*

  Call *get\_sample/0* to collect samples with some time in between.

- \*

  Call *utilization/2* to calculate the scheduler utilization in the interval between two samples.

- \*

  When done call *erlang:system\_flag(scheduler\_wall\_time,false)* to disable scheduler wall time measurements and avoid unecessary cpu overhead.

To get correct values from *utilization/2*, it is important that *scheduler\_wall\_time* is kept enabled during the entire interval between the two samples. To ensure this, the process that called *erlang:system\_flag(scheduler\_wall\_time,true)* must be kept alive, as *scheduler\_wall\_time* will automatically be disabled if it terminates.

## DATA TYPES

```
sched_sample()
```

```
sched_type() = normal | cpu | io
```

```
sched_id() = integer()
```

```
sched_util_result() =
    [{sched_type(), sched_id(), float(), string()} |
     {total, float(), string()} |
     {weighted, float(), string()}]
```

A list of tuples containing results for individual schedulers as well as aggregated averages. *Util* is the scheduler utilization as a floating point value between 0.0 and 1.0. *Percent* is the same utilization as a more human readable string expressed in percent.

- ***{normal, SchedulerId, Util, Percent}*:**

  Scheduler utilization of a normal scheduler with number *SchedulerId*. Schedulers that are not online will also be included. Online schedulers have the lowest *SchedulerId*.

- ***{cpu, SchedulerId, Util, Percent}*:**

  Scheduler utilization of a dirty-cpu scheduler with number *SchedulerId*.

- ***{io, SchedulerId, Util, Percent}*:**

  Scheduler utilization of a dirty-io scheduler with number *SchedulerId*. This tuple will only exist if both samples were taken with *sample\_all/0*.

- ***{total, Util, Percent}*:**

  Total utilization of all normal and dirty-cpu schedulers.

- ***{weighted, Util, Percent}*:**

  Total utilization of all normal and dirty-cpu schedulers, weighted against maximum amount of available CPU time.

## EXPORTS

```
get_sample() -> sched_sample() | undefined
```

Returns a scheduler utilization sample for normal and dirty-cpu schedulers. Returns *undefined* if system flag *scheduler\_wall\_time* has not been enabled.

```
get_sample_all() -> sched_sample() | undefined
```

Return a scheduler utilization sample for all schedulers, including dirty-io schedulers. Returns *undefined* if system flag *scheduler\_wall\_time* has not been enabled.

```
sample() -> sched_sample()
```

Return a scheduler utilization sample for normal and dirty-cpu schedulers. Will call *erlang:system\_flag(scheduler\_wall\_time,true)* first if not already already enabled.

**Note:**

This function is *not recommended* as there is no way to detect if *scheduler\_wall\_time* already was enabled or not. If *scheduler\_wall\_time* has been disabled between two samples, passing them to *utilization/2* will yield invalid results.

Instead use *get\_sample/0* together with *erlang:system\_flag(scheduler\_wall\_time,\_)*.

```
sample_all() -> sched_sample()
```

Return a scheduler utilization sample for all schedulers, including dirty-io schedulers. Will call *erlang:system\_flag(scheduler\_wall\_time,true)* first if not already already enabled.

**Note:**

This function is *not recommended* for same reason as *sample/0*. Instead use *get\_sample\_all/0* together with *erlang:system\_flag(scheduler\_wall\_time,\_)*.

```
utilization(Seconds) -> sched_util_result()
```

Types:

Seconds = integer() \>= 1\

Measure utilization for normal and dirty-cpu schedulers during *Seconds* seconds, and then return the result.

Will automatically first enable and then disable *scheduler\_wall\_time*.

```
utilization(Sample) -> sched_util_result()
```

Types:

Sample = sched\_sample()\

Calculate scheduler utilizations for the time interval from when *Sample* was taken and "now". The same as calling *scheduler:utilization(Sample, scheduler:sample\_all())*.

**Note:**

This function is *not recommended* as it's so easy to get invalid results without noticing. In particular do not do this:

```
scheduler:utilization(scheduler:sample()). % DO NOT DO THIS!
```

The above example takes two samples in rapid succession and calculates the scheduler utilization between them. The resulting values will probably be more misleading than informative.

Instead use *scheduler:utilization/2* and call *get\_sample/0* to get samples with some time in between.

```
utilization(Sample1, Sample2) -> sched_util_result()
```

Types:

Sample1 = Sample2 = sched\_sample()\

Calculates scheduler utilizations for the time interval between the two samples obtained from calling *get\_sample/0* or *get\_sample\_all/0*.

This function itself, does not need *scheduler\_wall\_time* to be enabled. However, for a correct result, *scheduler\_wall\_time* must have been enabled during the entire interval between the two samples.
