linux_stat 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +676 -197
- data/exe/linuxstat.rb +116 -8
- data/ext/fs_stat/fs_stat.c +9 -2
- data/ext/nproc/extconf.rb +11 -0
- data/ext/nproc/nproc.c +31 -0
- data/ext/sysconf/sysconf.c +30 -2
- data/ext/utsname/utsname.c +26 -14
- data/lib/linux_stat.rb +7 -1
- data/lib/linux_stat/battery.rb +17 -9
- data/lib/linux_stat/cpu.rb +175 -39
- data/lib/linux_stat/filesystem.rb +12 -12
- data/lib/linux_stat/kernel.rb +1 -1
- data/lib/linux_stat/os.rb +2 -2
- data/lib/linux_stat/prettify_bytes.rb +1 -4
- data/lib/linux_stat/process.rb +1 -1
- data/lib/linux_stat/process_info.rb +151 -24
- data/lib/linux_stat/swap.rb +1 -1
- data/lib/linux_stat/version.rb +1 -1
- metadata +5 -2
data/exe/linuxstat.rb
CHANGED
@@ -7,6 +7,46 @@ rescue LoadError
|
|
7
7
|
abort "The Gem needs to be installed before this test can be run!"
|
8
8
|
end
|
9
9
|
|
10
|
+
# Gradient colour to strings
|
11
|
+
class String
|
12
|
+
def colourize(colour = 1, flip: false)
|
13
|
+
colours, line_length = [], -1
|
14
|
+
temp = ''
|
15
|
+
|
16
|
+
each_line do |c|
|
17
|
+
n, i = c.length, -1
|
18
|
+
|
19
|
+
if line_length != n
|
20
|
+
step, line_length = 255.0./(n), n
|
21
|
+
colours.clear
|
22
|
+
|
23
|
+
while (i += 1) < n
|
24
|
+
l = i.*(step)
|
25
|
+
colours.<<(
|
26
|
+
case colour
|
27
|
+
when 0 then [ l.*(2).to_i.clamp(0, 255), l.to_i.clamp(0, 255), 255.-(l).to_i.clamp(0, 255) ]
|
28
|
+
when 1 then [ 255, 255.-(l).to_i.clamp(0, 255), l.to_i.clamp(0, 255) ]
|
29
|
+
when 2 then [ l.to_i.clamp(0, 255), 255.-(l).to_i.clamp(0, 255), l.to_i.clamp(0, 255) ]
|
30
|
+
when 3 then [ l.*(2).to_i.clamp(0, 255), 255.-(l).to_i.clamp(0, 255), 100.+(l / 2).to_i.clamp(0, 255) ]
|
31
|
+
when 4 then [ 30, 255.-(l / 2).to_i.clamp(0, 255), 110.+(l / 2).to_i.clamp(0, 255) ]
|
32
|
+
when 5 then [ 255.-(l * 2).to_i.clamp(0, 255), l.to_i.clamp(0, 255), 200 ]
|
33
|
+
when 6 then [ 50.+(255 - l).to_i.clamp(0, 255), 255.-(l / 2).to_i.clamp(0, 255), (l * 2).to_i.clamp(0, 255) ]
|
34
|
+
else [ l.*(2).to_i.clamp(0, 255), 255.-(l).to_i.clamp(0, 255), 100.+(l / 2).to_i.clamp(0, 255) ]
|
35
|
+
end
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
colours.reverse! if flip
|
40
|
+
end
|
41
|
+
|
42
|
+
i = -1
|
43
|
+
temp.concat "\e[38;2;#{colours[i][0]};#{colours[i][1]};#{colours[i][2]}m#{c[i]}" while (i += 1) < n
|
44
|
+
end
|
45
|
+
|
46
|
+
temp << "\e[0m".freeze
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
10
50
|
# Check which conflicting argument (e.g., `-md -html` together) is passed last
|
11
51
|
# Always use the last argument
|
12
52
|
conflicting, hash = [
|
@@ -36,17 +76,23 @@ MARKDOWN, HTML = hash[:markdown], hash[:html]
|
|
36
76
|
|
37
77
|
# Print time each method takes unless --no-time or -nt option is passed
|
38
78
|
PRINT_TIME = (MARKDOWN || HTML) ? false : !ARGV.any? { |x| x[/^\-\-no-time$/] || x[/^\-nt$/] }
|
39
|
-
|
40
|
-
%w(--markdown -md --no-time -nt --html -html).each(&ARGV.method(:delete))
|
79
|
+
PRINT_TYPE = ARGV.any? { |x| x[/^\-(\-show\-type|t)$/] }
|
80
|
+
%w(--markdown -md --no-time -nt --html -html --show-type -t).each(&ARGV.method(:delete))
|
41
81
|
|
42
82
|
# Run only desired classes / modules
|
43
83
|
constants = LinuxStat.constants
|
44
84
|
|
85
|
+
# Modules to delete from documentation and testing
|
86
|
+
%i(
|
87
|
+
Nproc
|
88
|
+
).each(&constants.method(:delete))
|
89
|
+
|
45
90
|
execute = constants.map(&:downcase).map.with_index { |x, i|
|
46
91
|
constants[i] if ARGV.find { |y| y.downcase.to_sym == x }
|
47
92
|
}.compact
|
48
93
|
|
49
94
|
execute.replace(constants) if execute.empty?
|
95
|
+
HEXAGONS = %W(\u2b22 \u2b23 \u2B53 \u2B1F)
|
50
96
|
|
51
97
|
execute.sort.each do |c|
|
52
98
|
e = eval("LinuxStat::#{c}")
|
@@ -54,7 +100,6 @@ execute.sort.each do |c|
|
|
54
100
|
next if e.class != Module && e.class != Class
|
55
101
|
|
56
102
|
meths = e.methods(false).sort
|
57
|
-
next if meths.any? { |a| e.method(a).arity > 0 }
|
58
103
|
|
59
104
|
if meths.length > 0
|
60
105
|
if MARKDOWN
|
@@ -67,20 +112,83 @@ execute.sort.each do |c|
|
|
67
112
|
end
|
68
113
|
|
69
114
|
meths.each do |meth|
|
115
|
+
arg = nil
|
116
|
+
params = e.method(meth).parameters
|
117
|
+
|
118
|
+
param = ''
|
119
|
+
|
120
|
+
params.each do |p|
|
121
|
+
case p[0]
|
122
|
+
when :opt
|
123
|
+
param << "#{p[1]}, "
|
124
|
+
when :key
|
125
|
+
param << "#{p[1]}:, "
|
126
|
+
when :req
|
127
|
+
param << "#{p[1] || 'arg'}, "
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
param.delete_suffix!(", ")
|
132
|
+
|
133
|
+
if e.method(meth).arity > 0
|
134
|
+
if c == :PrettifyBytes
|
135
|
+
arg = rand(10 ** 15)
|
136
|
+
elsif c == :FS
|
137
|
+
arg = '/'
|
138
|
+
else
|
139
|
+
next
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
disp_meth = "#{meth}"
|
144
|
+
disp_meth.concat(arg ? "(#{param} = #{arg.inspect})" : "(#{param})")
|
145
|
+
|
70
146
|
time = Time.now
|
71
|
-
|
147
|
+
ret = arg ? e.send(meth, arg) : e.send(meth)
|
72
148
|
time2 = Time.now
|
73
149
|
time = time2.-(time).*(1_000_000).round(3)
|
74
150
|
|
75
|
-
v =
|
151
|
+
v = ret.inspect
|
76
152
|
dis = v.length > 253 ? v[0..250].strip + '...'.freeze : v
|
77
153
|
|
154
|
+
source = e.singleton_method(meth).source_location.to_a
|
155
|
+
src, src_meth, src_ret = '', '', ''
|
156
|
+
|
157
|
+
unless source.empty?
|
158
|
+
src << " File:\t\t#{File.split(source[0])[-1]} | Line: #{source[1]}\n"
|
159
|
+
src_meth << " Definition:\t#{IO.foreach(source[0]).first(source[1])[-1].strip}\n"
|
160
|
+
|
161
|
+
src_ret << " Returns:\t" << case ret
|
162
|
+
when Array then 'Array | Empty Array'
|
163
|
+
when Complex then 'Complex | nil'
|
164
|
+
when Float then 'Float | nil'
|
165
|
+
when Hash then 'Hash | Empty Hash'
|
166
|
+
when Integer then 'Integer | nil'
|
167
|
+
when Rational then 'Rational | nil'
|
168
|
+
when String then "String | (Frozen) Empty String"
|
169
|
+
when Time then 'Time | nil'
|
170
|
+
when true, false then 'True or False | nil'
|
171
|
+
when nil then 'nil'
|
172
|
+
else ''
|
173
|
+
end << ?\n.freeze if PRINT_TYPE
|
174
|
+
|
175
|
+
if MARKDOWN || HTML
|
176
|
+
src.prepend('#'.freeze)
|
177
|
+
src_meth.prepend('#'.freeze)
|
178
|
+
src_ret.prepend(?#.freeze) if PRINT_TYPE
|
179
|
+
else
|
180
|
+
src.prepend(HEXAGONS.rotate![0].freeze)
|
181
|
+
src_meth.prepend(HEXAGONS.rotate![0].freeze)
|
182
|
+
src_ret.prepend(HEXAGONS.rotate![0].freeze) if PRINT_TYPE
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
78
186
|
if MARKDOWN
|
79
|
-
puts "#{e}.#{
|
187
|
+
puts "#{src}#{src_meth}#{src_ret}#{e}.#{disp_meth}\n=> #{dis}"
|
80
188
|
elsif HTML
|
81
|
-
puts "#{e}.#{
|
189
|
+
puts "#{src}#{src_meth}#{src_ret}#{e}.#{disp_meth}\n=> #{dis}"
|
82
190
|
else
|
83
|
-
puts "\e[1;38;2;80;80;255m#{e}.#{
|
191
|
+
puts "\e[1m#{src.colourize}\e[1m#{src_meth.colourize(6)}\e[1m#{src_ret.colourize(1)}\e[0m\e[1;38;2;80;80;255m#{e}.#{disp_meth}\e[0m\n=> #{dis}"
|
84
192
|
end
|
85
193
|
|
86
194
|
puts( "(" +
|
data/ext/fs_stat/fs_stat.c
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
#include <sys/statvfs.h>
|
2
2
|
#include "ruby.h"
|
3
3
|
|
4
|
-
#
|
5
|
-
#pragma
|
4
|
+
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
5
|
+
#pragma GCC optimize ("O3")
|
6
|
+
#pragma GCC diagnostic warning "-Wall"
|
7
|
+
#elif defined(__clang__)
|
8
|
+
#pragma clang optimize on
|
9
|
+
#pragma clang diagnostic warning "-Wall"
|
10
|
+
#elif defined(__INTEL_COMPILER)
|
11
|
+
#pragma intel optimization_level 3
|
12
|
+
#endif
|
6
13
|
|
7
14
|
static VALUE statfs(VALUE obj, VALUE dir) {
|
8
15
|
struct statvfs buf ;
|
data/ext/nproc/nproc.c
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#ifndef _GNU_SOURCE
|
2
|
+
#define _GNU_SOURCE
|
3
|
+
#endif
|
4
|
+
|
5
|
+
#include <sched.h>
|
6
|
+
#include "ruby.h"
|
7
|
+
|
8
|
+
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
9
|
+
#pragma GCC optimize ("O3")
|
10
|
+
#pragma GCC diagnostic warning "-Wall"
|
11
|
+
#elif defined(__clang__)
|
12
|
+
#pragma clang optimize on
|
13
|
+
#pragma clang diagnostic warning "-Wall"
|
14
|
+
#elif defined(__INTEL_COMPILER)
|
15
|
+
#pragma intel optimization_level 3
|
16
|
+
#endif
|
17
|
+
|
18
|
+
static VALUE count_cpu_for_pid(VALUE obj, VALUE pid) {
|
19
|
+
cpu_set_t set ;
|
20
|
+
CPU_ZERO(&set) ;
|
21
|
+
short int stat = sched_getaffinity(FIX2INT(pid), sizeof(set), &set) ;
|
22
|
+
|
23
|
+
if (stat < 0) return Qnil ;
|
24
|
+
return INT2FIX(CPU_COUNT(&set)) ;
|
25
|
+
}
|
26
|
+
|
27
|
+
void Init_nproc() {
|
28
|
+
VALUE _linux_stat = rb_define_module("LinuxStat") ;
|
29
|
+
VALUE _nproc = rb_define_module_under(_linux_stat, "Nproc") ;
|
30
|
+
rb_define_module_function(_nproc, "count_cpu_for_pid", count_cpu_for_pid, 1) ;
|
31
|
+
}
|
data/ext/sysconf/sysconf.c
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
#include <unistd.h>
|
2
2
|
#include "ruby.h"
|
3
3
|
|
4
|
-
#
|
5
|
-
#pragma
|
4
|
+
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
5
|
+
#pragma GCC optimize ("O3")
|
6
|
+
#pragma GCC diagnostic warning "-Wall"
|
7
|
+
#elif defined(__clang__)
|
8
|
+
#pragma clang optimize on
|
9
|
+
#pragma clang diagnostic warning "-Wall"
|
10
|
+
#elif defined(__INTEL_COMPILER)
|
11
|
+
#pragma intel optimization_level 3
|
12
|
+
#endif
|
6
13
|
|
7
14
|
static VALUE getTick(VALUE obj) {
|
8
15
|
return INT2FIX(sysconf(_SC_CLK_TCK)) ;
|
@@ -40,6 +47,22 @@ static VALUE getPosixVersion(VALUE obj) {
|
|
40
47
|
return INT2FIX(sysconf(_SC_VERSION)) ;
|
41
48
|
}
|
42
49
|
|
50
|
+
static VALUE getLineMax(VALUE obj) {
|
51
|
+
return INT2FIX(sysconf(_SC_LINE_MAX)) ;
|
52
|
+
}
|
53
|
+
|
54
|
+
static VALUE getExprNestMax(VALUE obj) {
|
55
|
+
return INT2FIX(sysconf(_SC_EXPR_NEST_MAX)) ;
|
56
|
+
}
|
57
|
+
|
58
|
+
static VALUE getProcessorConfigured(VALUE obj) {
|
59
|
+
return INT2FIX(sysconf(_SC_NPROCESSORS_CONF)) ;
|
60
|
+
}
|
61
|
+
|
62
|
+
static VALUE getProcessorOnline(VALUE obj) {
|
63
|
+
return INT2FIX(sysconf(_SC_NPROCESSORS_ONLN)) ;
|
64
|
+
}
|
65
|
+
|
43
66
|
static VALUE getUser(VALUE obj) {
|
44
67
|
char *name = getlogin() ;
|
45
68
|
return name ? rb_str_new_cstr(name) : rb_str_new_cstr("") ;
|
@@ -70,6 +93,11 @@ void Init_sysconf() {
|
|
70
93
|
rb_define_module_function(_sysconf, "stream_max", getStreamMax, 0) ;
|
71
94
|
rb_define_module_function(_sysconf, "tty_name_max", getTTYNameMax, 0) ;
|
72
95
|
rb_define_module_function(_sysconf, "posix_version", getPosixVersion, 0) ;
|
96
|
+
rb_define_module_function(_sysconf, "line_max", getLineMax, 0) ;
|
97
|
+
rb_define_module_function(_sysconf, "expr_nest_max", getExprNestMax, 0) ;
|
98
|
+
|
99
|
+
rb_define_module_function(_sysconf, "processor_online", getProcessorOnline, 0) ;
|
100
|
+
rb_define_module_function(_sysconf, "processor_configured", getProcessorConfigured, 0) ;
|
73
101
|
|
74
102
|
rb_define_module_function(_sysconf, "get_uid", getUID, 0) ;
|
75
103
|
rb_define_module_function(_sysconf, "get_gid", getGID, 0) ;
|
data/ext/utsname/utsname.c
CHANGED
@@ -1,39 +1,51 @@
|
|
1
1
|
#include <sys/utsname.h>
|
2
2
|
#include "ruby.h"
|
3
3
|
|
4
|
-
#
|
5
|
-
#pragma
|
4
|
+
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
|
5
|
+
#pragma GCC optimize ("O3")
|
6
|
+
#pragma GCC diagnostic warning "-Wall"
|
7
|
+
#elif defined(__clang__)
|
8
|
+
#pragma clang optimize on
|
9
|
+
#pragma clang diagnostic warning "-Wall"
|
10
|
+
#elif defined(__INTEL_COMPILER)
|
11
|
+
#pragma intel optimization_level 3
|
12
|
+
#endif
|
6
13
|
|
7
14
|
static struct utsname buf ;
|
8
|
-
|
15
|
+
|
16
|
+
static char *sysname = "", *nodename = "" ;
|
17
|
+
static char *release = "", *version = "", *machine = "" ;
|
9
18
|
|
10
19
|
void init_buf() {
|
11
|
-
status = uname(&buf) ;
|
20
|
+
short status = uname(&buf) ;
|
21
|
+
|
22
|
+
if (status > -1) {
|
23
|
+
sysname = buf.sysname ;
|
24
|
+
nodename = buf.nodename ;
|
25
|
+
release = buf.release ;
|
26
|
+
version = buf.version ;
|
27
|
+
machine = buf.machine ;
|
28
|
+
}
|
12
29
|
}
|
13
30
|
|
14
31
|
static VALUE getSysname(VALUE obj) {
|
15
|
-
|
16
|
-
return sysname ;
|
32
|
+
return rb_str_new_cstr(sysname) ;
|
17
33
|
}
|
18
34
|
|
19
35
|
static VALUE getNodename(VALUE obj) {
|
20
|
-
|
21
|
-
return nodename ;
|
36
|
+
return rb_str_new_cstr(nodename) ;
|
22
37
|
}
|
23
38
|
|
24
39
|
static VALUE getRelease(VALUE obj) {
|
25
|
-
|
26
|
-
return release ;
|
40
|
+
return rb_str_new_cstr(release) ;
|
27
41
|
}
|
28
42
|
|
29
43
|
static VALUE getVersion(VALUE obj) {
|
30
|
-
|
31
|
-
return version ;
|
44
|
+
return rb_str_new_cstr(version) ;
|
32
45
|
}
|
33
46
|
|
34
47
|
static VALUE getMachine(VALUE obj) {
|
35
|
-
|
36
|
-
return machine ;
|
48
|
+
return rb_str_new_cstr(machine) ;
|
37
49
|
}
|
38
50
|
|
39
51
|
void Init_utsname() {
|
data/lib/linux_stat.rb
CHANGED
@@ -23,7 +23,6 @@ require 'linux_stat/prettify_bytes'
|
|
23
23
|
# But might be required by other module functions in "Dependent Modules" section
|
24
24
|
require "linux_stat/battery"
|
25
25
|
require "linux_stat/bios"
|
26
|
-
require "linux_stat/cpu"
|
27
26
|
require "linux_stat/memory"
|
28
27
|
require "linux_stat/net"
|
29
28
|
require "linux_stat/process"
|
@@ -32,6 +31,10 @@ require "linux_stat/swap"
|
|
32
31
|
# Dependent Modules
|
33
32
|
# Modules that can have reverse dependency
|
34
33
|
|
34
|
+
# LinuxStat::CPU.nproc dependent modules
|
35
|
+
require "linux_stat/cpu"
|
36
|
+
require "linux_stat/nproc"
|
37
|
+
|
35
38
|
# LinuxStat::Uname dependent modules
|
36
39
|
require 'linux_stat/utsname'
|
37
40
|
require "linux_stat/os"
|
@@ -46,3 +49,6 @@ require "linux_stat/sysconf"
|
|
46
49
|
require "linux_stat/kernel"
|
47
50
|
require 'linux_stat/user'
|
48
51
|
require "linux_stat/process_info"
|
52
|
+
|
53
|
+
# A short alias to LinuxStat
|
54
|
+
LS = LinuxStat
|
data/lib/linux_stat/battery.rb
CHANGED
@@ -98,12 +98,25 @@ module LinuxStat
|
|
98
98
|
#
|
99
99
|
# If the battery is not present or the information is not available, it will return nil.
|
100
100
|
def charge
|
101
|
-
|
102
|
-
|
103
|
-
|
101
|
+
@@charge_now_file ||= File.join(PATH, 'charge_now')
|
102
|
+
@@charge_full_file ||= File.join(PATH, 'charge_full')
|
103
|
+
|
104
|
+
@@charge_now_readable ||= File.readable?(@@charge_now_file) && File.readable?(@@charge_full_file)
|
105
|
+
return nil unless @@charge_now_readable
|
106
|
+
|
107
|
+
charge_now = IO.read(@@charge_now_file).to_i
|
108
|
+
charge_full = IO.read(@@charge_full_file).to_i
|
104
109
|
|
105
110
|
percentage = charge_now.*(100).fdiv(charge_full)
|
106
|
-
percentage
|
111
|
+
percentage > 100 ? 100.0 : percentage < 0 ? 0.0 : percentage
|
112
|
+
end
|
113
|
+
|
114
|
+
def voltage_now
|
115
|
+
@@voltage_file ||= File.join(PATH, 'voltage_now'.freeze)
|
116
|
+
@@voltage_readable ||= File.readable?(@@voltage_file)
|
117
|
+
return nil unless @@voltage_readable
|
118
|
+
|
119
|
+
IO.read(@@voltage_file, 16).to_f.fdiv(1000000)
|
107
120
|
end
|
108
121
|
|
109
122
|
private
|
@@ -122,11 +135,6 @@ module LinuxStat
|
|
122
135
|
def status_readable?
|
123
136
|
@@status_readable ||= File.readable?(File.join(PATH, 'status'))
|
124
137
|
end
|
125
|
-
|
126
|
-
def charge_now_readable?
|
127
|
-
@@charge_now_readable ||= File.readable?(File.join(PATH, 'charge_now')) &&
|
128
|
-
File.readable?(File.join(PATH, 'charge_full'))
|
129
|
-
end
|
130
138
|
end
|
131
139
|
end
|
132
140
|
end
|
data/lib/linux_stat/cpu.rb
CHANGED
@@ -2,7 +2,7 @@ module LinuxStat
|
|
2
2
|
module CPU
|
3
3
|
class << self
|
4
4
|
##
|
5
|
-
# = stat(sleep = 1.0 / LinuxStat::Sysconf.sc_clk_tck)
|
5
|
+
# = stat(sleep = 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5)
|
6
6
|
#
|
7
7
|
# Where sleep is the delay to gather the data.
|
8
8
|
#
|
@@ -14,18 +14,20 @@ module LinuxStat
|
|
14
14
|
#
|
15
15
|
# And the consecutive ones are the real core usages.
|
16
16
|
#
|
17
|
-
#
|
18
|
-
#
|
17
|
+
# For example, on a system with 4 threads:
|
18
|
+
# LinuxStat::CPU.stat
|
19
|
+
#
|
20
|
+
# => {0=>84.38, 1=>100.0, 2=>50.0, 3=>87.5, 4=>87.5}
|
19
21
|
#
|
20
22
|
# If the information is not available, it will return an empty Hash
|
21
|
-
def stat(sleep =
|
23
|
+
def stat(sleep = ticks_to_ms_t5)
|
22
24
|
return {} unless stat?
|
23
25
|
|
24
|
-
data = IO.readlines('/proc/stat').select
|
26
|
+
data = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
|
25
27
|
sleep(sleep)
|
26
|
-
data2 = IO.readlines('/proc/stat').select
|
28
|
+
data2 = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
|
27
29
|
|
28
|
-
# On devices like android, the core count can change anytime.
|
30
|
+
# On devices like android, the core count can change anytime (hotplugging).
|
29
31
|
# I had crashes on Termux.
|
30
32
|
# So better just count the min number of CPU and iterate over that
|
31
33
|
# If data.length is smaller than data2.length, we don't have enough data to compare.
|
@@ -39,12 +41,10 @@ module LinuxStat
|
|
39
41
|
idle_then, idle_now = idle + iowait, idle2 + iowait2
|
40
42
|
totald = idle_now.+(user2 + nice2 + sys2 + irq2 + softirq2 + steal2) - idle_then.+(user + nice + sys + irq + softirq + steal)
|
41
43
|
|
42
|
-
res = totald.-(idle_now - idle_then).fdiv(totald).*(100)
|
43
|
-
res = 0.0
|
44
|
+
res = totald.-(idle_now - idle_then).fdiv(totald).abs.*(100)
|
45
|
+
res = res.nan? ? 0.0 : res > 100 ? 100.0 : res.round(2)
|
44
46
|
|
45
|
-
h.merge!(
|
46
|
-
x => res
|
47
|
-
)
|
47
|
+
h.merge!( x => res )
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -60,7 +60,7 @@ module LinuxStat
|
|
60
60
|
# It's like running LinuxStat::CPU.stat[0] but it's much more efficient and calculates just the aggregated usage which is available at the top of the /proc/stat file.
|
61
61
|
#
|
62
62
|
# If the information is not available, it will return nil.
|
63
|
-
def total_usage(sleep =
|
63
|
+
def total_usage(sleep = ticks_to_ms_t5)
|
64
64
|
return nil unless stat?
|
65
65
|
|
66
66
|
data = IO.foreach('/proc/stat').first.split.tap(&:shift).map!(&:to_f)
|
@@ -72,16 +72,63 @@ module LinuxStat
|
|
72
72
|
|
73
73
|
idle_then, idle_now = idle + iowait, idle2 + iowait2
|
74
74
|
totald = idle_now.+(user2 + nice2 + sys2 + irq2 + softirq2 + steal2) - idle_then.+(user + nice + sys + irq + softirq + steal)
|
75
|
-
|
75
|
+
|
76
|
+
u = totald.-(idle_now - idle_then).fdiv(totald).abs.*(100)
|
77
|
+
u > 100 ? 100.0 : u.round(2)
|
76
78
|
end
|
77
79
|
|
78
80
|
##
|
79
|
-
# Returns the total number of CPU
|
81
|
+
# Returns the total number of CPU available for the sysetm.
|
80
82
|
#
|
81
|
-
#
|
83
|
+
# It returns an Integer.
|
84
|
+
#
|
85
|
+
# If the information isn't available, it will return an empty Array.
|
82
86
|
def count
|
83
|
-
|
84
|
-
|
87
|
+
@@cpu_count ||= LinuxStat::Sysconf.processor_configured
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Returns the total number of CPU online in the sysetm.
|
92
|
+
#
|
93
|
+
# It opens /sys/devices/system/cpu/offline and
|
94
|
+
# performs various job to get one Ruby array.
|
95
|
+
#
|
96
|
+
# If the information isn't available, it will return an empty Array.
|
97
|
+
def online
|
98
|
+
@@online_file ||= '/sys/devices/system/cpu/online'.freeze
|
99
|
+
@@online_readable ||= File.readable?(@@online_file)
|
100
|
+
return [] unless @@online_readable
|
101
|
+
|
102
|
+
ret = []
|
103
|
+
IO.read(@@online_file).split(?,.freeze).each { |x|
|
104
|
+
x.strip!
|
105
|
+
c = x.split(?-.freeze).map(&:to_i)
|
106
|
+
ret.concat(c.length == 2 ? Range.new(*c).to_a : c)
|
107
|
+
}
|
108
|
+
|
109
|
+
ret
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Returns the total number of CPU offline in the sysetm.
|
114
|
+
#
|
115
|
+
# It opens /sys/devices/system/cpu/offline and
|
116
|
+
# performs various job to get one Ruby array.
|
117
|
+
#
|
118
|
+
# If the information isn't available, it will return an empty Array.
|
119
|
+
def offline
|
120
|
+
@@offline_file ||= '/sys/devices/system/cpu/offline'.freeze
|
121
|
+
@@offline_readable ||= File.readable?(@@offline_file)
|
122
|
+
return [] unless @@offline_readable
|
123
|
+
|
124
|
+
ret = []
|
125
|
+
IO.read(@@offline_file).split(?,.freeze).each { |x|
|
126
|
+
x.strip!
|
127
|
+
c = x.split(?-.freeze).map(&:to_i)
|
128
|
+
ret.concat(c.length == 2 ? Range.new(*c).to_a : c)
|
129
|
+
}
|
130
|
+
|
131
|
+
ret
|
85
132
|
end
|
86
133
|
|
87
134
|
##
|
@@ -95,33 +142,115 @@ module LinuxStat
|
|
95
142
|
end
|
96
143
|
|
97
144
|
##
|
98
|
-
# Returns
|
145
|
+
# Returns a Hash with current core frequencies corresponding to the CPUs.
|
99
146
|
#
|
100
|
-
#
|
147
|
+
# For example:
|
148
|
+
# LinuxStat::CPU.cur_freq
|
149
|
+
#
|
150
|
+
# => {"cpu0"=>1999990, "cpu1"=>2000042, "cpu2"=>2000016, "cpu3"=>2000088}
|
151
|
+
#
|
152
|
+
# If the information isn't available, it will return an empty Hash.
|
101
153
|
def cur_freq
|
102
|
-
@@
|
103
|
-
|
154
|
+
@@cur_f ||= cpus.map { |x|
|
155
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_cur_freq'.freeze)]
|
156
|
+
}
|
104
157
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
158
|
+
h = {}
|
159
|
+
@@cur_f.each { |id, file|
|
160
|
+
h.merge!(id => IO.read(file).to_i) if File.readable?(file)
|
161
|
+
}
|
162
|
+
|
163
|
+
h
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Returns a Hash with max core frequencies corresponding to the CPUs.
|
168
|
+
#
|
169
|
+
# For example:
|
170
|
+
# LinuxStat::CPU.min_freq
|
171
|
+
#
|
172
|
+
# => {"cpu0"=>2000000, "cpu1"=>2000000, "cpu2"=>2000000, "cpu3"=>2000000}
|
173
|
+
#
|
174
|
+
# If the information isn't available, it will return an empty Hash.
|
175
|
+
def min_freq
|
176
|
+
@@min_f ||= cpus.map { |x|
|
177
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_min_freq'.freeze)]
|
178
|
+
}
|
179
|
+
|
180
|
+
h = {}
|
181
|
+
@@min_f.each { |id, file|
|
182
|
+
h.merge!(id => IO.read(file).to_i) if File.readable?(file)
|
183
|
+
}
|
184
|
+
|
185
|
+
h
|
110
186
|
end
|
111
187
|
|
112
188
|
##
|
113
|
-
# Returns
|
189
|
+
# Returns a Hash with max core frequencies corresponding to the CPUs.
|
190
|
+
#
|
191
|
+
# For example:
|
192
|
+
# LinuxStat::CPU.max_freq
|
114
193
|
#
|
115
|
-
#
|
194
|
+
# => {"cpu0"=>2000000, "cpu1"=>2000000, "cpu2"=>2000000, "cpu3"=>2000000}
|
195
|
+
#
|
196
|
+
# If the information isn't available, it will return an empty Hash.
|
116
197
|
def max_freq
|
117
|
-
@@
|
118
|
-
|
198
|
+
@@min_f ||= cpus.map { |x|
|
199
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_max_freq'.freeze)]
|
200
|
+
}
|
119
201
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
202
|
+
h = {}
|
203
|
+
@@min_f.each { |id, file|
|
204
|
+
h.merge!(id => IO.read(file).to_i) if File.readable?(file)
|
205
|
+
}
|
206
|
+
|
207
|
+
h
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# Returns the corresponding governor of each CPU.
|
212
|
+
#
|
213
|
+
# The return type is a Hash.
|
214
|
+
#
|
215
|
+
# For example:
|
216
|
+
# LinuxStat::CPU.governor
|
217
|
+
#
|
218
|
+
# => {"cpu0"=>"powersave", "cpu1"=>"powersave", "cpu2"=>"performance", "cpu3"=>"performance"}
|
219
|
+
#
|
220
|
+
# If the information isn't available, it will return an empty Hash.
|
221
|
+
def governor
|
222
|
+
@@scaling_g ||= cpus.map { |x|
|
223
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_governor'.freeze)]
|
224
|
+
}
|
225
|
+
|
226
|
+
h = {}
|
227
|
+
@@scaling_g.each { |id, file|
|
228
|
+
h.merge!(id => IO.read(file).tap(&:strip!)) if File.readable?(file)
|
229
|
+
}
|
230
|
+
|
231
|
+
h
|
232
|
+
end
|
233
|
+
|
234
|
+
##
|
235
|
+
# Returns an array of governors for each CPU as a Hash.
|
236
|
+
#
|
237
|
+
# For example:
|
238
|
+
# LinuxStat::CPU.available_governors
|
239
|
+
#
|
240
|
+
# => {"cpu0"=>["performance", "powersave"], "cpu1"=>["performance", "powersave"], "cpu2"=>["performance", "powersave"], "cpu3"=>["performance", "powersave"]}
|
241
|
+
#
|
242
|
+
# If the information isn't available, it will return an empty Hash.
|
243
|
+
def available_governors
|
244
|
+
@@scaling_av_g ||= cpus.map { |x|
|
245
|
+
[File.split(x)[-1], File.join(x, 'cpufreq/scaling_available_governors'.freeze)]
|
246
|
+
}
|
247
|
+
|
248
|
+
h = {}
|
249
|
+
@@scaling_av_g.each { |id, file|
|
250
|
+
h.merge!(id => IO.read(file).split.each(&:strip!)) if File.readable?(file)
|
251
|
+
}
|
252
|
+
|
253
|
+
h
|
125
254
|
end
|
126
255
|
|
127
256
|
alias usages stat
|
@@ -129,15 +258,22 @@ module LinuxStat
|
|
129
258
|
|
130
259
|
private
|
131
260
|
def cpuinfo
|
132
|
-
File.readable?('/proc/cpuinfo') ? IO.readlines('/proc/cpuinfo') : []
|
261
|
+
File.readable?('/proc/cpuinfo') ? IO.readlines('/proc/cpuinfo').freeze : [].freeze
|
133
262
|
end
|
134
263
|
|
135
264
|
def stat?
|
136
265
|
@@stat_readable ||= File.readable?('/proc/stat')
|
137
266
|
end
|
138
267
|
|
139
|
-
|
140
|
-
|
268
|
+
# Just to avoid duplicate calculations
|
269
|
+
# ticks to ms times 5
|
270
|
+
# If the ticks is 100, it will return 0.05
|
271
|
+
def ticks_to_ms_t5
|
272
|
+
@@ms_t5 ||= 1.0 / LinuxStat::Sysconf.sc_clk_tck * 5
|
273
|
+
end
|
274
|
+
|
275
|
+
def cpus
|
276
|
+
@@all_cpu = Dir["/sys/devices/system/cpu/cpu[0-9]*/"].sort!.freeze
|
141
277
|
end
|
142
278
|
end
|
143
279
|
end
|