sunburst 0.3.0 → 0.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: 9ecfac43448912f08b86571fecabeb676b11902524428b542973b83f535eeb71
4
- data.tar.gz: 85668f8a6cb4a40f48e9e6f24c43dae60cf07b68a9ab1b6d4f5559b2eb8f0d71
3
+ metadata.gz: 327a6ef07e1800b7edc89af0dc6ad0696ff2aef5656c9b908b0bb274c344638b
4
+ data.tar.gz: fe11501674b83a4dc0372585ad9f0e3dcf2ab834c781ea30d81936d958f026fb
5
5
  SHA512:
6
- metadata.gz: '09483bbbc6011547a6cbc1a691363545d5c7002dbfca9c593fde20bb4083df5995e449e02d319bd65054967b164417a2cc2662cca41541c647ab745f67e776fe'
7
- data.tar.gz: 42c5ce9d7ba09046ddb22c27cb8de6ac64c64a488b0a52a3cb52357aa2d1fc3f4029e8772fa3543c6725ac5ada1258c4876564c0fb7ddd07ab2593d84d2e0463
6
+ metadata.gz: 12a106e06a0f15348d9c71db9ffcc6dd56a71541bf316a1de6e8d3bdf842966b12a437d21777705e3e7f707dba6397f54b86ca3d79a3ca81b76f4570d091d2f0
7
+ data.tar.gz: 4b840b941a94bb1be01d351e7e61e1130a1e8c59c377fad3475740a9229541ca8dd149c6b970a8aeefe53dbd96cfd1b781cb634b85cc05debf108a71cf68ff9e
data/exe/sunburst CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # Frozen_String_Literal: true
3
3
 
4
- $-v = nil
4
+ $-v = true
5
5
  STDOUT.sync = STDIN.sync = true
6
6
  require 'sunburst'
7
7
 
@@ -82,22 +82,24 @@ begin
82
82
 
83
83
  data = if progress
84
84
  if human_readable
85
- Sunburst.measure(command: command, time: time, sleep_time: 0.0001) { |exec_t, cpu_t, mem, threads, state|
86
- print "\e[2K:: "\
85
+ Sunburst.measure(command: command, time: time, sleep_time: 0.0001) { |exec_t, cpu_t, mem, threads, state, cpu_u|
86
+ print "\e[2K\r:: "\
87
87
  "Exec T: #{"%05.2f" % exec_t}s | "\
88
88
  "CPU T: #{"%05.2f" % cpu_t}s | "\
89
89
  "Mem: #{convert_bytes(mem)} | "\
90
90
  "Threads: #{threads} | "\
91
- "State: #{state}\r"
91
+ "State: #{state} | "\
92
+ "CPU U: #{cpu_u}\e[s\r\e[u"
92
93
  }
93
94
  else
94
- Sunburst.measure(command: command, time: time, sleep_time: 0.0001) { |exec_t, cpu_t, mem, threads, state|
95
- print "\e[2K:: "\
95
+ Sunburst.measure(command: command, time: time, sleep_time: 0.0001) { |exec_t, cpu_t, mem, threads, state, cpu_u|
96
+ print "\e[2K\r:: "\
96
97
  "Exec T: #{"%05.2f" % exec_t} | "\
97
98
  "CPU T: #{"%05.2f" % cpu_t} | "\
98
99
  "Mem: #{"%2d" % mem} | "\
99
100
  "Threads: #{threads} | "\
100
- "State: #{state}\r"
101
+ "State: #{state} | "\
102
+ "CPU U: #{cpu_u}\e[s\r\e[u"
101
103
  }
102
104
  end
103
105
  else
@@ -152,6 +154,13 @@ begin
152
154
  puts ":: The memory Usage Can't be Logged."
153
155
  end
154
156
 
157
+ avg_mem = data[:avg_mem]
158
+ if avg_mem
159
+ puts ":: Avg. Memory Usage: #{style}#{convert_bytes(avg_mem)}\e[0m (#{percent_mem.round(3)}% system mem)"
160
+ else
161
+ puts ":: The Average Memory Usage can't be Logged."
162
+ end
163
+
155
164
  max_mem = data[:max_memory]
156
165
  if max_mem
157
166
  percent_mem = max_mem.*(100).fdiv(Sunburst.total_ram)
@@ -178,6 +187,20 @@ begin
178
187
  puts ":: The max memory Usage can't be logged."
179
188
  end
180
189
 
190
+ avg_cpu_usage = data[:avg_cpu_usage]
191
+ if avg_cpu_usage
192
+ puts ":: Avg. CPU Usage: #{style}#{avg_cpu_usage}\e[0m"
193
+ else
194
+ puts ":: The Avg. CPU Usage Can't be Logged"
195
+ end
196
+
197
+ max_cpu_usage = data[:max_cpu_usage]
198
+ if max_cpu_usage
199
+ puts ":: Max CPU Usage: #{style}#{max_cpu_usage}\e[0m"
200
+ else
201
+ puts ":: The Max CPU Usage Can't be Logged"
202
+ end
203
+
181
204
  max_threads = data[:max_threads]
182
205
  style = +"\e[1;"
183
206
  style << if max_threads > 16
@@ -195,6 +218,8 @@ begin
195
218
  rescue Errno::ENOENT
196
219
  puts "sunburst: #{command}: command not found"
197
220
  puts ?\n, ?- * Sunburst.win_width
221
+ rescue Interrupt
222
+ puts "\n\e[2KInterrupt Received"
198
223
  rescue StandardError
199
224
  puts $!.full_message
200
225
  end
data/ext/stats/stats.c CHANGED
@@ -44,28 +44,35 @@ VALUE ps_stat(volatile VALUE obj, volatile VALUE pid) {
44
44
  int ppid, processor ;
45
45
  long unsigned utime, stime ;
46
46
  long num_threads ;
47
+ long long unsigned starttime ;
47
48
 
48
49
  char status = fscanf(
49
50
  f, "%*llu (%*[^)]%*[)] %1s "
50
51
  "%d %*d %*d %*d %*d %*u "
51
52
  "%*lu %*lu %*lu %*lu %lu %lu "
52
- "%*ld %*ld %*ld %*ld %ld",
53
- &state, &ppid, &utime, &stime, &num_threads
53
+ "%*ld %*ld %*ld %*ld %ld %*ld %ld",
54
+ &state, &ppid, &utime, &stime, &num_threads, &starttime
54
55
  ) ;
55
56
 
56
57
  fclose(f) ;
57
58
 
58
- if (status != 5) return rb_ary_new() ;
59
+ if (status != 6) return rb_ary_new() ;
59
60
 
60
- return rb_ary_new_from_args(5,
61
+ return rb_ary_new_from_args(6,
61
62
  INT2NUM(ppid),
62
63
  ULONG2NUM(utime),
63
64
  ULONG2NUM(stime),
64
65
  LONG2NUM(num_threads),
65
- rb_str_new(state, 1)
66
+ rb_str_new(state, 1),
67
+ ULL2NUM(starttime)
66
68
  ) ;
67
69
  }
68
70
 
71
+ VALUE nProcessors(volatile VALUE obj) {
72
+ int coreCount = sysconf(_SC_NPROCESSORS_CONF) ;
73
+ return (coreCount == -1) ? Qnil : INT2NUM(coreCount) ;
74
+ }
75
+
69
76
  VALUE clock_monotonic(volatile VALUE obj) {
70
77
  struct timespec tv ;
71
78
  clock_gettime(CLOCK_MONOTONIC, &tv) ;
@@ -109,4 +116,5 @@ void Init_stats() {
109
116
  rb_define_module_function(sunburst, "ps_stat", ps_stat, 1) ;
110
117
 
111
118
  rb_define_module_function(sunburst, "total_ram", totalRAM, 0) ;
119
+ rb_define_module_function(sunburst, "nprocessors", nProcessors, 0) ;
112
120
  }
@@ -10,13 +10,55 @@ module Sunburst
10
10
  stats
11
11
  end
12
12
 
13
+ def self.calculate_cpu_usage(pid, sleep_time)
14
+ uptime_file = '/proc/uptime'.freeze
15
+
16
+ unless File.readable?(uptime_file)
17
+ sleep(sleep_time)
18
+ return nil
19
+ end
20
+
21
+ ticks = Sunburst::TICKS
22
+ stat = Sunburst.ps_stat(pid)
23
+ uptime = IO.read('/proc/uptime').to_f
24
+
25
+ if stat.empty?
26
+ sleep(sleep_time)
27
+ return nil
28
+ end
29
+
30
+ utime, stime, starttime = *stat.values_at(1, 2, 5).map(&:to_f)
31
+ uptime *= ticks
32
+
33
+ total_time = utime + stime
34
+ idle1 = uptime - starttime - total_time
35
+
36
+ sleep(sleep_time)
37
+
38
+ stat = Sunburst.ps_stat(pid)
39
+ uptime = IO.read('/proc/uptime').to_f
40
+ return nil if stat.empty?
41
+
42
+ utime2, stime2, starttime2 = *stat.values_at(1, 2, 5).map(&:to_f)
43
+ uptime *= ticks
44
+
45
+ total_time2 = utime2 + stime2
46
+ idle2 = uptime - starttime2 - total_time2
47
+
48
+ totald = idle2.+(total_time2).-(idle1 + total_time)
49
+ cpu_u = totald.-(idle2 - idle1).fdiv(totald).abs.*(100)./(Sunburst.nprocessors)
50
+
51
+ cpu_u > 100 ? 100.0 : cpu_u
52
+ end
53
+
13
54
  def self.measure(command:, time: nil, sleep_time: 0.001)
14
55
  progress = block_given?
15
56
 
16
57
  r = {
17
58
  execution_time: nil, cpu_time: nil,
18
59
  memory: nil, max_threads: nil,
19
- max_memory: nil, state: nil, last_state: nil
60
+ avg_mem: nil, max_memory: nil, state: nil, last_state: nil,
61
+ avg_cpu_usage: nil, max_cpu_usage: nil
20
62
  }
21
63
 
22
64
  IO.popen(command) { |x|
@@ -29,11 +71,36 @@ module Sunburst
29
71
  Thread.new { print x.readpartial(4096) until x.eof? }
30
72
  end
31
73
 
74
+ cpu_usage = 0
75
+ max_cpu_usage = 0
76
+ cpu_usage_sum = 0
77
+ cpu_usage_measure_count = 0
78
+
79
+ Thread.new {
80
+ while true
81
+ _cpu_usage = calculate_cpu_usage(pid, 0.25)
82
+
83
+ if _cpu_usage
84
+ cpu_usage = "%05.2f%%".freeze % _cpu_usage
85
+ cpu_usage_sum += _cpu_usage
86
+ cpu_usage_measure_count += 1
87
+
88
+ max_cpu_usage = _cpu_usage if _cpu_usage > max_cpu_usage
89
+ else
90
+ cpu_usage = ?X.freeze
91
+ end
92
+
93
+ end
94
+ }
95
+
32
96
  last_mem = 0
33
97
  max_threads = 0
34
98
  max_mem = 0
35
99
  last_state = nil
36
100
 
101
+ avg_mem = 0
102
+ mem_measure_count = 0
103
+
37
104
  while true
38
105
  _last_mem = Sunburst.get_mem(pid)
39
106
 
@@ -41,6 +108,9 @@ module Sunburst
41
108
  last_mem = _last_mem
42
109
  max_mem = last_mem if max_mem < _last_mem
43
110
 
111
+ avg_mem += _last_mem
112
+ mem_measure_count += 1
113
+
44
114
  # Get stats
45
115
  stats = get_stats(pid)
46
116
  _threads = stats[3]
@@ -55,7 +125,8 @@ module Sunburst
55
125
  stats[1].+(stats[2]).fdiv(Sunburst::TICKS),
56
126
  _last_mem * Sunburst::PAGESIZE,
57
127
  _threads,
58
- last_state
128
+ last_state,
129
+ cpu_usage
59
130
  )
60
131
  end
61
132
 
@@ -84,10 +155,14 @@ module Sunburst
84
155
  r[:max_threads] = max_threads unless max_threads == 0
85
156
  r[:memory] = last_mem * Sunburst::PAGESIZE if last_mem > 0
86
157
  r[:max_memory] = max_mem * Sunburst::PAGESIZE if last_mem > 0
158
+ r[:avg_mem] = (avg_mem * Sunburst::PAGESIZE) / mem_measure_count if mem_measure_count > 0
87
159
 
88
160
  r[:execution_time] = time2.-(time1).truncate(5)
89
161
  r[:state] = state
90
162
  r[:last_state] = last_state
163
+
164
+ r[:avg_cpu_usage] = sprintf("%05.2f%%", cpu_usage_sum / cpu_usage_measure_count) if cpu_usage_measure_count > 0
165
+ r[:max_cpu_usage] = sprintf("%05.2f%%", max_cpu_usage) if max_cpu_usage > 0
91
166
  }
92
167
 
93
168
  r
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sunburst
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sunburst
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.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-04-11 00:00:00.000000000 Z
11
+ date: 2021-09-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Run a process for a given time, kill it with SIGKILL, report CPU time
14
14
  and memory usage
@@ -47,7 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
47
47
  - !ruby/object:Gem::Version
48
48
  version: '0'
49
49
  requirements: []
50
- rubygems_version: 3.2.13
50
+ rubygems_version: 3.2.21
51
51
  signing_key:
52
52
  specification_version: 4
53
53
  summary: Run a process for a given time, kill it with SIGKILL, report CPU time and