linux_stat 2.2.1 → 2.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a2257dd9d025a05cf31fbfdf06d67933abd1d355678fe23c0ab1d5797fce9e9
4
- data.tar.gz: 3898fa563cda7716321f689a64448afb0b46bb7ba1c9bac297c9f3ba0e9e4f38
3
+ metadata.gz: 56eb9d01b537db6e6dab3a6ee86a391a1076f63cc612ff961e33f7ab8c703129
4
+ data.tar.gz: 30a3f6df0c51dfb14c28fcbdd7d2298d4f13fa48e15ef9ef63ab13e0fd980e68
5
5
  SHA512:
6
- metadata.gz: 5b6fede8da5d7a14322253c8c108b56069f0d3089349f23a9b7c207500c240b8a855a847dc9de649797da81466e449911609f3308473a4d8f5c32c1d0622cf46
7
- data.tar.gz: 0f61a61920ca364cba0b3e664ff67bab7fcbf45d3d47eaea622b71b2fde7585cb761025f1b02d8f7e80ea0105b66541432cdb7ca12594938a6d5f04c0d648b05
6
+ metadata.gz: 1f24a5a7fb1d8f32a2c35c7cbc5a7b9bb380efb33a2df23e269ea4ebac565f866b6a399a0361a3f4f325bad13be1b545d59726efccabb4d8d6f8045ed03c3fc6
7
+ data.tar.gz: 81c1c316b49aaab37f4e300eb597db3a3bcb538549fc6192d9661e7ca5022bd5b6942a257ced51760e2065d7aca82ae465f55e79202ba7a5f8c9e917f53f505c
data/README.md CHANGED
@@ -38,18 +38,36 @@ It only works on Linux, and detecting the OS is upto the user of this gem.
38
38
  2. Ruby: Ruby 2.3.0 and above.
39
39
 
40
40
  ## Build Dependencies:
41
- + You need to have the C compiler installed to be able to compile the C extensions.
42
- On Arch Linux:
41
+ #### You need to have the C compiler installed to be able to compile the C extensions.
42
+
43
+ + On Arch Linux / Manjaro / Archlabs / Other Arch Based Distributions
44
+ ```
45
+ # pacman -S gcc make ruby
46
+ ```
47
+
48
+ + On Debian / Ubuntu / Linux Mint / Pop!_OS / Raspberry Pi OS / Other Debian Based Distributions
49
+ ```
50
+ # apt install gcc build-essential ruby ruby-dev build-essential
51
+ ```
52
+
53
+ + Gentoo / Gentoo Based Distributions
54
+ ```
55
+ # emerge --ask dev-lang/ruby
56
+ ```
57
+
58
+ + Fedora / AmazonLinux* / CentOS* / Other RedHat Based Distributions
43
59
  ```
44
- # pacman -S gcc make
60
+ # yum install gcc ruby-devel ruby make
45
61
  ```
46
62
 
47
- On Debian based systems:
63
+ You can run linux_stat on *AmazonLinux and *CentOS if you have Ruby 2.3.0+.
64
+
65
+ + OpenSUSE
48
66
  ```
49
- # apt install gcc build-essential ruby-dev
67
+ # zypper install gcc ruby ruby-devel make
50
68
  ```
51
69
 
52
- + You can remove the packages once the program is installed.
70
+ + You can remove the above packages once the gem is installed.
53
71
 
54
72
  ---
55
73
 
@@ -62,13 +80,28 @@ You can install hwdata simply.
62
80
  + Arch:
63
81
 
64
82
  ```
65
- sudo pacman -S hwids
83
+ # pacman -S hwids
66
84
  ```
67
85
 
68
86
  + Debian based systems:
69
87
 
70
88
  ```
71
- sudo apt install hwdata
89
+ # apt install hwdata
90
+ ```
91
+
92
+ + Gentoo / Gentoo Based Distributions
93
+ ```
94
+ # emerge --ask sys-apps/hwids
95
+ ```
96
+
97
+ + Fedora / Amazon Linux / CentOS
98
+ ```
99
+ # yum install hwdata
100
+ ```
101
+
102
+ + OpenSUSE
103
+ ```
104
+ zypper install hwdata
72
105
  ```
73
106
 
74
107
  But without hwdata, it won't show such information.
data/exe/linuxstat.rb CHANGED
@@ -7,6 +7,12 @@ rescue LoadError
7
7
  abort "The Gem needs to be installed before this test can be run!"
8
8
  end
9
9
 
10
+ # Time reporting format
11
+ T_FMT = '%d'.freeze
12
+
13
+ # Check the number of iterations
14
+ iterations = (ARGV.find { |x| x.to_i.to_s == x } || 1).to_i
15
+
10
16
  Integer.class_exec do
11
17
  define_method(:clamp) { |min, max|
12
18
  self < min ? min : self > max ? max : self
@@ -100,122 +106,166 @@ execute = constants.map(&:downcase).map.with_index { |x, i|
100
106
  execute.replace(constants) if execute.empty?
101
107
  HEXAGONS = %W(\u2b22 \u2b23 \u2B53 \u2B1F)
102
108
 
103
- execute.sort.each do |c|
104
- e = eval("LinuxStat::#{c}")
109
+ puts " #{HEXAGONS.rotate![0]} LinuxStat: #{LinuxStat::VERSION}"
110
+ puts " #{HEXAGONS.rotate![0]} Test Modules: #{execute.size}"
111
+ puts " #{HEXAGONS.rotate![0]} Iterations: #{iterations}"
105
112
 
106
- next if e.class != Module && e.class != Class
113
+ puts " #{HEXAGONS.rotate![0]} Format: Markdown" if MARKDOWN
114
+ puts " #{HEXAGONS.rotate![0]} Format: HTML" if HTML
107
115
 
108
- meths = e.methods(false).sort
116
+ sleep 2
117
+ puts
109
118
 
110
- if meths.length > 0
111
- if MARKDOWN
112
- puts "### LinuxStat::#{c}\n```"
113
- elsif HTML
114
- puts "<h3>LinuxStat::#{c}</h3>\n<pre>"
115
- else
116
- puts "\e[1;4;38;2;255;240;0mLinuxStat::#{c}\e[0m"
117
- end
119
+ def get_colour(n)
120
+ if n > 10_000
121
+ "\e[1;38;2;255;50;50m"
122
+ elsif n > 5_000
123
+ "\e[1;38;2;255;170;0m"
124
+ else
125
+ "\e[1;38;2;0;170;0m"
118
126
  end
127
+ end
128
+
129
+ total_real_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
130
+ total_cpu_time = Process.times
131
+
132
+ iterations.times do
133
+ execute.sort.each do |c|
134
+ e = eval("LinuxStat::#{c}")
135
+
136
+ next if e.class != Module && e.class != Class
119
137
 
120
- meths.each do |meth|
121
- arg = nil
138
+ meths = e.methods(false).sort
122
139
 
123
- arity = e.method(meth).arity
124
- if arity > 0 || arity == -2
125
- if c == :PrettifyBytes
126
- arg = rand(10 ** 15)
127
- elsif c == :FS
128
- arg = '/'
140
+ if meths.length > 0
141
+ if MARKDOWN
142
+ puts "### LinuxStat::#{c}\n```"
143
+ elsif HTML
144
+ puts "<h3>LinuxStat::#{c}</h3>\n<pre>"
129
145
  else
130
- next
146
+ puts "\e[1;4;38;2;255;240;0mLinuxStat::#{c}\e[0m"
131
147
  end
132
148
  end
133
149
 
134
- params = e.method(meth).parameters
135
- param = ''
136
- params.each do |p|
137
- case p[0]
138
- when :opt
139
- param << "#{p[1]}, "
140
- when :key
141
- param << "#{p[1]}:, "
142
- when :req
143
- _arg = arg ? " = #{arg.inspect}" : ''.freeze
144
- param << "#{p[1] || 'arg'}#{_arg}, "
150
+ meths.each do |meth|
151
+ arg = nil
152
+
153
+ arity = e.method(meth).arity
154
+ if arity > 0 || arity == -2
155
+ if c == :PrettifyBytes
156
+ arg = rand(10 ** 15)
157
+ elsif c == :FS
158
+ arg = '/'
159
+ else
160
+ next
161
+ end
145
162
  end
146
- end
147
163
 
148
- param.chomp!(", ")
149
-
150
- disp_meth = "#{meth}"
151
- disp_meth.concat(arg ? "(#{param})" : "(#{param})")
152
-
153
- time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
154
- ret = arg ? e.send(meth, arg) : e.send(meth)
155
- time2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
156
- time = time2.-(time).*(1_000_000).round(3)
157
-
158
- v = ret.inspect
159
- dis = v.length > 253 ? v[0..250].strip + '...'.freeze : v
160
-
161
- source = e.singleton_method(meth).source_location.to_a
162
- src, src_meth, src_ret = '', '', ''
163
-
164
- unless source.empty?
165
- src << " File:\t\t#{File.split(source[0])[-1]} | Line: #{source[1]}\n"
166
- src_meth << " Definition:\t#{IO.foreach(source[0]).first(source[1])[-1].strip}\n"
167
-
168
- src_ret << " Returns:\t" << case ret
169
- when Array then 'Array | Empty Array'
170
- when Complex then 'Complex | nil'
171
- when Float then 'Float | nil'
172
- when Hash then 'Hash | Empty Hash'
173
- when Integer then 'Integer | nil'
174
- when Rational then 'Rational | nil'
175
- when String then "String | (Frozen) Empty String"
176
- when Time then 'Time | nil'
177
- when true, false then 'True or False | nil'
178
- when nil then 'nil'
179
- else ''
180
- end << ?\n.freeze if PRINT_TYPE
181
-
182
- if MARKDOWN || HTML
183
- src.prepend('#'.freeze)
184
- src_meth.prepend('#'.freeze)
185
- src_ret.prepend(?#.freeze) if PRINT_TYPE
186
- else
187
- src.prepend(HEXAGONS.rotate![0].freeze)
188
- src_meth.prepend(HEXAGONS.rotate![0].freeze)
189
- src_ret.prepend(HEXAGONS.rotate![0].freeze) if PRINT_TYPE
164
+ params = e.method(meth).parameters
165
+ param = ''
166
+ params.each do |p|
167
+ case p[0]
168
+ when :opt
169
+ param << "#{p[1]}, "
170
+ when :key
171
+ param << "#{p[1]}:, "
172
+ when :req
173
+ _arg = arg ? " = #{arg.inspect}" : ''.freeze
174
+ param << "#{p[1] || 'arg'}#{_arg}, "
175
+ end
190
176
  end
191
- end
192
177
 
193
- if MARKDOWN
194
- puts "#{src}#{src_meth}#{src_ret}#{e}.#{disp_meth}\n=> #{dis}"
195
- elsif HTML
196
- puts "#{src}#{src_meth}#{src_ret}#{e}.#{disp_meth}\n=> #{dis}"
197
- else
198
- 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}"
199
- end
178
+ param.chomp!(", ")
179
+
180
+ disp_meth = "#{meth}"
181
+ disp_meth.concat(arg ? "(#{param})" : "(#{param})")
182
+
183
+ time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
184
+ cputime = Process.times
185
+
186
+ ret = arg ? e.send(meth, arg) : e.send(meth)
187
+
188
+ time2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
189
+ cputime2 = Process.times
190
+
191
+ time = time2.-(time).*(1_000_000)
192
+ cputime = cputime2.stime.+(cputime2.utime).-(cputime.stime + cputime.utime).*(1_000_000)
193
+
194
+ v = ret.inspect
195
+ dis = v.length > 253 ? v[0..250].strip + '...'.freeze : v
196
+
197
+ source = e.singleton_method(meth).source_location.to_a
198
+ src, src_meth, src_ret = '', '', ''
199
+
200
+ unless source.empty?
201
+ src << " File:\t\t#{File.split(source[0])[-1]} | Line: #{source[1]}\n"
202
+ src_meth << " Definition:\t#{IO.foreach(source[0]).first(source[1])[-1].strip}\n"
203
+
204
+ src_ret << " Returns:\t" << case ret
205
+ when Array then 'Array | Empty Array'
206
+ when Complex then 'Complex | nil'
207
+ when Float then 'Float | nil'
208
+ when Hash then 'Hash | Empty Hash'
209
+ when Integer then 'Integer | nil'
210
+ when Rational then 'Rational | nil'
211
+ when String then "String | (Frozen) Empty String"
212
+ when Time then 'Time | nil'
213
+ when true, false then 'True or False | nil'
214
+ when nil then 'nil'
215
+ else ''
216
+ end << ?\n.freeze if PRINT_TYPE
217
+
218
+ if MARKDOWN || HTML
219
+ src.prepend('#'.freeze)
220
+ src_meth.prepend('#'.freeze)
221
+ src_ret.prepend(?#.freeze) if PRINT_TYPE
222
+ else
223
+ src.prepend(HEXAGONS.rotate![0].freeze)
224
+ src_meth.prepend(HEXAGONS.rotate![0].freeze)
225
+ src_ret.prepend(HEXAGONS.rotate![0].freeze) if PRINT_TYPE
226
+ end
227
+ end
200
228
 
201
- puts( "(" +
202
- if time > 10_000
203
- "\e[1;38;2;255;50;50m"
204
- elsif time > 5_000
205
- "\e[1;38;2;255;170;0m"
229
+ if MARKDOWN
230
+ puts "#{src}#{src_meth}#{src_ret}#{e}.#{disp_meth}\n=> #{dis}"
231
+ elsif HTML
232
+ puts "#{src}#{src_meth}#{src_ret}#{e}.#{disp_meth}\n=> #{dis}"
206
233
  else
207
- "\e[1;38;2;0;170;0m"
208
- end + "Time taken: #{time}\u03BCs\e[0m)"
209
- ) if PRINT_TIME
234
+ 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}"
235
+ end
210
236
 
211
- puts
212
- end
237
+ if PRINT_TIME
238
+ time_colour = get_colour(time)
239
+ cputime_colour = get_colour(cputime)
240
+
241
+ puts "[Real Time: #{time_colour}#{T_FMT % time}\u03BCs\e[0m, "\
242
+ "CPU Time: #{cputime_colour}#{T_FMT % cputime}\u03BCs\e[0m]"
243
+ end
244
+
245
+ puts
246
+ end
213
247
 
214
- if meths.length > 0
215
- if MARKDOWN
216
- puts "```\n\n"
217
- elsif HTML
218
- puts "</pre>"
248
+ if meths.length > 0
249
+ if MARKDOWN
250
+ puts "```\n\n"
251
+ elsif HTML
252
+ puts "</pre>"
253
+ end
219
254
  end
220
255
  end
221
256
  end
257
+
258
+ if PRINT_TIME
259
+ total_real_time2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
260
+ total_cpu_time2 = Process.times
261
+
262
+ total_real_t = total_real_time2.-(total_real_time).*(1_000_000)
263
+
264
+ total_cpu_t = total_cpu_time2.stime.+(total_cpu_time2.utime).-(
265
+ total_cpu_time.stime + total_cpu_time.utime
266
+ ).*(1_000_000)
267
+
268
+ puts "\e[38;2;255;255;0m:: Warning total time also depends on your terminal speed!\e[0m"
269
+ puts "Total Real Time: #{T_FMT % total_real_t}\u03BCs"
270
+ puts "Total CPU Time: #{T_FMT % total_cpu_t}\u03BCs"
271
+ end
@@ -0,0 +1,25 @@
1
+ static VALUE getDiskStats (volatile VALUE obj, volatile VALUE path) {
2
+ FILE *file = fopen("/proc/diskstats", "r") ;
3
+ if(!file) return rb_ary_new() ;
4
+
5
+ char lines[120] ;
6
+ unsigned long long read, write ;
7
+ char *p = StringValuePtr(path) ;
8
+
9
+ while(fgets(lines, 119, file)) {
10
+ sscanf(lines, "%*s %*s %s %*s %*s %llu %*s %*s %*s %llu", lines, &read, &write) ;
11
+
12
+ if(strcmp(lines, p) == 0) {
13
+ fclose(file) ;
14
+
15
+ return rb_ary_new_from_args(
16
+ 2,
17
+ ULL2NUM(read),
18
+ ULL2NUM(write)
19
+ ) ;
20
+ }
21
+ }
22
+
23
+ fclose(file) ;
24
+ return rb_ary_new() ;
25
+ }
@@ -4,7 +4,8 @@ unless have_const('linux') || RbConfig::CONFIG['arch'].to_s[/linux/]
4
4
  abort('Platform is not linux')
5
5
  end
6
6
 
7
- unless have_header('sys/statvfs.h') && have_header('ruby.h')
7
+ unless have_header('sys/statvfs.h') && have_header('sys/ioctl.h') &&
8
+ have_header('fcntl.h') && have_header('linux/fs.h') && have_header('unistd.h')
8
9
  abort('Missing header')
9
10
  end
10
11
 
@@ -1,5 +1,12 @@
1
1
  #include <sys/statvfs.h>
2
+ #include <sys/ioctl.h>
3
+ #include <fcntl.h>
4
+ #include <linux/fs.h>
5
+ #include <unistd.h>
6
+
2
7
  #include "ruby.h"
8
+ #include "sector_size.h"
9
+ #include "disk_stat.h"
3
10
 
4
11
  #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
5
12
  #pragma GCC optimize ("O3")
@@ -11,7 +18,7 @@
11
18
  #pragma intel optimization_level 3
12
19
  #endif
13
20
 
14
- static VALUE statfs(VALUE obj, VALUE dir) {
21
+ static VALUE statfs(volatile VALUE obj, volatile VALUE dir) {
15
22
  struct statvfs buf ;
16
23
  char *d = StringValuePtr(dir) ;
17
24
  VALUE hash = rb_hash_new() ;
@@ -36,4 +43,6 @@ void Init_fs_stat() {
36
43
  VALUE _linux_stat = rb_define_module("LinuxStat") ;
37
44
  VALUE fs = rb_define_module_under(_linux_stat, "FS") ;
38
45
  rb_define_module_function(fs, "stat", statfs, 1) ;
46
+ rb_define_module_function(fs, "sectors", getSectorSize, 1) ;
47
+ rb_define_module_function(fs, "total_io", getDiskStats, 1) ;
39
48
  }
@@ -0,0 +1,13 @@
1
+ static VALUE getSectorSize(volatile VALUE obj, volatile VALUE path) {
2
+ char *dev = StringValuePtr(path) ;
3
+
4
+ unsigned int fd = open(dev, O_RDONLY | O_NONBLOCK) ;
5
+ if(fd < 0) return Qnil ;
6
+
7
+ unsigned int sSize = 0 ;
8
+ short status = ioctl(fd, BLKSSZGET, &sSize) ;
9
+ close(fd) ;
10
+ if(status < 0) return Qnil ;
11
+
12
+ return UINT2NUM(sSize) ;
13
+ }
data/ext/nproc/nproc.c CHANGED
@@ -15,7 +15,7 @@
15
15
  #pragma intel optimization_level 3
16
16
  #endif
17
17
 
18
- static VALUE count_cpu_for_pid(VALUE obj, VALUE pid) {
18
+ static VALUE count_cpu_for_pid(volatile VALUE obj, volatile VALUE pid) {
19
19
  cpu_set_t set ;
20
20
  CPU_ZERO(&set) ;
21
21
  char status = sched_getaffinity(FIX2INT(pid), sizeof(set), &set) ;
@@ -1,4 +1,4 @@
1
- VALUE last_pid(VALUE obj) {
1
+ static VALUE last_pid(volatile VALUE obj) {
2
2
  FILE *f = fopen("/proc/loadavg", "r") ;
3
3
  if (!f) return Qnil ;
4
4
 
data/ext/procfs/procfs.c CHANGED
@@ -13,6 +13,7 @@
13
13
  #include <stdio.h>
14
14
  #include <unistd.h>
15
15
  #include <string.h>
16
+ #include <glob.h>
16
17
  #include "ruby.h"
17
18
  #include "uptime.h"
18
19
  #include "statm.h"
@@ -22,6 +23,8 @@
22
23
  int Init_procfs() {
23
24
  VALUE _linux_stat = rb_define_module("LinuxStat") ;
24
25
  VALUE _procfs = rb_define_module_under(_linux_stat, "ProcFS") ;
26
+ VALUE _cpu = rb_define_module_under(_linux_stat, "CPU") ;
27
+ VALUE _process = rb_define_module_under(_linux_stat, "Process") ;
25
28
 
26
29
  // uptime
27
30
  rb_define_module_function(_procfs, "uptime_f", uptime_f, 0) ;
@@ -40,4 +43,7 @@ int Init_procfs() {
40
43
  rb_define_module_function(_procfs, "ps_state", ps_state, 1) ;
41
44
  rb_define_module_function(_procfs, "ps_times", ps_times, 1) ;
42
45
  rb_define_module_function(_procfs, "ps_stat", ps_stat, 1) ;
46
+ rb_define_module_function(_procfs, "cpu_times", cpuTimes, 0) ;
47
+ rb_define_module_function(_procfs, "list_process", listProcess, 0) ;
48
+
43
49
  }
data/ext/procfs/stat.h CHANGED
@@ -1,4 +1,4 @@
1
- VALUE ps_state(VALUE obj, VALUE pid) {
1
+ static VALUE ps_state(volatile VALUE obj, volatile VALUE pid) {
2
2
  int _pid = FIX2INT(pid) ;
3
3
  if (_pid < 0) return rb_str_new_cstr("") ;
4
4
 
@@ -17,7 +17,30 @@ VALUE ps_state(VALUE obj, VALUE pid) {
17
17
  return rb_str_new_cstr(_s) ;
18
18
  }
19
19
 
20
- VALUE ps_times(VALUE obj, VALUE pid) {
20
+ static VALUE listProcess(volatile VALUE obj) {
21
+ VALUE ary = rb_ary_new() ;
22
+
23
+ glob_t globlist ;
24
+ int status = glob("/proc/[0-9]*/", GLOB_NOSORT, NULL, &globlist) ;
25
+
26
+ if (status == GLOB_NOSPACE || status == GLOB_ABORTED || status == GLOB_NOMATCH) {
27
+ globfree(&globlist) ;
28
+ return ary ;
29
+ }
30
+
31
+ char *v, *token ;
32
+ unsigned int i = 0 ;
33
+ unsigned int num ;
34
+
35
+ while(v = globlist.gl_pathv[i++]) {
36
+ if (sscanf(v, "/proc/%u", &num) == 1) rb_ary_push(ary, UINT2NUM(num)) ;
37
+ }
38
+
39
+ globfree(&globlist) ;
40
+ return ary ;
41
+ }
42
+
43
+ static VALUE ps_times(volatile VALUE obj, volatile VALUE pid) {
21
44
  int _pid = FIX2INT(pid) ;
22
45
  if (_pid < 0) return Qnil ;
23
46
 
@@ -38,7 +61,7 @@ VALUE ps_times(VALUE obj, VALUE pid) {
38
61
  return DBL2NUM(total_time) ;
39
62
  }
40
63
 
41
- VALUE ps_stat(VALUE obj, VALUE pid) {
64
+ static VALUE ps_stat(volatile VALUE obj, volatile VALUE pid) {
42
65
  int _pid = FIX2INT(pid) ;
43
66
  if (_pid < 0) return rb_str_new_cstr("") ;
44
67
 
@@ -117,3 +140,46 @@ VALUE ps_stat(VALUE obj, VALUE pid) {
117
140
  INT2NUM(exit_code)
118
141
  ) ;
119
142
  }
143
+
144
+ static VALUE cpuTimes(volatile VALUE obj) {
145
+ VALUE ary = rb_ary_new() ;
146
+ FILE *f = fopen("/proc/stat", "r") ;
147
+
148
+ if (!f) return ary ;
149
+
150
+ unsigned long user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice ;
151
+ char line[1024] ;
152
+ char cpuCode[7] ;
153
+ float ticks = sysconf(_SC_CLK_TCK) ;
154
+ char scanStatus ;
155
+
156
+ while(fgets(line, 1023, f)) {
157
+ if (!(line[0] == 'c' && line[1] == 'p' && line[2] == 'u')) break ;
158
+
159
+ scanStatus = sscanf(line,
160
+ "%7[cpu0-9] %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
161
+ cpuCode, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest, &guest_nice
162
+ ) ;
163
+
164
+ if (scanStatus != 11) break ;
165
+
166
+ VALUE innerHash = rb_hash_new() ;
167
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("cpu")), rb_str_new_cstr(cpuCode)) ;
168
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("user")), rb_float_new(user / ticks)) ;
169
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("nice")), rb_float_new(nice / ticks)) ;
170
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("system")), rb_float_new(system / ticks)) ;
171
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("idle")), rb_float_new(idle / ticks)) ;
172
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("iowait")), rb_float_new(iowait / ticks)) ;
173
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("irq")), rb_float_new(irq / ticks)) ;
174
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("softirq")), rb_float_new(softirq / ticks)) ;
175
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("steal")), rb_float_new(steal / ticks)) ;
176
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("guest")), rb_float_new(guest / ticks)) ;
177
+ rb_hash_aset(innerHash, ID2SYM(rb_intern("guest_nice")), rb_float_new(guest_nice / ticks)) ;
178
+
179
+ rb_ary_push(ary, innerHash) ;
180
+ }
181
+
182
+ fclose(f) ;
183
+
184
+ return ary ;
185
+ }
data/ext/procfs/statm.h CHANGED
@@ -1,6 +1,6 @@
1
1
  #define PAGESIZE sysconf(_SC_PAGESIZE)
2
2
 
3
- VALUE statm(VALUE obj, VALUE pid) {
3
+ static VALUE statm(volatile VALUE obj, volatile VALUE pid) {
4
4
  VALUE hash = rb_hash_new() ;
5
5
 
6
6
  int _pid = FIX2INT(pid) ;
@@ -34,7 +34,7 @@ VALUE statm(VALUE obj, VALUE pid) {
34
34
  return hash ;
35
35
  }
36
36
 
37
- VALUE statm_virtual(VALUE obj, VALUE pid) {
37
+ static VALUE statm_virtual(volatile VALUE obj, volatile VALUE pid) {
38
38
  int _pid = FIX2INT(pid) ;
39
39
  if (_pid < 0) return Qnil ;
40
40
 
@@ -52,7 +52,7 @@ VALUE statm_virtual(VALUE obj, VALUE pid) {
52
52
  return UINT2NUM(_virtual * PAGESIZE) ;
53
53
  }
54
54
 
55
- VALUE statm_resident(VALUE obj, VALUE pid) {
55
+ static VALUE statm_resident(volatile VALUE obj, volatile VALUE pid) {
56
56
  int _pid = FIX2INT(pid) ;
57
57
  if (_pid < 0) return Qnil ;
58
58
 
@@ -70,7 +70,7 @@ VALUE statm_resident(VALUE obj, VALUE pid) {
70
70
  return UINT2NUM(resident * PAGESIZE) ;
71
71
  }
72
72
 
73
- VALUE statm_shared(VALUE obj, VALUE pid) {
73
+ static VALUE statm_shared(volatile VALUE obj, volatile VALUE pid) {
74
74
  int _pid = FIX2INT(pid) ;
75
75
  if (_pid < 0) return Qnil ;
76
76
 
@@ -88,7 +88,7 @@ VALUE statm_shared(VALUE obj, VALUE pid) {
88
88
  return UINT2NUM(shared * PAGESIZE) ;
89
89
  }
90
90
 
91
- VALUE statm_memory(VALUE obj, VALUE pid) {
91
+ static VALUE statm_memory(volatile VALUE obj, volatile VALUE pid) {
92
92
  int _pid = FIX2INT(pid) ;
93
93
  if (_pid < 0) return Qnil ;
94
94
 
data/ext/procfs/uptime.h CHANGED
@@ -1,4 +1,4 @@
1
- VALUE uptime_f(VALUE obj) {
1
+ static VALUE uptime_f(volatile VALUE obj) {
2
2
  FILE *f = fopen("/proc/uptime", "r") ;
3
3
  if (!f) return Qnil ;
4
4
 
@@ -11,103 +11,103 @@
11
11
  #pragma intel optimization_level 3
12
12
  #endif
13
13
 
14
- static VALUE getTick(VALUE obj) {
14
+ static VALUE getTick(volatile VALUE obj) {
15
15
  int val = sysconf(_SC_CLK_TCK) ;
16
16
  if (val < 0) return Qnil ;
17
17
 
18
18
  return INT2FIX(val) ;
19
19
  }
20
20
 
21
- static VALUE getChildMax(VALUE obj) {
21
+ static VALUE getChildMax(volatile VALUE obj) {
22
22
  long long int val = sysconf(_SC_CHILD_MAX) ;
23
23
  if (val < 0) return Qnil ;
24
24
 
25
25
  return LL2NUM(val) ;
26
26
  }
27
27
 
28
- static VALUE getHostnameMax(VALUE obj) {
28
+ static VALUE getHostnameMax(volatile VALUE obj) {
29
29
  long long val = sysconf(_SC_HOST_NAME_MAX) ;
30
30
  if (val < 0) return Qnil ;
31
31
 
32
32
  return LL2NUM(val) ;
33
33
  }
34
34
 
35
- static VALUE getLoginNameMax(VALUE obj) {
35
+ static VALUE getLoginNameMax(volatile VALUE obj) {
36
36
  long long val = sysconf(_SC_LOGIN_NAME_MAX) ;
37
37
  if (val < 0) return Qnil ;
38
38
 
39
39
  return LL2NUM(val) ;
40
40
  }
41
41
 
42
- static VALUE getOpenMax(VALUE obj) {
42
+ static VALUE getOpenMax(volatile VALUE obj) {
43
43
  long long val = sysconf(_SC_OPEN_MAX) ;
44
44
  if (val < 0) return Qnil ;
45
45
 
46
46
  return LL2NUM(val) ;
47
47
  }
48
48
 
49
- static VALUE getPageSize(VALUE obj) {
49
+ static VALUE getPageSize(volatile VALUE obj) {
50
50
  int val = sysconf(_SC_PAGESIZE) ;
51
51
  if (val < 0) return Qnil ;
52
52
 
53
53
  return INT2FIX(val) ;
54
54
  }
55
55
 
56
- static VALUE getStreamMax(VALUE obj) {
56
+ static VALUE getStreamMax(volatile VALUE obj) {
57
57
  long long val = sysconf(_SC_STREAM_MAX) ;
58
58
  if (val < 0) return Qnil ;
59
59
 
60
60
  return LL2NUM(val) ;
61
61
  }
62
62
 
63
- static VALUE getTTYNameMax(VALUE obj) {
63
+ static VALUE getTTYNameMax(volatile VALUE obj) {
64
64
  long long val = sysconf(_SC_TTY_NAME_MAX) ;
65
65
  if (val < 0) return Qnil ;
66
66
 
67
67
  return LL2NUM(val) ;
68
68
  }
69
69
 
70
- static VALUE getPosixVersion(VALUE obj) {
70
+ static VALUE getPosixVersion(volatile VALUE obj) {
71
71
  long long val = sysconf(_SC_VERSION) ;
72
72
  if (val < 0) return Qnil ;
73
73
 
74
74
  return LL2NUM(val) ;
75
75
  }
76
76
 
77
- static VALUE getLineMax(VALUE obj) {
77
+ static VALUE getLineMax(volatile VALUE obj) {
78
78
  long long val = sysconf(_SC_LINE_MAX) ;
79
79
  if (val < 0) return Qnil ;
80
80
 
81
81
  return LL2NUM(val) ;
82
82
  }
83
83
 
84
- static VALUE getExprNestMax(VALUE obj) {
84
+ static VALUE getExprNestMax(volatile VALUE obj) {
85
85
  long long val = sysconf(_SC_EXPR_NEST_MAX) ;
86
86
  if (val < 0) return Qnil ;
87
87
 
88
88
  return LL2NUM(val) ;
89
89
  }
90
90
 
91
- static VALUE getProcessorConfigured(VALUE obj) {
91
+ static VALUE getProcessorConfigured(volatile VALUE obj) {
92
92
  long val = sysconf(_SC_NPROCESSORS_CONF) ;
93
93
  if (val < 0) return Qnil ;
94
94
 
95
95
  return LONG2NUM(val) ;
96
96
  }
97
97
 
98
- static VALUE getProcessorOnline(VALUE obj) {
98
+ static VALUE getProcessorOnline(volatile VALUE obj) {
99
99
  long val = sysconf(_SC_NPROCESSORS_ONLN) ;
100
100
  if (val < 0) return Qnil ;
101
101
 
102
102
  return LONG2NUM(val) ;
103
103
  }
104
104
 
105
- static VALUE getUser(VALUE obj) {
105
+ static VALUE getUser(volatile VALUE obj) {
106
106
  char *name = getlogin() ;
107
107
  return name ? rb_str_new_cstr(name) : rb_str_new_cstr("") ;
108
108
  }
109
109
 
110
- static VALUE getUID(VALUE obj) {
110
+ static VALUE getUID(volatile VALUE obj) {
111
111
  return UINT2NUM((unsigned int) getuid()) ;
112
112
  }
113
113
 
@@ -115,11 +115,11 @@ static VALUE getGID(VALUE obj) {
115
115
  return UINT2NUM((unsigned int) getgid()) ;
116
116
  }
117
117
 
118
- static VALUE getEUID(VALUE obj) {
118
+ static VALUE getEUID(volatile VALUE obj) {
119
119
  return UINT2NUM((unsigned int) geteuid()) ;
120
120
  }
121
121
 
122
- static VALUE getHostname(VALUE obj) {
122
+ static VALUE getHostname(volatile VALUE obj) {
123
123
  int h_max = sysconf(_SC_HOST_NAME_MAX) + 1 ;
124
124
  char hostname[h_max] ;
125
125
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  static struct sysinfo info ;
15
15
 
16
- VALUE totalram(VALUE obj) {
16
+ static VALUE totalram(volatile VALUE obj) {
17
17
  char status = sysinfo(&info) ;
18
18
  if (status < 0) return Qnil ;
19
19
 
@@ -22,7 +22,7 @@ VALUE totalram(VALUE obj) {
22
22
  return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
23
23
  }
24
24
 
25
- VALUE freeram(VALUE obj) {
25
+ static VALUE freeram(volatile VALUE obj) {
26
26
  char status = sysinfo(&info) ;
27
27
  if (status < 0) return Qnil ;
28
28
 
@@ -31,7 +31,7 @@ VALUE freeram(VALUE obj) {
31
31
  return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
32
32
  }
33
33
 
34
- VALUE sharedram(VALUE obj) {
34
+ static VALUE sharedram(volatile VALUE obj) {
35
35
  char status = sysinfo(&info) ;
36
36
  if (status < 0) return Qnil ;
37
37
 
@@ -40,7 +40,7 @@ VALUE sharedram(VALUE obj) {
40
40
  return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
41
41
  }
42
42
 
43
- VALUE bufferram(VALUE obj) {
43
+ static VALUE bufferram(volatile VALUE obj) {
44
44
  char status = sysinfo(&info) ;
45
45
  if (status < 0) return Qnil ;
46
46
 
@@ -49,7 +49,7 @@ VALUE bufferram(VALUE obj) {
49
49
  return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
50
50
  }
51
51
 
52
- VALUE totalswap(VALUE obj) {
52
+ static VALUE totalswap(volatile VALUE obj) {
53
53
  static struct sysinfo info ;
54
54
  char status = sysinfo(&info) ;
55
55
  if (status < 0) return Qnil ;
@@ -59,7 +59,7 @@ VALUE totalswap(VALUE obj) {
59
59
  return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
60
60
  }
61
61
 
62
- VALUE freeswap(VALUE obj) {
62
+ static VALUE freeswap(volatile VALUE obj) {
63
63
  char status = sysinfo(&info) ;
64
64
  if (status < 0) return Qnil ;
65
65
 
@@ -68,7 +68,7 @@ VALUE freeswap(VALUE obj) {
68
68
  return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
69
69
  }
70
70
 
71
- VALUE totalhigh(VALUE obj) {
71
+ static VALUE totalhigh(volatile VALUE obj) {
72
72
  char status = sysinfo(&info) ;
73
73
  if (status < 0) return Qnil ;
74
74
 
@@ -77,7 +77,7 @@ VALUE totalhigh(VALUE obj) {
77
77
  return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
78
78
  }
79
79
 
80
- VALUE freehigh(VALUE obj) {
80
+ static VALUE freehigh(volatile VALUE obj) {
81
81
  char status = sysinfo(&info) ;
82
82
  if (status < 0) return Qnil ;
83
83
 
@@ -86,7 +86,7 @@ VALUE freehigh(VALUE obj) {
86
86
  return rb_funcallv_public(_rb_v, rb_intern("*"), 1, &_rb_mem_unit) ;
87
87
  }
88
88
 
89
- VALUE uptime(VALUE obj) {
89
+ static VALUE uptime(volatile VALUE obj) {
90
90
  char status = sysinfo(&info) ;
91
91
  if (status < 0) return Qnil ;
92
92
 
@@ -94,7 +94,7 @@ VALUE uptime(VALUE obj) {
94
94
  return ULL2NUM((unsigned long long) v) ;
95
95
  }
96
96
 
97
- VALUE loads(VALUE obj) {
97
+ static VALUE loads(volatile VALUE obj) {
98
98
  char status = sysinfo(&info) ;
99
99
  if(status < 0) return rb_ary_new() ;
100
100
 
@@ -112,7 +112,7 @@ VALUE loads(VALUE obj) {
112
112
  }
113
113
 
114
114
  // Some people may need this function, just keep it to not make unnecessary calls
115
- VALUE sysinfoStat(VALUE obj) {
115
+ static VALUE sysinfoStat(volatile VALUE obj) {
116
116
  char status = sysinfo(&info) ;
117
117
  VALUE hash = rb_hash_new() ;
118
118
  if (status < 0) return hash ;
@@ -28,23 +28,23 @@ void init_buf() {
28
28
  }
29
29
  }
30
30
 
31
- static VALUE getSysname(VALUE obj) {
31
+ static VALUE getSysname(volatile VALUE obj) {
32
32
  return rb_str_new_cstr(sysname) ;
33
33
  }
34
34
 
35
- static VALUE getNodename(VALUE obj) {
35
+ static VALUE getNodename(volatile VALUE obj) {
36
36
  return rb_str_new_cstr(nodename) ;
37
37
  }
38
38
 
39
- static VALUE getRelease(VALUE obj) {
39
+ static VALUE getRelease(volatile VALUE obj) {
40
40
  return rb_str_new_cstr(release) ;
41
41
  }
42
42
 
43
- static VALUE getVersion(VALUE obj) {
43
+ static VALUE getVersion(volatile VALUE obj) {
44
44
  return rb_str_new_cstr(version) ;
45
45
  }
46
46
 
47
- static VALUE getMachine(VALUE obj) {
47
+ static VALUE getMachine(volatile VALUE obj) {
48
48
  return rb_str_new_cstr(machine) ;
49
49
  }
50
50
 
@@ -209,6 +209,10 @@ module LinuxStat
209
209
  h
210
210
  end
211
211
 
212
+ def times
213
+ LinuxStat::ProcFS.cpu_times
214
+ end
215
+
212
216
  ##
213
217
  # Returns a Hash with max core frequencies corresponding to the CPUs.
214
218
  #
@@ -110,6 +110,51 @@ module LinuxStat
110
110
  def stat_raw(fs = ?..freeze)
111
111
  LinuxStat::FS.stat(fs)
112
112
  end
113
+
114
+ def sector_size(path = LinuxStat::Mounts.root)
115
+ LinuxStat::FS.sectors(path)
116
+ end
117
+
118
+ def io_total(path = LinuxStat::Mounts.root)
119
+ p = File.split(path)[-1]
120
+ _io_total = LinuxStat::FS.total_io(p)
121
+
122
+ return {} if _io_total.empty?
123
+
124
+ sector_size = LinuxStat::FS.sectors(path)
125
+ return {} unless sector_size
126
+
127
+ {
128
+ read: _io_total[0] &.*(sector_size),
129
+ write: _io_total[1] &.*(sector_size),
130
+ }
131
+ end
132
+
133
+ def io_usage(path = LinuxStat::Mounts.root, interval = 0.1)
134
+ p = File.split(path)[-1]
135
+
136
+ measure1 = LinuxStat::FS.total_io(p)
137
+ sleep(interval)
138
+ measure2 = LinuxStat::FS.total_io(p)
139
+
140
+ return {} if measure1.empty? || measure2.empty?
141
+
142
+ sector_size = LinuxStat::FS.sectors(path)
143
+ return {} unless sector_size
144
+
145
+ m1r = measure1[0]
146
+ m1w = measure1[1]
147
+
148
+ m2r = measure2[0]
149
+ m2w = measure2[1]
150
+
151
+ {
152
+ read: m2r.-(m1r).*(sector_size).fdiv(interval),
153
+ write: m2w.-(m1w).*(sector_size).fdiv(interval)
154
+ }
155
+ end
156
+
157
+ alias sectors sector_size
113
158
  end
114
159
  end
115
160
  end
@@ -7,6 +7,28 @@ module LinuxStat
7
7
  # 4. kiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB
8
8
 
9
9
  module PrettifyBytes
10
+ # Kilo = Kilobyte (1000 - 1), and so on...
11
+ # 8.times { |x| puts 1000.**(x.next).to_s << '.00' }
12
+ KILO = 1000.00
13
+ MEGA = 1000000.00
14
+ GIGA = 1000000000.00
15
+ TERA = 1000000000000.00
16
+ PETA = 1000000000000000.00
17
+ EXA = 1000000000000000000.00
18
+ ZETTA = 1000000000000000000000.00
19
+ YOTTA = 1000000000000000000000000.00
20
+
21
+ # Binary suffixes
22
+ # 8.times { |x| puts 1024.**(x.next).to_s << '.00' }
23
+ KIBI = 1024.00
24
+ MEBI = 1048576.00
25
+ GIBI = 1073741824.00
26
+ TEBI = 1099511627776.00
27
+ PEBI = 1125899906842624.00
28
+ EXBI = 1152921504606846976.00
29
+ ZEBI = 1180591620717411303424.00
30
+ YOBI = 1208925819614629174706176.00
31
+
10
32
  class << self
11
33
  ##
12
34
  # Converts a number to decimal byte units and outputs with the metric prefix
@@ -24,12 +46,33 @@ module LinuxStat
24
46
  #
25
47
  # => "1.07 gigabytes"
26
48
  def convert_decimal(n, precision: 2)
27
- @@d_units ||= %W(#{''} kilo mega giga tera peta exa zetta)
28
- .map.with_index { |x, i| [x, 1000.**(i + 1)] }
29
- unit = @@d_units.find { |x| n < x[1] } || ['yotta'.freeze, 10 ** 27]
30
-
31
- converted = n.fdiv(unit[1] / 1000).round(2)
32
- "#{pad_left(converted, precision)} #{unit[0]}byte#{?s.freeze if converted != 1}"
49
+ if n < KILO
50
+ "#{"%.#{precision}f" % n} byte#{?s.freeze if n != 1}"
51
+ elsif n < MEGA
52
+ n /= KILO
53
+ "#{"%.#{precision}f" % n} kilobyte#{?s.freeze if n != 1}"
54
+ elsif n < GIGA
55
+ n /= MEGA
56
+ "#{"%.#{precision}f" % n} megabyte#{?s.freeze if n != 1}"
57
+ elsif n < TERA
58
+ n /= GIGA
59
+ "#{"%.#{precision}f" % n} gigabyte#{?s.freeze if n != 1}"
60
+ elsif n < PETA
61
+ n /= TERA
62
+ "#{"%.#{precision}f" % n} terabyte#{?s.freeze if n != 1}"
63
+ elsif n < EXA
64
+ n /= PETA
65
+ "#{"%.#{precision}f" % n} petabyte#{?s.freeze if n != 1}"
66
+ elsif n < ZETTA
67
+ n /= EXA
68
+ "#{"%.#{precision}f" % n} exabyte#{?s.freeze if n != 1}"
69
+ elsif n < YOTTA
70
+ n /= ZETTA
71
+ "#{"%.#{precision}f" % n} zettabyte#{?s.freeze if n != 1}"
72
+ else
73
+ n /= YOTTA
74
+ "#{"%.#{precision}f" % n} yottabyte#{?s.freeze if n != 1}"
75
+ end
33
76
  end
34
77
 
35
78
  # Converts a number to binary byte units and outputs with the IEC prefix
@@ -47,12 +90,33 @@ module LinuxStat
47
90
  #
48
91
  # => "1.0 gibibyte"
49
92
  def convert_binary(n, precision: 2)
50
- @@b_units ||= %W(#{''} kibi mebi gibi tebi pebi exbi zebi)
51
- .map.with_index { |x, i| [x, 1024.**(i + 1)] }
52
- unit = @@b_units.find { |x| n < x[1] } || ['yobi'.freeze, 10 ** 27]
53
-
54
- converted = n.fdiv(unit[1] / 1024).round(2)
55
- "#{pad_left(converted, precision)} #{unit[0]}byte#{?s.freeze if converted != 1}"
93
+ if n < KIBI
94
+ "#{"%.#{precision}f" % n} byte#{?s.freeze if n != 1}"
95
+ elsif n < MEBI
96
+ n /= KIBI
97
+ "#{"%.#{precision}f" % n} kibibyte#{?s.freeze if n != 1}"
98
+ elsif n < GIBI
99
+ n /= MEBI
100
+ "#{"%.#{precision}f" % n} mebibyte#{?s.freeze if n != 1}"
101
+ elsif n < TEBI
102
+ n /= GIBI
103
+ "#{"%.#{precision}f" % n} gibibyte#{?s.freeze if n != 1}"
104
+ elsif n < PEBI
105
+ n /= TEBI
106
+ "#{"%.#{precision}f" % n} tebibyte#{?s.freeze if n != 1}"
107
+ elsif n < EXBI
108
+ n /= PEBI
109
+ "#{"%.#{precision}f" % n} pebibyte#{?s.freeze if n != 1}"
110
+ elsif n < ZEBI
111
+ n /= EXBI
112
+ "#{"%.#{precision}f" % n} exbiyte#{?s.freeze if n != 1}"
113
+ elsif n < YOBI
114
+ n /= ZEBI
115
+ "#{"%.#{precision}f" % n} zebibyte#{?s.freeze if n != 1}"
116
+ else
117
+ n /= YOBI
118
+ "#{"%.#{precision}f" % n} yobibyte#{?s.freeze if n != 1}"
119
+ end
56
120
  end
57
121
 
58
122
  # Converts a number to decimal byte units
@@ -70,12 +134,33 @@ module LinuxStat
70
134
  #
71
135
  # => "1.07 GB"
72
136
  def convert_short_decimal(n, precision: 2)
73
- @@sd_units ||= %W(#{''} k M G T P E Z)
74
- .map.with_index { |x, i| [x, 1000.**(i + 1)] }
75
- unit = @@sd_units.find { |x| n < x[1] } || [?Y.freeze, 10 ** 27]
76
-
77
- converted = n.fdiv(unit[1] / 1000).round(2)
78
- "#{pad_left(converted, precision)} #{unit[0]}B"
137
+ if n < KILO
138
+ "#{"%.#{precision}f" % n} B"
139
+ elsif n < MEGA
140
+ n /= KILO
141
+ "#{"%.#{precision}f" % n} kB"
142
+ elsif n < GIGA
143
+ n /= MEGA
144
+ "#{"%.#{precision}f" % n} MB"
145
+ elsif n < TERA
146
+ n /= GIGA
147
+ "#{"%.#{precision}f" % n} GB"
148
+ elsif n < PETA
149
+ n /= TERA
150
+ "#{"%.#{precision}f" % n} TB"
151
+ elsif n < EXA
152
+ n /= PETA
153
+ "#{"%.#{precision}f" % n} PB"
154
+ elsif n < ZETTA
155
+ n /= EXA
156
+ "#{"%.#{precision}f" % n} EB"
157
+ elsif n < YOTTA
158
+ n /= ZETTA
159
+ "#{"%.#{precision}f" % n} ZB"
160
+ else
161
+ n /= YOTTA
162
+ "#{"%.#{precision}f" % n} YB"
163
+ end
79
164
  end
80
165
 
81
166
  ##
@@ -95,19 +180,33 @@ module LinuxStat
95
180
  #
96
181
  # => "1.0 GiB"
97
182
  def convert_short_binary(n, precision: 2)
98
- return "#{pad_left(n, precision)} B" if n < 1024
99
-
100
- @@sb_units ||= %W(#{''} K M G T P E Z)
101
- .map.with_index { |x, i| [x, 1024.**(i + 1)] }
102
- unit = @@sb_units.find { |x| n < x[1] } || [?Y.freeze, 1024 ** 9]
103
-
104
- converted = n.fdiv(unit[1] / 1024).round(2)
105
- "#{pad_left(converted, precision)} #{unit[0]}iB"
106
- end
107
-
108
- private
109
- def pad_left(n, mantissa_length = 2)
110
- sprintf("%.#{mantissa_length}f".freeze, n)
183
+ if n < KIBI
184
+ "#{"%.#{precision}f" % n} B"
185
+ elsif n < MEBI
186
+ n /= KIBI
187
+ "#{"%.#{precision}f" % n} KiB"
188
+ elsif n < GIBI
189
+ n /= MEBI
190
+ "#{"%.#{precision}f" % n} MiB"
191
+ elsif n < TEBI
192
+ n /= GIBI
193
+ "#{"%.#{precision}f" % n} GiB"
194
+ elsif n < PEBI
195
+ n /= TEBI
196
+ "#{"%.#{precision}f" % n} TiB"
197
+ elsif n < EXBI
198
+ n /= PEBI
199
+ "#{"%.#{precision}f" % n} PiB"
200
+ elsif n < ZEBI
201
+ n /= EXBI
202
+ "#{"%.#{precision}f" % n} EiB"
203
+ elsif n < YOBI
204
+ n /= ZEBI
205
+ "#{"%.#{precision}f" % n} ZiB"
206
+ else
207
+ n /= YOBI
208
+ "#{"%.#{precision}f" % n} YiB"
209
+ end
111
210
  end
112
211
  end
113
212
  end
@@ -1,25 +1,15 @@
1
1
  module LinuxStat
2
2
  # Shows various information about a process that is either
3
3
  # running, sleeping, idle or a zombie.
4
-
5
4
  module Process
6
5
  class << self
7
6
  ##
8
7
  # Returns the list of processes from /proc/.
8
+ # The output doesn't guarantee a sorted list, in fact it's shuffled most of the time.
9
9
  #
10
10
  # The return type is an Array of Integers.
11
11
  def list
12
- d = Dir['/proc/*'.freeze]
13
- ret, i = [], -1
14
- count = d.length
15
-
16
- while(i += 1) < count
17
- pid = File.split(d[i])[1]
18
- pid_i = pid.to_i
19
- ret << pid_i if pid_i.to_s == pid
20
- end
21
-
22
- ret
12
+ LinuxStat::ProcFS.list_process
23
13
  end
24
14
 
25
15
  ##
@@ -27,7 +17,7 @@ module LinuxStat
27
17
  #
28
18
  # The return type is Integer.
29
19
  def count
30
- list.length
20
+ LinuxStat::ProcFS.list_process.length
31
21
  end
32
22
 
33
23
  ##
@@ -36,7 +26,7 @@ module LinuxStat
36
26
  def names
37
27
  h, i = {}, -1
38
28
 
39
- l = list
29
+ l = LinuxStat::ProcFS.list_process
40
30
  count = l.length
41
31
 
42
32
  while(i += 1) < count
@@ -57,7 +47,7 @@ module LinuxStat
57
47
  def cmdlines
58
48
  h, i = {}, -1
59
49
 
60
- l = list
50
+ l = LinuxStat::ProcFS.list_process
61
51
  count = l.length
62
52
 
63
53
  while(i += 1) < count
@@ -66,7 +56,7 @@ module LinuxStat
66
56
  begin
67
57
  cmdlines = IO.read("/proc/#{x}/cmdline").strip
68
58
  cmdlines.gsub!(?\u0000.freeze, ?\s.freeze)
69
- h.merge!( x => cmdlines)
59
+ h.merge!(x => cmdlines)
70
60
  rescue StandardError
71
61
  end
72
62
  end
@@ -78,7 +68,7 @@ module LinuxStat
78
68
  def types
79
69
  h, i = {}, -1
80
70
 
81
- l = list
71
+ l = LinuxStat::ProcFS.list_process
82
72
  count = l.length
83
73
 
84
74
  while(i += 1) < count
@@ -109,7 +99,7 @@ module LinuxStat
109
99
  # Returns all the id of processes that are sleeping.
110
100
  # The return type is an Array of Integers.
111
101
  def sleeping
112
- list.select { |x|
102
+ LinuxStat::ProcFS.list_process.select { |x|
113
103
  LinuxStat::ProcFS.ps_state(x) == ?S.freeze
114
104
  }
115
105
  end
@@ -118,7 +108,7 @@ module LinuxStat
118
108
  # Returns all the id of processes that are idle.
119
109
  # The return type is an Array of Integers.
120
110
  def idle
121
- list.select { |x|
111
+ LinuxStat::ProcFS.list_process.select { |x|
122
112
  LinuxStat::ProcFS.ps_state(x) == ?I.freeze
123
113
  }
124
114
  end
@@ -127,7 +117,7 @@ module LinuxStat
127
117
  # Returns all the id of processes that are zombies.
128
118
  # The return type is an Array of Integers.
129
119
  def zombie
130
- list.select { |x|
120
+ LinuxStat::ProcFS.list_process.select { |x|
131
121
  LinuxStat::ProcFS.ps_state(x) == ?Z.freeze
132
122
  }
133
123
  end
@@ -136,7 +126,7 @@ module LinuxStat
136
126
  # Returns all the id of processes that are running.
137
127
  # The return type is an Array of Integers.
138
128
  def running
139
- list.select { |x|
129
+ LinuxStat::ProcFS.list_process.select { |x|
140
130
  LinuxStat::ProcFS.ps_state(x) == ?R.freeze
141
131
  }
142
132
  end
@@ -145,7 +135,7 @@ module LinuxStat
145
135
  # Returns all the id of processes that are stopped.
146
136
  # The return type is an Array of Integers.
147
137
  def stopped
148
- list.select { |x|
138
+ LinuxStat::ProcFS.list_process.select { |x|
149
139
  v = LinuxStat::ProcFS.ps_state(x)
150
140
  v == ?T.freeze || v == ?t.freeze
151
141
  }
@@ -521,7 +521,9 @@ module LinuxStat
521
521
  def start_time(pid = $$)
522
522
  # Getting two Time objects and dealing with floating point numbers
523
523
  # Just to make sure the time goes monotonically
524
- Time.at(start_time_epoch(pid))
524
+ _ste = start_time_epoch(pid)
525
+ return nil unless _ste
526
+ Time.at(_ste)
525
527
  end
526
528
 
527
529
  ##
@@ -22,6 +22,7 @@ module LinuxStat
22
22
  #
23
23
  # If the info isn't available, it will return an empty Hash.
24
24
  def any?
25
+ return nil unless File.readable?('/proc/swaps'.freeze)
25
26
  !!IO.foreach('/proc/swaps'.freeze).first(2)[1]
26
27
  end
27
28
 
@@ -1,3 +1,3 @@
1
1
  module LinuxStat
2
- VERSION ||= "2.2.1"
2
+ VERSION = "2.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linux_stat
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sourav Goswami
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-12 00:00:00.000000000 Z
11
+ date: 2021-08-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Linux only, efficient linux system utilization reporting and system monitoring
14
14
  gem
@@ -31,8 +31,10 @@ files:
31
31
  - bin/console
32
32
  - bin/setup
33
33
  - exe/linuxstat.rb
34
+ - ext/fs_stat/disk_stat.h
34
35
  - ext/fs_stat/extconf.rb
35
36
  - ext/fs_stat/fs_stat.c
37
+ - ext/fs_stat/sector_size.h
36
38
  - ext/nproc/extconf.rb
37
39
  - ext/nproc/nproc.c
38
40
  - ext/procfs/extconf.rb
@@ -85,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
87
  - !ruby/object:Gem::Version
86
88
  version: '0'
87
89
  requirements: []
88
- rubygems_version: 3.2.7
90
+ rubygems_version: 3.2.21
89
91
  signing_key:
90
92
  specification_version: 4
91
93
  summary: Efficient linux system reporting gem