sunburst 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENCE +21 -0
- data/README.md +43 -0
- data/bin/setup +8 -0
- data/exe/sunburst +80 -0
- data/ext/stats/extconf.rb +4 -0
- data/ext/stats/stats.c +77 -0
- data/lib/sunburst.rb +5 -0
- data/lib/sunburst/sunburst.rb +43 -0
- data/lib/sunburst/version.rb +5 -0
- metadata +57 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 21354f28529b35ce4d5897120e0f0b37f3ace979705c9d80f746fc2f55e55444
|
4
|
+
data.tar.gz: 8bf865f98151f931e009bf9c8ee0c19397a7cdc3c5c3406c8ac5273f9743963f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b23ae54f7a5d19b065c172ea24d9a9df6e81c048ff07a56b770f8d6abe1765cd78971e8604c5f05179d27b9410d8b23997076c79fc56360f69ca2c76bfb72f80
|
7
|
+
data.tar.gz: dd542f7f462a637e909dd3d1f84e59f2adcc3a184fd0a67287d56228f4a5fd4c757a0950e8294825642a6f26462ffefef7ed51435acbb833f19b31d35ae20791
|
data/LICENCE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Sourav Goswami
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Sunburst
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sunburst`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'sunburst'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install sunburst
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/sunburst. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/sunburst/blob/master/CODE_OF_CONDUCT.md).
|
36
|
+
|
37
|
+
## License
|
38
|
+
|
39
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
40
|
+
|
41
|
+
## Code of Conduct
|
42
|
+
|
43
|
+
Everyone interacting in the Sunburst project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/sunburst/blob/master/CODE_OF_CONDUCT.md).
|
data/bin/setup
ADDED
data/exe/sunburst
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'sunburst'
|
2
|
+
STDOUT.sync = STDIN.sync = true
|
3
|
+
|
4
|
+
def help
|
5
|
+
puts <<~EOF
|
6
|
+
Sunburst lets you run a command for a given time.
|
7
|
+
When the time expires, the program will be SIGKILLed.
|
8
|
+
Sunburst will then report the total CPU time and last known memory usage
|
9
|
+
of the program.
|
10
|
+
|
11
|
+
If no time is specified, it will run until the command exits.
|
12
|
+
|
13
|
+
Arguments:
|
14
|
+
\s\s\s\s--time=N\s\s\s\s\s\s\s\s\s\sRun the program for N seconds
|
15
|
+
\s\s\s\s-h | --help\s\s\s\s\s\s\sShow this help section
|
16
|
+
\s\s\s\s--humanize\s\s\s\s\s\s\s\sHuman readable memory units
|
17
|
+
|
18
|
+
Example:
|
19
|
+
\s\s\s\ssunburst echo hello world --time=0.05 --humanize
|
20
|
+
\s\s\s\ssunburst "echo hello world" --time=0.05 --humanize
|
21
|
+
\s\s\s\ssunburst "ruby -e 'while true do end'" --time=3 --humanize
|
22
|
+
\s\s\s\ssunburst "ruby -e 'p :Hello'" --time=3 --humanize
|
23
|
+
EOF
|
24
|
+
|
25
|
+
exit 0
|
26
|
+
end
|
27
|
+
|
28
|
+
help if ARGV.any? { |x| x[/^\-(\-help|h)$/] }
|
29
|
+
|
30
|
+
time_arg = ARGV.find { |x| x[/^\-\-time=[0-9]+\.?[0-9]*$/] }
|
31
|
+
ARGV.delete(time_arg) if time_arg
|
32
|
+
time = time_arg ? time_arg.split('=')[-1].to_f : nil
|
33
|
+
|
34
|
+
_human_readable = ARGV.find { |x| x[/^\-\-humanize$/] }
|
35
|
+
ARGV.delete(_human_readable) if _human_readable
|
36
|
+
human_readable = _human_readable
|
37
|
+
|
38
|
+
command = ARGV.join(' ')
|
39
|
+
|
40
|
+
help if command.empty?
|
41
|
+
|
42
|
+
puts %Q(:: Running "#{command}" for #{time || 'infinite'} seconds)
|
43
|
+
puts ?- * Sunburst.win_width
|
44
|
+
|
45
|
+
begin
|
46
|
+
data = Sunburst.measure(command: command, time: time, sleep_time: 0.0001)
|
47
|
+
|
48
|
+
puts ?- * Sunburst.win_width
|
49
|
+
puts ":: Total Execution Time: #{data[:execution_time]} seconds"
|
50
|
+
puts ":: CPU Time: #{data[:cpu_time]} second#{?s if data[:cpu_time] != 1}"
|
51
|
+
|
52
|
+
mem = data[:memory]
|
53
|
+
|
54
|
+
if mem
|
55
|
+
if human_readable
|
56
|
+
mem_text = if mem >= 10 ** 12
|
57
|
+
"#{mem.fdiv(10 ** 12).round(3)} TB"
|
58
|
+
elsif mem >= 10 ** 9
|
59
|
+
"#{mem.fdiv(10 ** 9).round(3)} GB"
|
60
|
+
elsif mem >= 10 ** 6
|
61
|
+
"#{mem.fdiv(10 ** 6).round(3)} MB"
|
62
|
+
elsif mem >= 10 ** 3
|
63
|
+
"#{mem.fdiv(10 ** 3).round(3)} KB"
|
64
|
+
else
|
65
|
+
"#{mem} Bytes"
|
66
|
+
end
|
67
|
+
|
68
|
+
puts ":: Memory usage: #{mem_text}"
|
69
|
+
else
|
70
|
+
puts ":: Memory usage: #{mem} bytes"
|
71
|
+
end
|
72
|
+
else
|
73
|
+
puts ":: The memory usage can't be logged."
|
74
|
+
end
|
75
|
+
rescue Errno::ENOENT
|
76
|
+
puts "sunburst: #{command}: command not found"
|
77
|
+
puts ?- * Sunburst.win_width
|
78
|
+
rescue StandardError
|
79
|
+
puts "$!.full_message"
|
80
|
+
end
|
data/ext/stats/stats.c
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include <unistd.h>
|
3
|
+
#include <time.h>
|
4
|
+
#include <sys/ioctl.h>
|
5
|
+
|
6
|
+
unsigned int PAGESIZE ;
|
7
|
+
unsigned int TICKS ;
|
8
|
+
|
9
|
+
VALUE statm_memory(VALUE obj, VALUE pid) {
|
10
|
+
int _pid = FIX2INT(pid) ;
|
11
|
+
if (_pid < 0) return Qnil ;
|
12
|
+
|
13
|
+
char _path[22] ;
|
14
|
+
sprintf(_path, "/proc/%d/statm", _pid) ;
|
15
|
+
|
16
|
+
FILE *f = fopen(_path, "r") ;
|
17
|
+
if (!f) return Qnil ;
|
18
|
+
|
19
|
+
unsigned int resident, shared ;
|
20
|
+
char status = fscanf(f, "%*u %u %u", &resident, &shared) ;
|
21
|
+
fclose(f) ;
|
22
|
+
|
23
|
+
if (status != 2) return Qnil ;
|
24
|
+
|
25
|
+
unsigned int v = resident - shared ;
|
26
|
+
return UINT2NUM(v) ;
|
27
|
+
}
|
28
|
+
|
29
|
+
VALUE ps_times(VALUE obj, VALUE pid) {
|
30
|
+
int _pid = FIX2INT(pid) ;
|
31
|
+
if (_pid < 0) return Qnil ;
|
32
|
+
|
33
|
+
char _path[22] ;
|
34
|
+
sprintf(_path, "/proc/%d/stat", _pid) ;
|
35
|
+
|
36
|
+
FILE *f = fopen(_path, "r") ;
|
37
|
+
if (!f) return Qnil ;
|
38
|
+
|
39
|
+
unsigned long utime, stime ;
|
40
|
+
|
41
|
+
char status = fscanf(f, "%*llu (%*[^)]%*[)] %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %lu %lu", &utime, &stime) ;
|
42
|
+
fclose(f) ;
|
43
|
+
|
44
|
+
if (status != 2) return Qnil ;
|
45
|
+
float total_time = (utime + stime) / (float)TICKS ;
|
46
|
+
|
47
|
+
return rb_float_new(total_time) ;
|
48
|
+
}
|
49
|
+
|
50
|
+
VALUE clock_monotonic(VALUE obj) {
|
51
|
+
struct timespec tv ;
|
52
|
+
clock_gettime(CLOCK_MONOTONIC, &tv) ;
|
53
|
+
long double time = tv.tv_sec + tv.tv_nsec / 1000000000.0 ;
|
54
|
+
|
55
|
+
return rb_float_new(time) ;
|
56
|
+
}
|
57
|
+
|
58
|
+
VALUE winWidth(VALUE obj) {
|
59
|
+
struct winsize w ;
|
60
|
+
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) ;
|
61
|
+
return INT2NUM(w.ws_col) ;
|
62
|
+
}
|
63
|
+
|
64
|
+
void Init_stats() {
|
65
|
+
PAGESIZE = sysconf(_SC_PAGESIZE) ;
|
66
|
+
TICKS = sysconf(_SC_CLK_TCK) ;
|
67
|
+
|
68
|
+
VALUE sunburst = rb_define_module("Sunburst") ;
|
69
|
+
rb_define_const(sunburst, "PAGESIZE", UINT2NUM(PAGESIZE)) ;
|
70
|
+
rb_define_const(sunburst, "TICKS", UINT2NUM(TICKS)) ;
|
71
|
+
|
72
|
+
rb_define_module_function(sunburst, "get_mem", statm_memory, 1) ;
|
73
|
+
rb_define_module_function(sunburst, "get_times", ps_times, 1) ;
|
74
|
+
rb_define_module_function(sunburst, "clock_monotonic", clock_monotonic, 0) ;
|
75
|
+
|
76
|
+
rb_define_module_function(sunburst, "win_width", winWidth, 0) ;
|
77
|
+
}
|
data/lib/sunburst.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sunburst
|
2
|
+
def self.measure(command:, time: nil, sleep_time: 0.001)
|
3
|
+
r = {execution_time: nil, cpu_time: nil, memory: nil}
|
4
|
+
|
5
|
+
IO.popen(command) { |x|
|
6
|
+
time1 = Sunburst.clock_monotonic
|
7
|
+
pid = x.pid
|
8
|
+
|
9
|
+
t = Thread.new {
|
10
|
+
print x.readpartial(4096) until x.eof?
|
11
|
+
}
|
12
|
+
|
13
|
+
last_mem = 0
|
14
|
+
|
15
|
+
while true
|
16
|
+
_last_mem = Sunburst.get_mem(pid)
|
17
|
+
|
18
|
+
break if (time && Sunburst.clock_monotonic - time1 > time) || _last_mem == 0
|
19
|
+
last_mem = _last_mem
|
20
|
+
|
21
|
+
sleep(sleep_time)
|
22
|
+
end
|
23
|
+
|
24
|
+
time2 = Sunburst.clock_monotonic
|
25
|
+
|
26
|
+
# Get CPU Time
|
27
|
+
cpu_time = Sunburst.get_times(pid).truncate(5)
|
28
|
+
|
29
|
+
# Get Memory Usage
|
30
|
+
_last_mem = Sunburst.get_mem(pid)
|
31
|
+
last_mem = _last_mem unless _last_mem == 0
|
32
|
+
|
33
|
+
t.kill
|
34
|
+
Process.kill(9, pid)
|
35
|
+
|
36
|
+
r[:execution_time] = time2.-(time1).truncate(5)
|
37
|
+
r[:cpu_time] = cpu_time
|
38
|
+
r[:memory] = last_mem * Sunburst::PAGESIZE if last_mem > 0
|
39
|
+
}
|
40
|
+
|
41
|
+
r
|
42
|
+
end
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sunburst
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sourav Goswami
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-04-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Run a process for a given time, kill it with SIGKILL, report CPU time
|
14
|
+
and memory usage
|
15
|
+
email:
|
16
|
+
- souravgoswami@protonmail.com
|
17
|
+
executables:
|
18
|
+
- sunburst
|
19
|
+
extensions:
|
20
|
+
- ext/stats/extconf.rb
|
21
|
+
extra_rdoc_files:
|
22
|
+
- README.md
|
23
|
+
files:
|
24
|
+
- LICENCE
|
25
|
+
- README.md
|
26
|
+
- bin/setup
|
27
|
+
- exe/sunburst
|
28
|
+
- ext/stats/extconf.rb
|
29
|
+
- ext/stats/stats.c
|
30
|
+
- lib/sunburst.rb
|
31
|
+
- lib/sunburst/sunburst.rb
|
32
|
+
- lib/sunburst/version.rb
|
33
|
+
homepage: https://github.com/Souravgoswami/sunburst/
|
34
|
+
licenses:
|
35
|
+
- MIT
|
36
|
+
metadata: {}
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.6.0
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubygems_version: 3.2.13
|
53
|
+
signing_key:
|
54
|
+
specification_version: 4
|
55
|
+
summary: Run a process for a given time, kill it with SIGKILL, report CPU time and
|
56
|
+
memory usage
|
57
|
+
test_files: []
|