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. If the information isn’t available, it will return 0.



66
67
68
69
# File 'lib/linux_stat/cpu.rb', line 66

def count
  # CPU count can change during the program runtime
  cpuinfo.count { |x| x.start_with?('processor') }
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.



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

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.



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

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.



75
76
77
# File 'lib/linux_stat/cpu.rb', line 75

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

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

stat(sleep = 0.075) Where sleep is the delay to gather the data. 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



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/linux_stat/cpu.rb', line 15

def stat(sleep = 0.075)
  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.
  # 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)

    h.merge!(
      x => totald.-(idle_now - idle_then).fdiv(totald).*(100).round(2).abs
    )
  end
end

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

total_usage(sleep = 0.075) Where sleep is the delay to gather the data. 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.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/linux_stat/cpu.rb', line 49

def total_usage(sleep = 0.075)
  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