CpuUtil (CpuUtil v0.6.0)

CPU utility functions.

Functions to read and calculate CPU utilization for a given process.

NOTE: Only *nix systems supported.

Link to this section Summary

Functions

Calculate CPU utilization given 2 readings.

Get the number of CPU Cores.

Get the cpu for the given os_pid and number of cores.

Get the current OS PID.

Read the CPU's average load.

Get the number of CPU Cores.

Get the current OS stat.

Calculate the OS process CPU Utilization.

Read the OS stat data.

Parse the data read from /proc/stat.

Get the current OS <PID> stat.

Get the total_time from the given list.

Get the total_time.

Get the total time given the contents of "/proc/stat"

Link to this section Types

Link to this type

proc_pid_stat()

Specs

proc_pid_stat() :: %{
  pid: integer(),
  tcomm: binary(),
  state: binary(),
  ppid: integer(),
  pgrp: integer(),
  sid: integer(),
  tty_nr: integer(),
  tty_pgrp: integer(),
  flags: integer(),
  min_flt: integer(),
  cmin_flt: integer(),
  maj_flt: integer(),
  cmaj_flt: integer(),
  utime: integer(),
  stime: integer(),
  cutime: integer(),
  cstime: integer()
}

Specs

util() :: %{sys: float(), total: float(), user: float()}

Specs

util_stat() :: %{stats: proc_pid_stat(), total: integer()}

Link to this section Functions

Link to this function

calc_pid_util(prev, curr, cores \\ 1, precision \\ 1)

Calculate CPU utilization given 2 readings.

Algorithm

user_util = 100 (utime_after - utime_before) / (time_total_after - time_total_before); sys_util = 100 (stime_after - stime_before) / (time_total_after - time_total_before);

Usage

> pid = CpuUtil.os_pid()
> cores = CpuUtil.num_cores()
> u1 = CpuUtil.pid_util(pid)
> Process.sleep(1000)
> u2 = CpuUtil.pid_util(pid)
> CpuUtil.calc_pid_util(u1, u2, cores)
%{
   user: 2.0,
   sys: 0.5,
   total: 2.5
}

References

Examples

iex> prev = %{total: 99, stats: %{utime: 20, stime: 10}}
iex> curr = %{total: 248, stats: %{utime: 29, stime: 18}}
iex> CpuUtil.calc_pid_util(prev, curr)
%{sys: 5.4, total: 11.4, user: 6.0}

iex> prev = %{total: 99, stats: %{utime: 20, stime: 10}}
iex> curr = %{total: 248, stats: %{utime: 29, stime: 18}}
iex> CpuUtil.calc_pid_util(prev, curr, 2, 2)
%{sys: 10.74, total: 22.82, user: 12.08}

Specs

core_count() :: {:ok, integer()} | :error

Get the number of CPU Cores.

Examples

iex> {:ok, cores} = CpuUtil.core_count()
iex> is_integer(cores)
true
Link to this function

get_cpu_util(pid, opts \\ [])

Specs

get_cpu_util(
  integer(),
  keyword()
) :: util()

Get the cpu for the given os_pid and number of cores.

Blocks the calling process for time (1) seconds to collect the before and after samples.

Specs

getpid() :: integer()

Get the current OS PID.

Examples

iex> CpuUtil.getpid() |> is_integer()
true
Link to this function

loadavg(num \\ 1)

Specs

loadavg(integer()) :: binary()

Read the CPU's average load.

Examples

iex> {float, ""} = CpuUtil.loadavg() |> Float.parse()
iex> is_float(float)
true

Specs

num_cores() :: {:ok, integer()} | :error

Get the number of CPU Cores.

Deprecated! Use CpuUtil.core_count/0 instead.

Specs

pid_util(integer()) :: util_stat()

Get the current OS stat.

  • Read the total time from /proc/stat
  • Read the PID stats from /proc/<PID>/stat

Return a map:

%{
  total: integer()
  stats: proc_pid_stat()
}

Examples

iex> fields = ~w(cmaj_flt cmin_flt cstime cutime flags maj_flt min_flt pgrp pid ppid sid
...>             state stime tcomm tty_nr tty_pgrp utime)a
iex> util = CpuUtil.pid_util(CpuUtil.getpid())
iex> Map.keys(util) == ~w(stats total)a and is_integer(util.total) and
...>   Map.keys(util.stats) == fields
true
Link to this function

process_util(prev, curr, opts \\ [])

Specs

process_util({binary(), binary()}, {binary(), binary()}, keyword()) :: util()

Calculate the OS process CPU Utilization.

Similar to CpuUtil.calc_pid_util/4 except that it takes the raw binary data read from {"/proc/stat", "/proc/<os_pid>/stat"}.

Examples

iex> prev = {"cpu  11380053 51 3665881 1638097578 194367 213 149713 110770 0",
...> "9930 (beam.smp) S 24113 9930 24113 34817 9930 4202496 189946 5826 0 0 12025 1926 " <>
...> "0 0 20 0 28 0 275236728 3164401664 42600 18446744073709551615 4194304 7475860 " <>
...> "140732561929584 140732561927920 256526653091 0 0 4224 134365702 18446744073709551615 " <>
...> "0 0 17 3 0 0 0 0 0"}
iex> curr = {"cpu  11380060 51 3665883 1638099001 194367 213 149713 110770 0",
...> "9930 (beam.smp) S 24113 9930 24113 34817 9930 4202496 189950 5826 0 0 12027 1927 " <>
...> "0 0 20 0 28 0 275236728 3164401664 42600 18446744073709551615 4194304 7475860 " <>
...> "140732561929584 140732561927920 256526653091 0 0 4224 134365702 18446744073709551615 " <>
...> "0 0 17 3 0 0 0 0 0"}
iex> CpuUtil.process_util(prev, curr)
%{sys: 0.1, total: 0.2, user: 0.1}

Specs

stat() :: list() | {:error, any()}

Read the OS stat data.

  • Reads /proc/stat
  • Parses the first line ('cpu')
  • Converts the numbers (string) to integers

Examples

iex> ["cpu" | numbers] = CpuUtil.stat()
iex> length(numbers) == 10 and Enum.all?(numbers, &is_integer/1)
true

Specs

stat(binary()) :: list() | {:error, any()}

Parse the data read from /proc/stat.

Extract the first line "cpu" and convert numbers to integers.

Examples

iex> CpuUtil.stat("cpu 12010882 75 3879349 1731141995 200300 225 154316 115184 0") ["cpu", 12010882, 75, 3879349, 1731141995, 200300, 225, 154316, 115184, 0]

Specs

stat_pid(integer() | binary()) :: proc_pid_stat() | {:error, any()}

Get the current OS <PID> stat.

  • Read /proc/<PID>/stat (single line of space separated fields)
  • Parse the fields and convert any numbers (string) to integers

Returns a map of of the fields (atom keys) per the following definition:

  • pid process id
  • tcomm filename of the executable
  • state state (R is running, S is sleeping, D is sleeping in an
  •            uninterruptible wait, Z is zombie, T is traced or stopped)
  • ppid process id of the parent process
  • pgrp pgrp of the process
  • sid session id
  • tty_nr tty the process uses
  • tty_pgrp pgrp of the tty
  • flags task flags
  • min_flt number of minor faults
  • cmin_flt number of minor faults with child's
  • maj_flt number of major faults
  • cmaj_flt number of major faults with child's
  • utime user mode jiffies
  • stime kernel mode jiffies
  • cutime user mode jiffies with child's
  • cstime kernel mode jiffies with child's

Examples

iex> CpuUtil.stat_pid(CpuUtil.getpid()) |> Map.keys()
~w(cmaj_flt cmin_flt cstime cutime flags maj_flt min_flt pgrp pid ppid sid state stime tcomm tty_nr tty_pgrp utime)a

# iex> str = "9731 (beam.smp) S 9730 9730 9730 0 -1 4202496 13784 3143 0 0 93 11 0 0 20 0 "
# iex> str = str <> "28 0 291467565 2993774592 15101 18446744073709551615 4194304 7475860 "
# iex> str = str <> "140732224047216 140732224045552 256526653091 0 0 4224 16902 "
# iex> str = str <> "18446744073709551615 0 0 17 3 0 0 0 0 0"
iex> content = "9731 (beam.smp) S 9730 9730 9730 0 -1 4202496 13784 3143 0 0 93 11 0 0 " <>
...> "20 0 291467565 2993774592 15101 18446744073709551615 4194304 7475860 140732224047216 " <>
...> "140732224047216 140732224045552 256526653091 0 0 4224 16902 18446744073709551615 0 " <>
...> "0 17 3 0 0 0 0 0"
iex> CpuUtil.stat_pid(content)
%{
  cmaj_flt: 0,
  cmin_flt: 3143,
  cstime: 0,
  cutime: 0,
  flags: 4202496,
  maj_flt: 0,
  min_flt: 13784,
  pgrp: 9730,
  pid: 9731,
  ppid: 9730,
  sid: 9730,
  state: "S",
  stime: 11,
  tcomm: "(beam.smp)",
  tty_nr: 0,
  tty_pgrp: "-1",
  utime: 93
}
Link to this function

stat_total_time(list)

Specs

stat_total_time(list()) :: integer()

Get the total_time from the given list.

Takes the output of CpuUtil.stat/0 and returns the total time.

Examples

iex> data = ["cpu", 12010882, 75, 3879349, 1731141995, 200300, 225, 154316, 115184, 0]
iex> CpuUtil.stat_total_time(data)
1747502326

Specs

total_time() :: integer()

Get the total_time.

Return the total time (from /proc/stat) as an integer.

Examples

iex> CpuUtil.total_time() |> is_integer()
true
Link to this function

total_time(stat)

Specs

total_time(binary()) :: integer() | float()

Get the total time given the contents of "/proc/stat"

Examples

iex> CpuUtil.total_time("cpu 12010882 75 3879349 1731141995 200300 225 154316 115184 0")
1747502326