sunburst 0.2.0 → 0.3.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: bac5cf8138ded782d5114cf84c9d05f3f06e748328024aaa2c99783187c734ac
4
- data.tar.gz: a8959e5ff6b66c568b0c5d7ead18abdb5c1df9305155e4e9f29ca0c449074617
3
+ metadata.gz: 9ecfac43448912f08b86571fecabeb676b11902524428b542973b83f535eeb71
4
+ data.tar.gz: 85668f8a6cb4a40f48e9e6f24c43dae60cf07b68a9ab1b6d4f5559b2eb8f0d71
5
5
  SHA512:
6
- metadata.gz: bad636441bee759ab7783226a3ea6e0e86b5cfae584b1ddc81f2d181df354101c58c43092f38f80136d00e22846641199b5256bc8c80da5f398e29d32a990432
7
- data.tar.gz: 8846d22b978e865380622bd7139d0260c7d0f9a3b6c2e43c01230bedeb5f7f473b24136ac1a9dc1a08b85e7efa7f7029a33f439630cd24fa49e6876dd17626c5
6
+ metadata.gz: '09483bbbc6011547a6cbc1a691363545d5c7002dbfca9c593fde20bb4083df5995e449e02d319bd65054967b164417a2cc2662cca41541c647ab745f67e776fe'
7
+ data.tar.gz: 42c5ce9d7ba09046ddb22c27cb8de6ac64c64a488b0a52a3cb52357aa2d1fc3f4029e8772fa3543c6725ac5ada1258c4876564c0fb7ddd07ab2593d84d2e0463
data/exe/sunburst CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # Frozen_String_Literal: true
3
+
2
4
  $-v = nil
3
5
  STDOUT.sync = STDIN.sync = true
4
6
  require 'sunburst'
@@ -15,13 +17,16 @@ def help
15
17
  Arguments:
16
18
  \s\s\s\s--time=N\s\s\s\s\s\s\s\s\s\sRun the program for N seconds
17
19
  \s\s\s\s-h | --help\s\s\s\s\s\s\sShow this help section
20
+ \s\s\s\s-p | --progress\s\s\sShow realtime stats of the process
18
21
  \s\s\s\s--humanize\s\s\s\s\s\s\s\sHuman readable memory units
19
22
 
20
23
  Example:
21
24
  \s\s\s\ssunburst echo hello world --time=0.05 --humanize
22
25
  \s\s\s\ssunburst "echo hello world" --time=0.05 --humanize
23
26
  \s\s\s\ssunburst "ruby -e 'while true do end'" --time=3 --humanize
24
- \s\s\s\ssunburst "ruby -e 'p :Hello'" --time=3 --humanize
27
+ \s\s\s\ssunburst "ruby -e 'p :Hello'" --time=3
28
+ \s\s\s\ssunburst "while : ; do : ; done" --time=3 --humanize --progress
29
+
25
30
  EOF
26
31
 
27
32
  exit 0
@@ -32,6 +37,20 @@ def splitter(sub = 8)
32
37
  puts ?\n, ?-.*(width - sub).center(width)
33
38
  end
34
39
 
40
+ def convert_bytes(mem)
41
+ if mem >= 10 ** 12
42
+ "#{"%06.3f" % mem.fdiv(10 ** 12)} TB"
43
+ elsif mem >= 10 ** 9
44
+ "#{"%06.3f" % mem.fdiv(10 ** 9)} GB"
45
+ elsif mem >= 10 ** 6
46
+ "#{"%06.3f" % mem.fdiv(10 ** 6)} MB"
47
+ elsif mem >= 10 ** 3
48
+ "#{"%06.3f" % mem.fdiv(10 ** 3)} KB"
49
+ else
50
+ "#{"%06.3f" % mem} Bytes"
51
+ end
52
+ end
53
+
35
54
  help if ARGV.any? { |x| x[/^\-(\-help|h)$/] }
36
55
 
37
56
  time_arg = ARGV.find { |x| x[/^\-\-time=[0-9]+\.?[0-9]*$/] }
@@ -42,20 +61,49 @@ _human_readable = ARGV.find { |x| x[/^\-\-humanize$/] }
42
61
  ARGV.delete(_human_readable) if _human_readable
43
62
  human_readable = _human_readable
44
63
 
64
+ _progress = ARGV.find { |x| x[/^\-(\-progress|p)$/] }
65
+ ARGV.delete(_progress) if _progress
66
+ progress = _progress
67
+
45
68
  command = ARGV.join(' ')
46
69
 
47
70
  help if command.empty?
48
71
 
49
72
  puts %Q(:: Running "#{command}" for #{time || 'infinite'} seconds)
50
73
 
51
-
52
74
  begin
53
- print ""
75
+ message = if progress
76
+ "\e[4mLogging Stats, Ignoring Standard Output and Error\e[0m"
77
+ else
78
+ "\e[4mLogging Standard Output and Error\e[0m"
79
+ end
54
80
 
55
- message = "\e[4mLogging Standard Output and Error\e[0m"
56
81
  puts "\e[38;2;243;156;18m#{message.center(Sunburst.win_width + 6)}\e[0m"
57
82
 
58
- data = Sunburst.measure(command: command, time: time, sleep_time: 0.0001)
83
+ data = if progress
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:: "\
87
+ "Exec T: #{"%05.2f" % exec_t}s | "\
88
+ "CPU T: #{"%05.2f" % cpu_t}s | "\
89
+ "Mem: #{convert_bytes(mem)} | "\
90
+ "Threads: #{threads} | "\
91
+ "State: #{state}\r"
92
+ }
93
+ else
94
+ Sunburst.measure(command: command, time: time, sleep_time: 0.0001) { |exec_t, cpu_t, mem, threads, state|
95
+ print "\e[2K:: "\
96
+ "Exec T: #{"%05.2f" % exec_t} | "\
97
+ "CPU T: #{"%05.2f" % cpu_t} | "\
98
+ "Mem: #{"%2d" % mem} | "\
99
+ "Threads: #{threads} | "\
100
+ "State: #{state}\r"
101
+ }
102
+ end
103
+ else
104
+ Sunburst.measure(command: command, time: time, sleep_time: 0.0001)
105
+ end
106
+
59
107
  print "\e[38;2;243;156;18m"
60
108
  splitter()
61
109
  print "\e[0m"
@@ -64,7 +112,7 @@ begin
64
112
  cpu_time = data[:cpu_time]
65
113
  percent_time = cpu_time.*(100).fdiv(exec_time)
66
114
 
67
- style = "\e[1;"
115
+ style = +"\e[1;"
68
116
  style << if percent_time > 75
69
117
  "38;2;230;80;70m"
70
118
  elsif percent_time > 50
@@ -76,13 +124,13 @@ begin
76
124
  end
77
125
 
78
126
  puts ":: Total Execution Time: #{data[:execution_time]} seconds\e[0m"
79
- puts ":: CPU Time: #{style}#{data[:cpu_time]}\e[0m second#{?s if data[:cpu_time] != 1} (#{percent_time.round(3)}% exec time)"
127
+ puts ":: Total CPU Time: #{style}#{data[:cpu_time]}\e[0m second#{?s if data[:cpu_time] != 1} (#{percent_time.round(3)}% exec time)"
80
128
 
81
129
  mem = data[:memory]
82
130
  if mem
83
131
  percent_mem = mem.*(100).fdiv(Sunburst.total_ram)
84
132
 
85
- style = "\e[1;"
133
+ style = +"\e[1;"
86
134
  style << if percent_mem > 50
87
135
  "38;2;230;80;70m"
88
136
  elsif percent_mem > 30
@@ -94,28 +142,44 @@ begin
94
142
  end
95
143
 
96
144
  if human_readable
97
- mem_text = if mem >= 10 ** 12
98
- "#{mem.fdiv(10 ** 12).round(3)} TB"
99
- elsif mem >= 10 ** 9
100
- "#{mem.fdiv(10 ** 9).round(3)} GB"
101
- elsif mem >= 10 ** 6
102
- "#{mem.fdiv(10 ** 6).round(3)} MB"
103
- elsif mem >= 10 ** 3
104
- "#{mem.fdiv(10 ** 3).round(3)} KB"
105
- else
106
- "#{mem} Bytes"
107
- end
108
-
109
- puts ":: Memory usage: #{style}#{mem_text}\e[0m (#{percent_mem.round(3)}% system mem)"
145
+ mem_text = convert_bytes(mem)
146
+
147
+ puts ":: Memory Usage During Exit: #{style}#{mem_text}\e[0m (#{percent_mem.round(3)}% system mem)"
148
+ else
149
+ puts ":: Memory Usage During Exit: #{style}#{mem} bytes\e[0m (#{percent_mem.round(3)}% system mem)"
150
+ end
151
+ else
152
+ puts ":: The memory Usage Can't be Logged."
153
+ end
154
+
155
+ max_mem = data[:max_memory]
156
+ if max_mem
157
+ percent_mem = max_mem.*(100).fdiv(Sunburst.total_ram)
158
+
159
+ style = +"\e[1;"
160
+ style << if percent_mem > 50
161
+ "38;2;230;80;70m"
162
+ elsif percent_mem > 30
163
+ "38;2;45;125;255m"
164
+ elsif percent_mem > 10
165
+ "38;2;255;225;0m"
166
+ else
167
+ "38;2;40;175;95m"
168
+ end
169
+
170
+ if human_readable
171
+ mem_text = convert_bytes(max_mem)
172
+
173
+ puts ":: Max Memory Usage: #{style}#{mem_text}\e[0m (#{percent_mem.round(3)}% system mem)"
110
174
  else
111
- puts ":: Memory usage: #{style}#{mem} bytes\e[0m (#{percent_mem.round(3)}% system mem)"
175
+ puts ":: Max Memory Usage: #{style}#{max_mem} bytes\e[0m (#{percent_mem.round(3)}% system mem)"
112
176
  end
113
177
  else
114
- puts ":: The memory usage can't be logged."
178
+ puts ":: The max memory Usage can't be logged."
115
179
  end
116
180
 
117
181
  max_threads = data[:max_threads]
118
- style = "\e[1;"
182
+ style = +"\e[1;"
119
183
  style << if max_threads > 16
120
184
  "38;2;230;80;70m"
121
185
  elsif max_threads > 8
data/ext/stats/stats.c CHANGED
@@ -40,27 +40,29 @@ VALUE ps_stat(volatile VALUE obj, volatile VALUE pid) {
40
40
 
41
41
  // For this info
42
42
  // follow https://man7.org/linux/man-pages/man5/proc.5.html
43
+ char state[1] ;
43
44
  int ppid, processor ;
44
45
  long unsigned utime, stime ;
45
46
  long num_threads ;
46
47
 
47
48
  char status = fscanf(
48
- f, "%*llu (%*[^)]%*[)] %*c "
49
+ f, "%*llu (%*[^)]%*[)] %1s "
49
50
  "%d %*d %*d %*d %*d %*u "
50
51
  "%*lu %*lu %*lu %*lu %lu %lu "
51
52
  "%*ld %*ld %*ld %*ld %ld",
52
- &ppid, &utime, &stime, &num_threads
53
+ &state, &ppid, &utime, &stime, &num_threads
53
54
  ) ;
54
55
 
55
56
  fclose(f) ;
56
57
 
57
- if (status != 4) return rb_ary_new() ;
58
+ if (status != 5) return rb_ary_new() ;
58
59
 
59
- return rb_ary_new_from_args(4,
60
+ return rb_ary_new_from_args(5,
60
61
  INT2NUM(ppid),
61
62
  ULONG2NUM(utime),
62
63
  ULONG2NUM(stime),
63
- LONG2NUM(num_threads)
64
+ LONG2NUM(num_threads),
65
+ rb_str_new(state, 1)
64
66
  ) ;
65
67
  }
66
68
 
@@ -11,30 +11,53 @@ module Sunburst
11
11
  end
12
12
 
13
13
  def self.measure(command:, time: nil, sleep_time: 0.001)
14
+ progress = block_given?
15
+
14
16
  r = {
15
17
  execution_time: nil, cpu_time: nil,
16
- memory: nil, max_threads: nil
18
+ memory: nil, max_threads: nil,
19
+ max_memory: nil, state: nil, last_state: nil
17
20
  }
18
21
 
19
22
  IO.popen(command) { |x|
20
23
  time1 = Sunburst.clock_monotonic
21
24
  pid = x.pid
22
25
 
23
- t = Thread.new { print x.readpartial(4096) until x.eof? }
26
+ t = if progress
27
+ Thread.new { }
28
+ else
29
+ Thread.new { print x.readpartial(4096) until x.eof? }
30
+ end
24
31
 
25
32
  last_mem = 0
26
33
  max_threads = 0
34
+ max_mem = 0
35
+ last_state = nil
27
36
 
28
37
  while true
29
38
  _last_mem = Sunburst.get_mem(pid)
30
39
 
31
40
  break if (time && Sunburst.clock_monotonic - time1 > time) || _last_mem == 0
32
41
  last_mem = _last_mem
42
+ max_mem = last_mem if max_mem < _last_mem
33
43
 
34
44
  # Get stats
35
45
  stats = get_stats(pid)
36
46
  _threads = stats[3]
37
47
  max_threads = _threads if max_threads < _threads
48
+ last_state = stats[4]
49
+
50
+ cpu_time = stats[1].+(stats[2]).fdiv(Sunburst::TICKS)
51
+
52
+ if progress
53
+ yield(
54
+ Sunburst.clock_monotonic.-(time1),
55
+ stats[1].+(stats[2]).fdiv(Sunburst::TICKS),
56
+ _last_mem * Sunburst::PAGESIZE,
57
+ _threads,
58
+ last_state
59
+ )
60
+ end
38
61
 
39
62
  sleep(sleep_time)
40
63
  end
@@ -48,18 +71,23 @@ module Sunburst
48
71
  _threads = stats[3]
49
72
  max_threads = _threads if max_threads < _threads
50
73
 
51
- # Get Memory Usage
52
74
  _last_mem = Sunburst.get_mem(pid)
75
+ max_mem = _last_mem if max_mem < _last_mem
53
76
  last_mem = _last_mem unless _last_mem == 0
54
77
 
78
+ state = stats[4]
79
+
55
80
  t.kill
56
81
  Process.kill(9, pid)
57
82
 
58
83
  r[:cpu_time] = cpu_time
59
84
  r[:max_threads] = max_threads unless max_threads == 0
60
85
  r[:memory] = last_mem * Sunburst::PAGESIZE if last_mem > 0
86
+ r[:max_memory] = max_mem * Sunburst::PAGESIZE if last_mem > 0
61
87
 
62
88
  r[:execution_time] = time2.-(time1).truncate(5)
89
+ r[:state] = state
90
+ r[:last_state] = last_state
63
91
  }
64
92
 
65
93
  r
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sunburst
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sunburst
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sourav Goswami
@@ -18,11 +18,9 @@ executables:
18
18
  - sunburst
19
19
  extensions:
20
20
  - ext/stats/extconf.rb
21
- extra_rdoc_files:
22
- - README.md
21
+ extra_rdoc_files: []
23
22
  files:
24
23
  - LICENCE
25
- - README.md
26
24
  - bin/setup
27
25
  - exe/sunburst
28
26
  - ext/stats/extconf.rb
data/README.md DELETED
@@ -1,78 +0,0 @@
1
- # Sunburst
2
- Sunburst lets you run a command for a given time.
3
- When the time expires, the program will be SIGKILLed.
4
- Sunburst will then report the total CPU time and last known memory usage
5
- of the program.
6
-
7
- For example:
8
-
9
- ```
10
- $ sunburst "while : ; do echo hi ; sleep 1 ; done" --time=3
11
- :: Running "while : ; do echo hi ; sleep 1 ; done" for 3.0 seconds
12
- Logging Standard Output and Error
13
- hi
14
- hi
15
- hi
16
-
17
- ----------------------------------------------------------------------
18
- :: Total Execution Time: 3.00097 seconds
19
- :: CPU Time: 0.0 seconds (0.0% exec time)
20
- :: Memory usage: 577536 bytes (0.007% system mem)
21
- :: Max Threads: 1
22
- ```
23
-
24
- Or
25
-
26
- ```
27
- $ sunburst "while : ; do : ; done" --time=3
28
- :: Running "while : ; do : ; done" for 3.0 seconds
29
- Logging Standard Output and Error
30
-
31
- ----------------------------------------------------------------------
32
- :: Total Execution Time: 3.00097 seconds
33
- :: CPU Time: 2.97 seconds (98.968% exec time)
34
- :: Memory usage: 360448 bytes (0.004% system mem)
35
- :: Max Threads: 1
36
- ```
37
-
38
- ## Installation
39
- Add this line to your application's Gemfile:
40
-
41
- ```ruby
42
- gem 'sunburst'
43
- ```
44
-
45
- And then execute:
46
-
47
- ```
48
- $ bundle install
49
- ```
50
-
51
- Or install it yourself as:
52
- ```
53
- $ gem install sunburst
54
- ```
55
-
56
- ## Usage
57
- Run sunbust -h for instruction.
58
-
59
- ```
60
- Arguments:
61
- --time=N Run the program for N seconds
62
- -h | --help Show this help section
63
- --humanize Human readable memory units
64
-
65
- Example:
66
- sunburst echo hello world --time=0.05 --humanize
67
- sunburst "echo hello world" --time=0.05 --humanize
68
- sunburst "ruby -e 'while true do end'" --time=3 --humanize
69
- sunburst "ruby -e 'p :Hello'" --time=3 --humanize
70
- ```
71
-
72
- If no time is specified, it will run until the command exits.
73
-
74
- ## Contributing
75
- Bug reports and pull requests are welcome on GitHub at https://github.com/Souravgoswami/sunburst.
76
-
77
- ## License
78
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).