linux_stat 2.3.0 → 2.5.2

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: 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