linux_stat 2.0.1 → 2.2.1

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.
data/exe/linuxstat.rb CHANGED
@@ -150,9 +150,9 @@ execute.sort.each do |c|
150
150
  disp_meth = "#{meth}"
151
151
  disp_meth.concat(arg ? "(#{param})" : "(#{param})")
152
152
 
153
- time = Time.now
153
+ time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
154
154
  ret = arg ? e.send(meth, arg) : e.send(meth)
155
- time2 = Time.now
155
+ time2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
156
156
  time = time2.-(time).*(1_000_000).round(3)
157
157
 
158
158
  v = ret.inspect
data/ext/procfs/procfs.c CHANGED
@@ -38,5 +38,6 @@ int Init_procfs() {
38
38
 
39
39
  // stat
40
40
  rb_define_module_function(_procfs, "ps_state", ps_state, 1) ;
41
+ rb_define_module_function(_procfs, "ps_times", ps_times, 1) ;
41
42
  rb_define_module_function(_procfs, "ps_stat", ps_stat, 1) ;
42
43
  }
data/ext/procfs/stat.h CHANGED
@@ -1,6 +1,9 @@
1
1
  VALUE ps_state(VALUE obj, VALUE pid) {
2
+ int _pid = FIX2INT(pid) ;
3
+ if (_pid < 0) return rb_str_new_cstr("") ;
4
+
2
5
  char _path[22] ;
3
- sprintf(_path, "/proc/%lu/stat", FIX2UINT(pid)) ;
6
+ sprintf(_path, "/proc/%d/stat", _pid) ;
4
7
 
5
8
  FILE *f = fopen(_path, "r") ;
6
9
  if (!f) return rb_str_new_cstr("") ;
@@ -14,9 +17,33 @@ VALUE ps_state(VALUE obj, VALUE pid) {
14
17
  return rb_str_new_cstr(_s) ;
15
18
  }
16
19
 
20
+ VALUE ps_times(VALUE obj, VALUE pid) {
21
+ int _pid = FIX2INT(pid) ;
22
+ if (_pid < 0) return Qnil ;
23
+
24
+ char _path[22] ;
25
+ sprintf(_path, "/proc/%d/stat", _pid) ;
26
+
27
+ FILE *f = fopen(_path, "r") ;
28
+ if (!f) return Qnil ;
29
+
30
+ unsigned long utime, stime ;
31
+
32
+ char status = fscanf(f, "%*llu (%*[^)]%*[)] %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %lu %lu", &utime, &stime) ;
33
+ fclose(f) ;
34
+
35
+ if (status != 2) return Qnil ;
36
+ double total_time = (utime + stime) / (float)sysconf(_SC_CLK_TCK);
37
+
38
+ return DBL2NUM(total_time) ;
39
+ }
40
+
17
41
  VALUE ps_stat(VALUE obj, VALUE pid) {
42
+ int _pid = FIX2INT(pid) ;
43
+ if (_pid < 0) return rb_str_new_cstr("") ;
44
+
18
45
  char _path[22] ;
19
- sprintf(_path, "/proc/%lu/stat", FIX2UINT(pid)) ;
46
+ sprintf(_path, "/proc/%d/stat", _pid) ;
20
47
 
21
48
  FILE *f = fopen(_path, "r") ;
22
49
 
data/ext/procfs/statm.h CHANGED
@@ -1,13 +1,15 @@
1
1
  #define PAGESIZE sysconf(_SC_PAGESIZE)
2
2
 
3
3
  VALUE statm(VALUE obj, VALUE pid) {
4
- char _path[22] ;
5
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
4
+ VALUE hash = rb_hash_new() ;
6
5
 
7
- FILE *f = fopen(_path, "r") ;
6
+ int _pid = FIX2INT(pid) ;
7
+ if (_pid < 0) return hash ;
8
8
 
9
- VALUE hash = rb_hash_new() ;
9
+ char _path[22] ;
10
+ sprintf(_path, "/proc/%d/statm", _pid) ;
10
11
 
12
+ FILE *f = fopen(_path, "r") ;
11
13
  if (!f) return hash ;
12
14
 
13
15
  unsigned int _virtual, resident, shared ;
@@ -33,13 +35,15 @@ VALUE statm(VALUE obj, VALUE pid) {
33
35
  }
34
36
 
35
37
  VALUE statm_virtual(VALUE obj, VALUE pid) {
38
+ int _pid = FIX2INT(pid) ;
39
+ if (_pid < 0) return Qnil ;
40
+
36
41
  char _path[22] ;
37
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
42
+ sprintf(_path, "/proc/%d/statm", _pid) ;
38
43
 
39
44
  FILE *f = fopen(_path, "r") ;
40
- VALUE hash = rb_hash_new() ;
45
+ if (!f) return Qnil ;
41
46
 
42
- if (!f) return hash ;
43
47
  unsigned int _virtual ;
44
48
  char status = fscanf(f, "%u", &_virtual) ;
45
49
  fclose(f) ;
@@ -49,13 +53,15 @@ VALUE statm_virtual(VALUE obj, VALUE pid) {
49
53
  }
50
54
 
51
55
  VALUE statm_resident(VALUE obj, VALUE pid) {
56
+ int _pid = FIX2INT(pid) ;
57
+ if (_pid < 0) return Qnil ;
58
+
52
59
  char _path[22] ;
53
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
60
+ sprintf(_path, "/proc/%d/statm", _pid) ;
54
61
 
55
62
  FILE *f = fopen(_path, "r") ;
56
- VALUE hash = rb_hash_new() ;
63
+ if (!f) return Qnil ;
57
64
 
58
- if (!f) return hash ;
59
65
  unsigned int resident ;
60
66
  char status = fscanf(f, "%*u %u", &resident) ;
61
67
  fclose(f) ;
@@ -65,13 +71,15 @@ VALUE statm_resident(VALUE obj, VALUE pid) {
65
71
  }
66
72
 
67
73
  VALUE statm_shared(VALUE obj, VALUE pid) {
74
+ int _pid = FIX2INT(pid) ;
75
+ if (_pid < 0) return Qnil ;
76
+
68
77
  char _path[22] ;
69
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
78
+ sprintf(_path, "/proc/%d/statm", _pid) ;
70
79
 
71
80
  FILE *f = fopen(_path, "r") ;
72
- VALUE hash = rb_hash_new() ;
81
+ if (!f) return Qnil ;
73
82
 
74
- if (!f) return hash ;
75
83
  unsigned int shared ;
76
84
  char status = fscanf(f, "%*u %*u %u", &shared) ;
77
85
  fclose(f) ;
@@ -81,11 +89,13 @@ VALUE statm_shared(VALUE obj, VALUE pid) {
81
89
  }
82
90
 
83
91
  VALUE statm_memory(VALUE obj, VALUE pid) {
92
+ int _pid = FIX2INT(pid) ;
93
+ if (_pid < 0) return Qnil ;
94
+
84
95
  char _path[22] ;
85
- sprintf(_path, "/proc/%lu/statm", FIX2UINT(pid)) ;
96
+ sprintf(_path, "/proc/%d/statm", _pid) ;
86
97
 
87
98
  FILE *f = fopen(_path, "r") ;
88
-
89
99
  if (!f) return Qnil ;
90
100
 
91
101
  unsigned int resident, shared ;
@@ -105,11 +105,19 @@ module LinuxStat
105
105
  #
106
106
  # If the battery is not present or the information is not available, it will return nil.
107
107
  def charge
108
- @@charge_now_file ||= File.join(PATH, 'charge_now')
109
- @@charge_full_file ||= File.join(PATH, 'charge_full')
108
+ @@charge_now_file ||= if File.readable?(File.join(PATH, 'charge_now'))
109
+ File.join(PATH, 'charge_now').freeze
110
+ elsif File.readable?(File.join(PATH, 'energy_now'))
111
+ File.join(PATH, 'energy_now').freeze
112
+ end
113
+
114
+ @@charge_full_file ||= if File.readable?(File.join(PATH, 'charge_full'))
115
+ File.join(PATH, 'charge_full').freeze
116
+ elsif File.readable?(File.join(PATH, 'energy_full'))
117
+ File.join(PATH, 'energy_full').freeze
118
+ end
110
119
 
111
- @@charge_now_readable ||= File.readable?(@@charge_now_file) && File.readable?(@@charge_full_file)
112
- return nil unless @@charge_now_readable
120
+ return nil unless @@charge_now_file && @@charge_full_file
113
121
 
114
122
  charge_now = IO.read(@@charge_now_file).to_i
115
123
  charge_full = IO.read(@@charge_full_file).to_i
@@ -178,7 +186,14 @@ module LinuxStat
178
186
  # For example, a sample output can be like this (taken on a test system):
179
187
  #
180
188
  # LinuxStat::Battery.devices_stat
181
- # => {:AC=>{:type=>"Mains", :online=>1}, :BAT0=>{:model=>"DELL CYMGM77", :manufacturer=>"Samsung SDI", :type=>"Battery", :status=>"Full", :capacity=>100, :voltage_min_design=>11.4, :charge_full_design=>3.684, :charge_full_design_wh=>42.0, :voltage_now=>12.558, :charge_now=>2.087, :charge_now_wh=>26.21, :charge_full_wh=>23.79, :charge_percentage=>100.0}, :hidpp_battery_0=>{:model=>"Wireless Keyboard", :manufacturer=>"Logitech", :type=>"Battery", :status=>"Discharging", :online=>1}}
189
+ # => {:AC=>{:type=>"Mains", :online=>1},
190
+ # :BAT0=>{:model=>"DELL CYMGM77", :manufacturer=>"Samsung SDI",
191
+ # :type=>"Battery", :status=>"Full", :capacity=>100, :voltage_min_design=>11.4,
192
+ # :charge_full_design=>3.684, :charge_full_design_wh=>42.0,
193
+ # :voltage_now=>12.558, :charge_now=>2.087, :charge_now_wh=>26.21,
194
+ # :charge_full_wh=>23.79, :charge_percentage=>100.0},
195
+ # :hidpp_battery_0=>{:model=>"Wireless Keyboard", :manufacturer=>"Logitech",
196
+ # :type=>"Battery", :status=>"Discharging", :online=>1}}
182
197
  #
183
198
  # If you need info about lots of batteries, use this method.
184
199
  # If the informations are not available, it will return empty Hash for each devices.
@@ -208,7 +223,16 @@ module LinuxStat
208
223
 
209
224
  # charge now
210
225
  cn_f = File.join(x, 'charge_now'.freeze).freeze
211
- charge_now = File.readable?(cn_f) ? IO.read(cn_f).to_i.fdiv(1_000_000) : nil
226
+ charge_now = if File.readable?(cn_f)
227
+ IO.read(cn_f).to_i.fdiv(1_000_000)
228
+ else
229
+ en_f = File.join(x, 'energy_now'.freeze)
230
+ if File.readable?(en_f)
231
+ IO.read(en_f) .to_i.fdiv(1_000_000)
232
+ else
233
+ nil
234
+ end
235
+ end
212
236
 
213
237
  # voltage min design
214
238
  vmd_f = File.join(x, 'voltage_min_design'.freeze).freeze
@@ -220,7 +244,16 @@ module LinuxStat
220
244
 
221
245
  # charge full
222
246
  cf_f = File.join(x, 'charge_full'.freeze).freeze
223
- charge_full = File.readable?(cf_f) ? IO.read(cf_f).to_i.fdiv(1_000_000) : nil
247
+ charge_full = if File.readable?(cf_f)
248
+ IO.read(cf_f).to_i.fdiv(1_000_000)
249
+ else
250
+ ef_f = File.join(x, 'energy_full'.freeze)
251
+ if File.readable?(ef_f)
252
+ IO.read(ef_f).to_i.fdiv(1_000_000)
253
+ else
254
+ nil
255
+ end
256
+ end
224
257
 
225
258
  # status
226
259
  s_f = File.join(x, 'status'.freeze).freeze
data/lib/linux_stat/os.rb CHANGED
@@ -7,7 +7,11 @@ module LinuxStat
7
7
  # Reads /etc/os-release and returns a Hash. For example:
8
8
  # LinuxStat::OS.os_release
9
9
  #
10
- # => {:NAME=>"Arch Linux", :PRETTY_NAME=>"Arch Linux", :ID=>"arch", :BUILD_ID=>"rolling", :ANSI_COLOR=>"38;2;23;147;209", :HOME_URL=>"https://www.archlinux.org/", :DOCUMENTATION_URL=>"https://wiki.archlinux.org/", :SUPPORT_URL=>"https://bbs.archlinux.org/", :BUG_REPORT_URL=>"https://bugs.archlinux.org/", :LOGO=>"archlinux"}
10
+ # => {:NAME=>"Arch Linux", :PRETTY_NAME=>"Arch Linux", :ID=>"arch", :BUILD_ID=>"rolling",
11
+ # :ANSI_COLOR=>"38;2;23;147;209", :HOME_URL=>"https://www.archlinux.org/",
12
+ # :DOCUMENTATION_URL=>"https://wiki.archlinux.org/",
13
+ # :SUPPORT_URL=>"https://bbs.archlinux.org/", :BUG_REPORT_URL=>"https://bugs.archlinux.org/",
14
+ # :LOGO=>"archlinux"}
11
15
  #
12
16
  # If the info isn't available, it will return an empty Hash.
13
17
  #
@@ -127,7 +131,7 @@ module LinuxStat
127
131
  #
128
132
  # The return type is strictly Integer and doesn't fail.
129
133
  def bits
130
- @@bits ||= if RbConfig::CONFIG['host_cpu'].end_with?('64') || RUBY_PLATFORM.end_with?('64') || machine.end_with?('64')
134
+ @@bits ||= if machine.end_with?('64') || RbConfig::CONFIG['host_cpu'].end_with?('64') || RUBY_PLATFORM.end_with?('64')
131
135
  64
132
136
  else
133
137
  32
@@ -138,7 +142,7 @@ module LinuxStat
138
142
  # Reads /proc/uptime and returns the system uptime:
139
143
  # LinuxStat::OS.uptime
140
144
  #
141
- # => {:hour=>10, :minute=>34, :second=>12.59}
145
+ # => {:hour=>16, :minute=>10, :second=>11, :jiffy=>20}
142
146
  #
143
147
  # Using uptime is 10x slower than using uptime_i
144
148
  #
@@ -151,12 +155,14 @@ module LinuxStat
151
155
 
152
156
  h = uptime_i / 3600
153
157
  m = uptime_i % 3600 / 60
154
- s = _uptime.%(3600).%(60).round(2)
158
+ s = uptime_i.%(60)
159
+ j = _uptime.-(uptime_i) * 100
155
160
 
156
161
  {
157
162
  hour: h,
158
163
  minute: m,
159
- second: s
164
+ second: s,
165
+ jiffy: j.to_i
160
166
  }
161
167
  end
162
168
 
@@ -283,7 +283,7 @@ module LinuxStat
283
283
  uptime = LS::ProcFS.uptime_f
284
284
  return {} unless uptime && !stat.empty?
285
285
 
286
- utime, stime, starttime = *stat.values_at(11, 12, 19).map(&:to_f)
286
+ utime, stime, starttime = *stat.values_at(10, 11, 18).map(&:to_f)
287
287
  uptime *= ticks
288
288
 
289
289
  total_time = utime + stime
@@ -295,14 +295,14 @@ module LinuxStat
295
295
  uptime = LS::ProcFS.uptime_f
296
296
  return {} unless uptime && !stat.empty?
297
297
 
298
- utime2, stime2, starttime2 = *stat.values_at(11, 12, 19).map(&:to_f)
298
+ utime2, stime2, starttime2 = *stat.values_at(10, 11, 18).map(&:to_f)
299
299
  uptime *= ticks
300
300
 
301
301
  total_time2 = utime2 + stime2
302
302
  idle2 = uptime - starttime2 - total_time2
303
303
 
304
304
  totald = idle2.+(total_time2).-(idle1 + total_time)
305
- cpu_u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count)
305
+ cpu_u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(LinuxStat::CPU.count)
306
306
 
307
307
  {
308
308
  cpu_usage: cpu_u > 100 ? 100.0 : cpu_u.round(2),
@@ -338,32 +338,10 @@ module LinuxStat
338
338
  #
339
339
  # This method is more efficient than running LinuxStat::ProcessInfo.cpu_stat()
340
340
  def cpu_usage(pid: $$, sleep: ticks_to_ms_t5)
341
- ticks = get_ticks
342
- stat = LinuxStat::ProcFS.ps_stat(pid)
343
- uptime = LS::ProcFS.uptime_f
344
- return nil unless uptime && !stat.empty?
345
-
346
- utime, stime, starttime = *stat.values_at(10, 11, 18).map(&:to_f)
347
- uptime *= ticks
348
-
349
- total_time = utime + stime
350
- idle1 = uptime - starttime - total_time
351
-
352
- sleep(sleep)
353
-
354
- stat = LinuxStat::ProcFS.ps_stat(pid)
355
- uptime = LS::ProcFS.uptime_f
356
- return nil unless uptime && !stat.empty?
357
-
358
- utime2, stime2, starttime2 = *stat.values_at(10, 11, 18).map(&:to_f)
359
- uptime *= ticks
360
-
361
- total_time2 = utime2 + stime2
362
- idle2 = uptime - starttime2 - total_time2
341
+ u = cpu_usage_thread(pid, sleep)
342
+ return nil unless u
363
343
 
364
- totald = idle2.+(total_time2).-(idle1 + total_time)
365
-
366
- u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(cpu_count)
344
+ u /= LinuxStat::CPU.count
367
345
  u > 100 ? 100.0 : u.round(2)
368
346
  end
369
347
 
@@ -390,34 +368,10 @@ module LinuxStat
390
368
  #
391
369
  # But if the info isn't available, it will return nil.
392
370
  def thread_usage(pid: $$, sleep: ticks_to_ms_t5)
393
- ticks = get_ticks
394
- stat = LinuxStat::ProcFS.ps_stat(pid)
395
- uptime = LS::ProcFS.uptime_f
396
- return nil unless uptime && !stat.empty?
397
-
398
- utime, stime, starttime = *stat.values_at(10, 11, 18).map(&:to_f)
399
- uptime *= ticks
400
-
401
- total_time = utime + stime
402
- idle1 = uptime - starttime - total_time
371
+ u = cpu_usage_thread(pid, sleep)
372
+ return nil unless u
403
373
 
404
- sleep(sleep)
405
-
406
- stat = LinuxStat::ProcFS.ps_stat(pid)
407
- uptime = LS::ProcFS.uptime_f
408
- return nil unless uptime && !stat.empty?
409
-
410
- utime2, stime2, starttime2 = *stat.values_at(10, 11, 18).map(&:to_f)
411
- uptime *= ticks
412
-
413
- total_time2 = utime2 + stime2
414
- idle2 = uptime - starttime2 - total_time2
415
-
416
- totald = idle2.+(total_time2).-(idle1 + total_time)
417
-
418
- u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)
419
-
420
- cpu_count_t100 = cpu_count * 100
374
+ cpu_count_t100 = LinuxStat::CPU.count * 100
421
375
  u > cpu_count_t100 ? cpu_count_t100 : u.round(2)
422
376
  end
423
377
 
@@ -655,6 +609,47 @@ module LinuxStat
655
609
  LinuxStat::Nproc.count_cpu_for_pid(pid)
656
610
  end
657
611
 
612
+ ##
613
+ # = def cpu_times_i(pid = $$)
614
+ #
615
+ # Shows the CPU time used by the process.
616
+ #
617
+ # The return value is a Float.
618
+ # But if the info isn't available, it will return nil.
619
+ def cpu_time(pid = $$)
620
+ LinuxStat::ProcFS.ps_times(pid)
621
+ end
622
+
623
+ ##
624
+ # = def cpu_times(pid = $$)
625
+ #
626
+ # Shows the CPU time used by the process.
627
+ #
628
+ # The return value is a Hash formatted like this:
629
+ # LS::ProcessInfo.cpu_times($$)
630
+ #
631
+ # => {:hour=>0, :minute=>39, :second=>12, :jiffy=>0.42}
632
+ #
633
+ # But if the info isn't available, it will return an empty Hash..
634
+ def cpu_times(pid = $$)
635
+ v = LinuxStat::ProcFS.ps_times(pid)
636
+ return {} unless v
637
+
638
+ v_i = v.to_i
639
+
640
+ hour = v_i / 3600
641
+ min = v_i % 3600 / 60
642
+ sec = v_i % 60
643
+ jiffy = v.-(v_i) * 100
644
+
645
+ {
646
+ hour: hour,
647
+ minute: min,
648
+ second: sec,
649
+ jiffy: jiffy.to_i
650
+ }
651
+ end
652
+
658
653
  alias count_cpu nproc
659
654
 
660
655
  private
@@ -674,8 +669,33 @@ module LinuxStat
674
669
  @@pagesize ||= LinuxStat::Sysconf.pagesize.to_i
675
670
  end
676
671
 
677
- def cpu_count
678
- @@nprocessors_conf ||= LinuxStat::CPU.count
672
+ def cpu_usage_thread(pid, delay)
673
+ ticks = get_ticks
674
+ stat = LinuxStat::ProcFS.ps_stat(pid)
675
+ uptime = LS::ProcFS.uptime_f
676
+ return nil unless uptime && !stat.empty?
677
+
678
+ utime, stime, starttime = *stat.values_at(10, 11, 18).map(&:to_f)
679
+ uptime *= ticks
680
+
681
+ total_time = utime + stime
682
+ idle1 = uptime - starttime - total_time
683
+
684
+ sleep(delay)
685
+
686
+ stat = LinuxStat::ProcFS.ps_stat(pid)
687
+ uptime = LS::ProcFS.uptime_f
688
+ return nil unless uptime && !stat.empty?
689
+
690
+ utime2, stime2, starttime2 = *stat.values_at(10, 11, 18).map(&:to_f)
691
+ uptime *= ticks
692
+
693
+ total_time2 = utime2 + stime2
694
+ idle2 = uptime - starttime2 - total_time2
695
+
696
+ totald = idle2.+(total_time2).-(idle1 + total_time)
697
+
698
+ totald.-(idle2 - idle1).fdiv(totald).abs.*(100)
679
699
  end
680
700
  end
681
701
  end