linux_stat 2.3.0 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2caab049f35d0dcad515eff80928136273b729219cc70a7c07f6823282f0a39c
4
- data.tar.gz: eb8a5a546f795116e825bd704da6380a81b197b61ffd4125d0dc2c267e6ea808
3
+ metadata.gz: c9155ed8b1f6161a8bafcb9fbd9f1a1d9f70b018ca62aabf49ad1c7439030ee2
4
+ data.tar.gz: 22e52732cd8c8a2fca1f34ca9ece06178373c800ddbc200c42d1a61d49c29995
5
5
  SHA512:
6
- metadata.gz: cd77811626f97fe248885dc2686447e584801d607fb2147200852ff3debc36e0fe37fe8a139a71fe67398ac3fde074c821b68428ccbb6a9cf4126385bcfa23df
7
- data.tar.gz: 89a2646c48f68d48e02bc5593bb4f616090c5e1c30045a05eb39a3d0b1c41412853ee09c600b11d4f1e59544bf49e5409fb1d2906d666290989683a707142358
6
+ metadata.gz: d1f781908039e1946676f8a1502321b530538aef6d303976b07930c6d8933e7a45ca671e1aa3438fc774caa68c1b939f1ee12f47a5a6399523700b46cfb0c9f5
7
+ data.tar.gz: cd51272b3c145c9a57a5b3ae444c21119430106436e29c843420269cbad47044fdc4e3836bf86e61404c6df20f462164dc673ec5e6d76b4acacfcc37effc61c8
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
@@ -11,7 +11,7 @@ end
11
11
  T_FMT = '%d'.freeze
12
12
 
13
13
  # Check the number of iterations
14
- iterations = (ARGV.find { |x| x.to_i.to_s == x } || 1).to_i
14
+ iterations = (ARGV.find { |x| LinuxStat::Misc.integer?(x) } || 1).to_i
15
15
 
16
16
  Integer.class_exec do
17
17
  define_method(:clamp) { |min, max|
@@ -73,14 +73,14 @@ conflicting.each do |x, y, z|
73
73
  rev = ARGV.reverse
74
74
 
75
75
  if rev.index { |_x| _x[y] } < rev.index { |_x| _x[z] }
76
- hash.merge!(o1 => true)
76
+ hash.store(o1, true)
77
77
  else
78
- hash.merge!(o2 => true)
78
+ hash.store(o2, true)
79
79
  end
80
80
  elsif m1
81
- hash.merge!(o1 => true)
81
+ hash.store(o1, true)
82
82
  elsif m2
83
- hash.merge!(o2 => true)
83
+ hash.store(o2, true)
84
84
  end
85
85
  end
86
86
 
@@ -266,6 +266,6 @@ if PRINT_TIME
266
266
  ).*(1_000_000)
267
267
 
268
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}ms"
270
- puts "Total CPU Time: #{T_FMT % total_cpu_t}ms"
269
+ puts "Total Real Time: #{T_FMT % total_real_t}\u03BCs"
270
+ puts "Total CPU Time: #{T_FMT % total_cpu_t}\u03BCs"
271
271
  end
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'linux_stat/misc/integer'
@@ -0,0 +1,63 @@
1
+ /*
2
+ Validates if a String is integer or not.
3
+
4
+ Conditions:
5
+ - The String can start with - (negative)
6
+ - If the Argument is a BigInt or Integer, or anything else, return false
7
+ - The String cannot have anything other than 0 to 9
8
+ - The String can have leading zeroes and negative sign:
9
+ Example 1: "-00999" which translates to Ruby's -999 (decimal)
10
+ Example 2: "000999" translates to 999
11
+ - If it fails to determine, it returns nil instead of false
12
+ - It doesn't raise any error. Handing nil is enough to indicate that it failed.
13
+ */
14
+
15
+ #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
16
+ #pragma GCC optimize ("O3")
17
+ #pragma GCC diagnostic warning "-Wall"
18
+ #elif defined(__clang__)
19
+ #pragma clang optimize on
20
+ #pragma clang diagnostic warning "-Wall"
21
+ #elif defined(__INTEL_COMPILER)
22
+ #pragma intel optimization_level 3
23
+ #endif
24
+
25
+ #include <limits.h>
26
+ #include "ruby.h"
27
+
28
+ VALUE isNumber(volatile VALUE obj, volatile VALUE val) {
29
+ // But we don't expect anything other than String though as Argument.
30
+ // Note that raising ArgumentError or any kind of Error shouldn't be done here
31
+ // Otherwise Integer(n) is the best method in Ruby.
32
+ if (!RB_TYPE_P(val, T_STRING))
33
+ return Qnil ;
34
+
35
+ char *str = StringValuePtr(val) ;
36
+ char ch = str[0] ;
37
+
38
+ // If the string is empty, return false
39
+ if (!ch) return Qfalse ;
40
+
41
+ unsigned char i = ch == '-' ? 1 : 0 ;
42
+ if (!str[i]) return Qfalse ;
43
+
44
+ unsigned char max = UCHAR_MAX ;
45
+
46
+ # pragma GCC unroll 4
47
+ while((ch = str[i++])) {
48
+ if (ch < 48 || ch > 57)
49
+ return Qfalse ;
50
+
51
+ if (i == max)
52
+ return Qnil ;
53
+ }
54
+
55
+ return Qtrue ;
56
+ }
57
+
58
+ void Init_integer() {
59
+ VALUE linuxStat = rb_define_module("LinuxStat") ;
60
+ VALUE misc = rb_define_module_under(linuxStat, "Misc") ;
61
+
62
+ rb_define_module_function(misc, "integer?", isNumber, 1) ;
63
+ }
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
@@ -17,6 +17,29 @@ static VALUE ps_state(volatile VALUE obj, volatile VALUE pid) {
17
17
  return rb_str_new_cstr(_s) ;
18
18
  }
19
19
 
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
+
20
43
  static VALUE ps_times(volatile VALUE obj, volatile VALUE pid) {
21
44
  int _pid = FIX2INT(pid) ;
22
45
  if (_pid < 0) return Qnil ;
@@ -117,3 +140,46 @@ static VALUE ps_stat(volatile VALUE obj, volatile 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
+ }
@@ -308,7 +308,7 @@ module LinuxStat
308
308
  ret[:charge_full_wh] = c_f_wh if c_f_wh
309
309
  ret[:charge_percentage] = charge_percentage if charge_percentage
310
310
 
311
- h.merge!(File.split(x)[-1].to_sym => ret)
311
+ h.store(File.split(x)[-1].to_sym, ret)
312
312
  end
313
313
  h
314
314
  end
@@ -21,24 +21,53 @@ module LinuxStat
21
21
  #
22
22
  # => {0=>84.38, 1=>100.0, 2=>50.0, 3=>87.5, 4=>87.5}
23
23
  #
24
+ # It discards any offline CPU or disabled CPU.
25
+ # For example, if your system CPU has 4 cores, and you disabled core 3, the output will be:
26
+ # LinuxStat::CPU.stat
27
+ #
28
+ # => {0=>26.67, 1=>0.0, 2=>20.0, 4=>20.0}
29
+ #
24
30
  # If the information is not available, it will return an empty Hash
25
31
  def stat(sleep = ticks_to_ms_t5)
26
32
  return {} unless stat?
27
33
 
28
- data = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
34
+ data = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }
35
+ cpu_names1 = []
36
+ data.map! { |x|
37
+ splitted = x.split
38
+ name = splitted.shift[/\d*$/]
39
+ cpu_names1.push(name.empty? ? 0 : name.to_i + 1)
40
+ splitted.map!(&:to_f)
41
+ }
42
+
29
43
  sleep(sleep)
30
- data2 = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }.map! { |x| x.split.map!(&:to_f) }
44
+ data2 = IO.readlines('/proc/stat'.freeze).select { |x| x[/^cpu\d*/] }
45
+
46
+ cpu_names2 = []
47
+ data2.map! { |x|
48
+ splitted = x.split
49
+ name = splitted.shift[/\d*$/]
50
+ cpu_names2.push(name.empty? ? 0 : name.to_i + 1)
51
+ splitted.map!(&:to_f)
52
+ }
31
53
 
32
54
  # On devices like android, the core count can change anytime (hotplugging).
33
55
  # I had crashes on Termux.
34
56
  # So better just count the min number of CPU and iterate over that
35
57
  # If data.length is smaller than data2.length, we don't have enough data to compare.
36
- dl, d2l = data.length, data2.length
37
- min = dl > d2l ? d2l : dl
58
+ dl, d2l = cpu_names1.length, cpu_names2.length
59
+ if dl > d2l
60
+ min = d2l
61
+ cpu_cores = cpu_names2
62
+ else
63
+ min = dl
64
+ cpu_cores = cpu_names1
65
+ end
38
66
 
39
67
  min.times.reduce({}) do |h, x|
40
- user, nice, sys, idle, iowait, irq, softirq, steal = *data[x].drop(1)
41
- user2, nice2, sys2, idle2, iowait2, irq2, softirq2, steal2 = *data2[x].drop(1)
68
+ cpu_core = cpu_cores[x]
69
+ user, nice, sys, idle, iowait, irq, softirq, steal = *data[x]
70
+ user2, nice2, sys2, idle2, iowait2, irq2, softirq2, steal2 = *data2[x]
42
71
 
43
72
  idle_then, idle_now = idle + iowait, idle2 + iowait2
44
73
  totald = idle_now.+(user2 + nice2 + sys2 + irq2 + softirq2 + steal2) - idle_then.+(user + nice + sys + irq + softirq + steal)
@@ -46,7 +75,8 @@ module LinuxStat
46
75
  res = totald.-(idle_now - idle_then).fdiv(totald).abs.*(100)
47
76
  res = res.nan? ? 0.0 : res > 100 ? 100.0 : res.round(2)
48
77
 
49
- h.merge!( x => res )
78
+ h.store(cpu_core, res)
79
+ h
50
80
  end
51
81
  end
52
82
 
@@ -203,12 +233,16 @@ module LinuxStat
203
233
 
204
234
  h = {}
205
235
  @@cur_f.each { |id, file|
206
- h.merge!(id => IO.read(file).to_i) if File.readable?(file)
236
+ h.store(id, IO.read(file).to_i) if File.readable?(file)
207
237
  }
208
238
 
209
239
  h
210
240
  end
211
241
 
242
+ def times
243
+ LinuxStat::ProcFS.cpu_times
244
+ end
245
+
212
246
  ##
213
247
  # Returns a Hash with max core frequencies corresponding to the CPUs.
214
248
  #
@@ -225,7 +259,7 @@ module LinuxStat
225
259
 
226
260
  h = {}
227
261
  @@min_f.each { |id, file|
228
- h.merge!(id => IO.read(file).to_i) if File.readable?(file)
262
+ h.store(id, IO.read(file).to_i) if File.readable?(file)
229
263
  }
230
264
 
231
265
  h
@@ -247,7 +281,7 @@ module LinuxStat
247
281
 
248
282
  h = {}
249
283
  @@min_f.each { |id, file|
250
- h.merge!(id => IO.read(file).to_i) if File.readable?(file)
284
+ h.store(id, IO.read(file).to_i) if File.readable?(file)
251
285
  }
252
286
 
253
287
  h
@@ -271,7 +305,7 @@ module LinuxStat
271
305
 
272
306
  h = {}
273
307
  @@scaling_g.each { |id, file|
274
- h.merge!(id => IO.read(file).tap(&:strip!)) if File.readable?(file)
308
+ h.store(id, IO.read(file).tap(&:strip!)) if File.readable?(file)
275
309
  }
276
310
 
277
311
  h
@@ -293,14 +327,91 @@ module LinuxStat
293
327
 
294
328
  h = {}
295
329
  @@scaling_av_g.each { |id, file|
296
- h.merge!(id => IO.read(file).split.each(&:strip!)) if File.readable?(file)
330
+ h.store(id, IO.read(file).split.each(&:strip!)) if File.readable?(file)
297
331
  }
298
332
 
299
333
  h
300
334
  end
301
335
 
336
+ ##
337
+ # Returns the number of physical cores on the system.
338
+ #
339
+ # The return value is an Array of Integers. Each number denoting the physical processor number.
340
+ # You can later use this to schedule tasks or something else (not provided by LinuxStat).
341
+ #
342
+ # However, if the information isn't available on /sys/devices/system/cpu[0-9]*/topology/thread_siblings_list, it will return an empty Array.
343
+ def physical_core_list
344
+ physical_cores = []
345
+ hyperthreaded = {}
346
+
347
+ return [] unless File.readable?('/sys/devices/system/cpu/'.freeze)
348
+ entries = Dir.entries('/sys/devices/system/cpu/'.freeze)
349
+ entries.delete(?..freeze)
350
+ entries.delete('..'.freeze)
351
+
352
+ entries.each do |x|
353
+ if x[0..2] == 'cpu'.freeze && LinuxStat::Misc.integer?(x[3..-1])
354
+ file = "/sys/devices/system/cpu/#{x}/topology/thread_siblings_list"
355
+ next unless File.readable?(file)
356
+
357
+ data = IO.read(file)
358
+ data.strip!
359
+
360
+ val = data.split(?,.freeze).map(&:to_i)
361
+ val.shift
362
+
363
+ # Add items has for fast lookup.
364
+ # This hash includes all hyper threaded cores that doesn't map to anything.
365
+ # But this hash has the purpose to look up for items and not include in the list of physical_cores
366
+ # This is just an array, but can look for keys in O(1), so it's faster than ary.find() { ... }.
367
+ val.each { |x| hyperthreaded.store(x, nil) }
368
+
369
+ key = x[3..-1].to_i
370
+ physical_cores << key unless hyperthreaded.key?(key)
371
+ end
372
+ end
373
+
374
+ physical_cores
375
+ end
376
+
377
+ ##
378
+ # Returns the number of physical cores on the system.
379
+ #
380
+ # The return value is an Array of Integers. Each number denoting the hyperthreaded processor number.
381
+ # You can later use this to schedule tasks or something else (not provided by LinuxStat).
382
+ #
383
+ # However, if the information isn't available on /sys/devices/system/cpu[0-9]*/topology/thread_siblings_list, it will return an empty Array.
384
+ def hyperthreaded_core_list
385
+ hyperthreaded = {}
386
+
387
+ return [] unless File.readable?('/sys/devices/system/cpu/'.freeze)
388
+ entries = Dir.entries('/sys/devices/system/cpu/'.freeze)
389
+ entries.delete(?..freeze)
390
+ entries.delete('..'.freeze)
391
+
392
+ entries.each do |x|
393
+ if x[0..2] == 'cpu'.freeze && LinuxStat::Misc.integer?(x[3..-1])
394
+ file = "/sys/devices/system/cpu/#{x}/topology/thread_siblings_list"
395
+ next unless File.readable?(file)
396
+
397
+ data = IO.read(file)
398
+ data.strip!
399
+
400
+ val = data.split(?,.freeze).map(&:to_i)
401
+ val.shift
402
+
403
+ # Add items has for fast lookup to get rid of duplicate items.
404
+ val.each { |x| hyperthreaded.store(x, nil) unless hyperthreaded.key?(x) }
405
+ end
406
+ end
407
+
408
+ hyperthreaded.keys
409
+ end
410
+
302
411
  alias usages stat
303
412
  alias usage total_usage
413
+ alias physical_cores physical_core_list
414
+ alias hyperthreaded_cores hyperthreaded_core_list
304
415
 
305
416
  private
306
417
  def cpuinfo
@@ -58,7 +58,7 @@ module LinuxStat
58
58
  def tmpfs
59
59
  ret = {}
60
60
  mounts.each { |x|
61
- ret.merge!({x.split[1] => x}) if x.start_with?('tmpfs '.freeze)
61
+ ret.store(x.split[1], x) if x.start_with?('tmpfs '.freeze)
62
62
  }
63
63
  ret
64
64
  end
@@ -115,7 +115,7 @@ module LinuxStat
115
115
 
116
116
  unless x.empty?
117
117
  _x = x.split
118
- m.merge!(_x[0] => _x[1])
118
+ m.store(_x[0], _x[1])
119
119
  end
120
120
  end
121
121
  m
@@ -146,7 +146,7 @@ module LinuxStat
146
146
  _x = x.split
147
147
  total, free, available, used = fs_info(_x[1])
148
148
 
149
- m.merge!(_x[0] => {
149
+ m.store(_x[0], {
150
150
  mountpoint: _x[1],
151
151
 
152
152
  total: total,
@@ -120,8 +120,8 @@ module LinuxStat
120
120
 
121
121
  r.each_with_index { |x, i|
122
122
  downcased = x.downcase
123
- h.merge!(:r => i) if downcased.start_with?('receive'.freeze)
124
- h.merge!(:t => i) if downcased.start_with?('transmit'.freeze)
123
+ h.store(:r, i) if downcased.start_with?('receive'.freeze)
124
+ h.store(:t, i) if downcased.start_with?('transmit'.freeze)
125
125
  }
126
126
 
127
127
  data_0 = data.next.gsub(?|.freeze, ' %'.freeze)
data/lib/linux_stat/os.rb CHANGED
@@ -234,7 +234,8 @@ module LinuxStat
234
234
  value[0] = ''.freeze if value[0] == ?".freeze
235
235
  value[-1] = ''.freeze if value[-1] == ?".freeze
236
236
 
237
- h.merge!( key.to_sym => value )
237
+ h.store(key.to_sym, value)
238
+ h
238
239
  }
239
240
  end
240
241
  end
@@ -76,7 +76,7 @@ module LinuxStat
76
76
  kernel_driver: kernel_driver
77
77
  }
78
78
 
79
- ret.merge!(hwdata: query) unless query.empty?
79
+ ret.store(:hwdata, query) unless query.empty?
80
80
 
81
81
  ret
82
82
  }
@@ -186,14 +186,14 @@ module LinuxStat
186
186
  vendor: vendor, device: device
187
187
  }
188
188
 
189
- ret.merge!(sub_vendor: sub_vendor) if sub_vendor
190
- ret.merge!(sub_device: sub_device) if sub_device
189
+ ret.store(:sub_vendor, sub_vendor) if sub_vendor
190
+ ret.store(:sub_device, sub_device) if sub_device
191
191
 
192
- ret.merge!(kernel_driver: kernel_driver) if kernel_driver
193
- ret.merge!(revision: revision) unless revision.empty?
194
- ret.merge!(irq: irq) if irq
195
- ret.merge!(enable: enable) unless enable.nil?
196
- ret.merge!(hwdata: query) unless query.empty?
192
+ ret.store(:kernel_driver, kernel_driver) if kernel_driver
193
+ ret.store(:revision, revision) unless revision.empty?
194
+ ret.store(:irq, irq) if irq
195
+ ret.store(:enable, enable) unless enable.nil?
196
+ ret.store(:hwdata, query) unless query.empty?
197
197
 
198
198
  ret
199
199
  rescue StandardError
@@ -355,7 +355,7 @@ module LinuxStat
355
355
 
356
356
  if sub_vendor_id && sub_device_id
357
357
  sub_product = vendor.dig(1, product_id, 1, sub_vendor_id, sub_device_id)
358
- ret.merge!(sub_system: sub_product) if sub_product
358
+ ret.store(:sub_system, sub_product) if sub_product
359
359
  end
360
360
 
361
361
  ret
@@ -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,14 +26,14 @@ 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
43
33
  x = l[i]
44
34
 
45
35
  begin
46
- h.merge!( x => IO.read("/proc/#{x}/comm").strip)
36
+ h.store(x, IO.read("/proc/#{x}/comm").strip)
47
37
  rescue StandardError
48
38
  end
49
39
  end
@@ -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.store(x, cmdlines)
70
60
  rescue StandardError
71
61
  end
72
62
  end
@@ -78,14 +68,14 @@ 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
85
75
  x = l[i]
86
76
 
87
77
  begin
88
- h.merge!(x =>
78
+ h.store(x,
89
79
  case LinuxStat::ProcFS.ps_state(x)
90
80
  when ?S.freeze then :sleeping
91
81
  when ?I.freeze then :idle
@@ -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
  }
@@ -36,7 +36,7 @@ module LinuxStat
36
36
 
37
37
  if x[/^(read|write)_bytes:\s*\d*$/]
38
38
  splitted = x.split
39
- out.merge!(splitted[0].split(?:)[0].to_sym => splitted[-1].to_i)
39
+ out.store(splitted[0].split(?:)[0].to_sym, splitted[-1].to_i)
40
40
  end
41
41
  }
42
42
 
@@ -13,7 +13,8 @@ module LinuxStat
13
13
  file = IO.readlines('/proc/swaps'.freeze).drop(1)
14
14
  file.reduce({}) do |h, x|
15
15
  name, *stats = x.strip.split
16
- h.merge!(name => stats.map! { |v| v.to_i.to_s == v ? v.to_i : v.to_sym })
16
+ h.store(name, stats.map! { |v| LinuxStat::Misc.integer?(v) ? v.to_i : v.to_sym })
17
+ h
17
18
  end
18
19
  end
19
20
 
@@ -107,10 +107,10 @@ module LinuxStat
107
107
 
108
108
  h = {path: path, name: name}
109
109
 
110
- h.merge!(label: label) if label
111
- h.merge!(key => value)
112
- h.merge!(temp_crit: temp_crit) if temp_crit
113
- h.merge!(temp_crit: temp_max) if temp_max
110
+ h.store(:label, label) if label
111
+ h.store(key, value)
112
+ h.store(:temp_crit, temp_crit) if temp_crit
113
+ h.store(:temp_crit, temp_max) if temp_max
114
114
 
115
115
  ret.push(h)
116
116
  end
@@ -102,20 +102,20 @@ module LinuxStat
102
102
  vendor_id: id_vendor, product_id: id_product
103
103
  }
104
104
 
105
- ret.merge!(bus_num: bus_num.to_i) unless bus_num.empty?
106
- ret.merge!(dev_num: dev_num.to_i) unless dev_num.empty?
105
+ ret.store(:bus_num, bus_num.to_i) unless bus_num.empty?
106
+ ret.store(:dev_num, dev_num.to_i) unless dev_num.empty?
107
107
 
108
- ret.merge!(serial: serial) unless serial.empty?
108
+ ret.store(:serial, serial) unless serial.empty?
109
109
 
110
- ret.merge!(hwdata: query) unless query.empty?
111
- ret.merge!(product: product) unless product.empty?
112
- ret.merge!(manufacturer: manufacturer) unless manufacturer.empty?
110
+ ret.store(:hwdata, query) unless query.empty?
111
+ ret.store(:product, product) unless product.empty?
112
+ ret.store(:manufacturer, manufacturer) unless manufacturer.empty?
113
113
 
114
- ret.merge!(removable: is_removable) unless is_removable.nil?
115
- ret.merge!(authorized: authorized == 1)
114
+ ret.store(:removable, is_removable) unless is_removable.nil?
115
+ ret.store(:authorized, authorized == 1)
116
116
 
117
- ret.merge!(b_max_power: b_max_power) unless b_max_power.empty?
118
- ret.merge!(b_max_packet_size0: b_max_packet_size0) if b_max_packet_size0
117
+ ret.store(:b_max_power, b_max_power) unless b_max_power.empty?
118
+ ret.store(:b_max_packet_size0, b_max_packet_size0) if b_max_packet_size0
119
119
 
120
120
  ret
121
121
  rescue StandardError
@@ -25,9 +25,11 @@ module LinuxStat
25
25
  def ids
26
26
  return {} unless passwd_readable?
27
27
  passwd_splitted.reduce({}) { |h, x|
28
- h.merge!(x[0].to_sym => {
28
+ h.store(x[0].to_sym, {
29
29
  uid: x[2].to_i, gid: x[3].to_i
30
30
  })
31
+
32
+ h
31
33
  }
32
34
  end
33
35
 
@@ -42,8 +44,10 @@ module LinuxStat
42
44
  def uids
43
45
  return {} unless passwd_readable?
44
46
  passwd_splitted.reduce({}) { |h, x|
45
- h.merge!(x[0].to_sym => x[2].to_i)
47
+ h.store(x[0].to_sym, x[2].to_i)
48
+ h
46
49
  }
50
+
47
51
  end
48
52
 
49
53
  ##
@@ -59,7 +63,8 @@ module LinuxStat
59
63
  return {} unless passwd_readable?
60
64
 
61
65
  passwd_splitted.reduce({}) { |h, x|
62
- h.merge!(x[0].to_sym => x[3].to_i)
66
+ h.store(x[0].to_sym, x[3].to_i)
67
+ h
63
68
  }
64
69
  end
65
70
 
@@ -76,7 +81,8 @@ module LinuxStat
76
81
  return {} unless passwd_readable?
77
82
  passwd.reduce({}) { |h, x|
78
83
  splitted = x.split(?:)
79
- h.merge!(splitted[0].to_sym => splitted[5])
84
+ h.store(splitted[0].to_sym, splitted[5])
85
+ h
80
86
  }
81
87
  end
82
88
 
@@ -1,3 +1,3 @@
1
1
  module LinuxStat
2
- VERSION = "2.3.0"
2
+ VERSION = "2.5.2"
3
3
  end
data/lib/linux_stat.rb CHANGED
@@ -15,6 +15,7 @@
15
15
 
16
16
  # Miscellaneous Modules
17
17
  # Independed and LinuxStat's miscellaneous modules
18
+ require 'linux_stat/misc/integer'
18
19
  require 'linux_stat/prettify_bytes'
19
20
  require "linux_stat/version"
20
21
 
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.3.0
4
+ version: 2.5.2
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-06-07 00:00:00.000000000 Z
11
+ date: 2021-10-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Linux only, efficient linux system utilization reporting and system monitoring
14
14
  gem
@@ -18,6 +18,7 @@ executables:
18
18
  - linuxstat.rb
19
19
  extensions:
20
20
  - ext/fs_stat/extconf.rb
21
+ - ext/misc/integer/extconf.rb
21
22
  - ext/nproc/extconf.rb
22
23
  - ext/procfs/extconf.rb
23
24
  - ext/sysconf/extconf.rb
@@ -35,6 +36,8 @@ files:
35
36
  - ext/fs_stat/extconf.rb
36
37
  - ext/fs_stat/fs_stat.c
37
38
  - ext/fs_stat/sector_size.h
39
+ - ext/misc/integer/extconf.rb
40
+ - ext/misc/integer/integer?.c
38
41
  - ext/nproc/extconf.rb
39
42
  - ext/nproc/nproc.c
40
43
  - ext/procfs/extconf.rb
@@ -87,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
90
  - !ruby/object:Gem::Version
88
91
  version: '0'
89
92
  requirements: []
90
- rubygems_version: 3.2.18
93
+ rubygems_version: 3.2.29
91
94
  signing_key:
92
95
  specification_version: 4
93
96
  summary: Efficient linux system reporting gem