sunburst 0.3.0 → 0.4.0

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