Module: LinuxStat::CPU

Defined in:
lib/linux_stat/cpu.rb

Class Method Summary collapse

Class Method Details

.countObject

Returns the total number of CPU threads configured for the sysetm.

If the information isn’t available, it will return 0.



95
96
97
98
99
100
# File 'lib/linux_stat/cpu.rb', line 95

def count
  # Let's rely on sysconf(_SC_NPROCESSORS_ONLN), which is 100x faster than running:
  # IO.read('/sys/devices/system/cpu/online')[-2].to_i + 1

  LinuxStat::Sysconf.processor_online
end

.cur_freqObject

Returns an array with current core frequencies corresponding to the usages.

If the information isn’t available, it will return an empty array.



116
117
118
119
120
121
122
123
124
125
# File 'lib/linux_stat/cpu.rb', line 116

def cur_freq
  @@cpu_freqs ||= Dir["/sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_cur_freq"]
  @@cur_freqs_readable ||= @@cpu_freqs.all?(&File.method(:readable?))

  if @@cur_freqs_readable
    @@cpu_freqs.map { |x| IO.read(x).to_i }
  else
    []
  end
end

.max_freqObject

Returns an array with max core frequencies corresponding to the usages.

If the information isn’t available, it will return an empty array.



131
132
133
134
135
136
137
138
139
140
# File 'lib/linux_stat/cpu.rb', line 131

def max_freq
  @@max_freqs ||= Dir["/sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_max_freq"]
  @@max_freqs_readable ||= @@max_freqs.all?(&File.method(:readable?))

  if @@max_freqs_readable
    @@max_freqs.map { |x| IO.read(x).to_i }
  else
    []
  end
end

.modelObject

Returns the model of processor.

If the information isn’t available, it will return en empty string.

The output is also cached (memoized) ; as changing the value in runtime is unexpected.



108
109
110
# File 'lib/linux_stat/cpu.rb', line 108

def model
  @@name ||= cpuinfo.find { |x| x.start_with?('model name') }.to_s.split(?:)[-1].to_s.strip
end

.onlineObject

Returns the total number of CPU threads online now.

This value can change while a CPU is offline, due to kernel’s hotplugging feature.

If the information isn’t available, it will return 0.



84
85
86
87
88
89
# File 'lib/linux_stat/cpu.rb', line 84

def online
  # Let's rely on sysconf(_SC_NPROCESSORS_CONF), which is 100x faster than
  # counting online cpu from /sys/devices/system/cpu

  LinuxStat::Sysconf.processor_configured
end

.stat(sleep = ticks_to_ms_t5) ⇒ Object Also known as: usages

stat(sleep = 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)

Where sleep is the delay to gather the data.

The minimum possible value at anytime is 1.0 / LinuxStat::Sysconf.sc_clk_tck

This method returns the cpu usage of all threads.

The first one is aggregated CPU usage reported by the Linux kernel.

And the consecutive ones are the real core usages.

On a system with 4 threads, the output will be like

1=>100.0, 2=>50.0, 3=>87.5, 4=>87.5

If the information is not available, it will return an empty Hash



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/linux_stat/cpu.rb', line 21

def stat(sleep = ticks_to_ms_t5)
  return {} unless stat?

  data = IO.readlines('/proc/stat').select! { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
  sleep(sleep)
  data2 = IO.readlines('/proc/stat').select! { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }

  # On devices like android, the core count can change anytime (hotplugging).
  # I had crashes on Termux.
  # So better just count the min number of CPU and iterate over that
  # If data.length is smaller than data2.length, we don't have enough data to compare.
  dl, d2l = data.length, data2.length
  min = dl > d2l ? d2l : dl

  min.times.reduce({}) do |h, x|
    user, nice, sys, idle, iowait, irq, softirq, steal = *data[x].drop(1)
    user2, nice2, sys2, idle2, iowait2, irq2, softirq2, steal2 = *data2[x].drop(1)

    idle_then, idle_now  = idle + iowait, idle2 + iowait2
    totald = idle_now.+(user2 + nice2 + sys2 + irq2 + softirq2 + steal2) - idle_then.+(user + nice + sys + irq + softirq + steal)

    res = totald.-(idle_now - idle_then).fdiv(totald).*(100).round(2).abs
    res = 0.0 if res.nan?

    h.merge!(
      x => res
    )
  end
end

.total_usage(sleep = ticks_to_ms_t5) ⇒ Object Also known as: usage

total_usage(sleep = 1.0 / LinuxStat::Sysconf.sc_clk_tck)

Where sleep is the delay to gather the data.

The minimum possible value at anytime is 1.0 / LinuxStat::Sysconf.sc_clk_tck

This method returns the cpu usage of all threads.

It’s like running LinuxStat::CPU.stat but it’s much more efficient and calculates just the aggregated usage which is available at the top of the /proc/stat file.

If the information is not available, it will return nil.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/linux_stat/cpu.rb', line 63

def total_usage(sleep = ticks_to_ms_t5)
  return nil unless stat?

  data = IO.foreach('/proc/stat').first.split.tap(&:shift).map!(&:to_f)
  sleep(sleep)
  data2 = IO.foreach('/proc/stat').first.split.tap(&:shift).map!(&:to_f)

  user, nice, sys, idle, iowait, irq, softirq, steal = *data
  user2, nice2, sys2, idle2, iowait2, irq2, softirq2, steal2 = *data2

  idle_then, idle_now  = idle + iowait, idle2 + iowait2
  totald = idle_now.+(user2 + nice2 + sys2 + irq2 + softirq2 + steal2) - idle_then.+(user + nice + sys + irq + softirq + steal)
  totald.-(idle_now - idle_then).fdiv(totald).*(100).round(2).abs
end