sunburst 0.2.0 → 0.3.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: 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).