-
Notifications
You must be signed in to change notification settings - Fork 2
/
time.rb
executable file
·147 lines (120 loc) · 4.18 KB
/
time.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/ruby
require 'term/ansicolor'
require 'open3'
require 'io/console'
require 'csv'
include Term::ANSIColor
@hostname=`hostname`.strip
@width = IO.console.winsize[1]
def col(width, text)
return text + "".ljust(width - uncolored(text).size)
end
def rcol(width, text)
return "".ljust(width - uncolored(text).size) + text
end
def clr(s,l,h)
return s >= h ? (green (s.to_s)) : (s < l ? (red (s.to_s)) : (yellow (s.to_s)))
end
def clr_diff_str(s,t, epsilon, str)
if ((s.to_f-t.to_f).abs < epsilon) then
return str
end
return s > t ? (green str)
: (s < t) ? (red str) : str
end
def clr_diff(s,t)
return clr_diff_str(s,t,s.to_f*0.01,s.to_s)
end
def avg(l)
a = l.inject(0.0) { |sum, el| sum + el } / l.size
return a.round(2)
end
def timefile(mod)
return Dir.pwd + "/" + mod.gsub(/(.*)(\/)(.*)/, '\1/.\3') + ".time"
end
def readETA(mod)
@times = []
if (File.readable?(timefile(mod))) then
CSV.foreach(timefile(mod)) do |row|
if row[1] != nil and row[1].strip == @hostname then
@times << row[0].strip.to_f
end
end
end
#times = times.last(5)
#avg = times.inject(0.0) { |sum, el| sum + el } / times.size
#est = times.size > 0 ? avg.round(2).to_s : ""
est = @times.size > 0 ? @times[-1].round(2).to_s : ""
eta = (Time.now + est.to_i).strftime("%H:%M:%S")
return est, eta
end
def writeETA(mod, time)
rev = `git rev-parse HEAD`
CSV.open(timefile(mod), "ab") do |csv|
csv << ["#{time}", "#{@hostname}", "#{Time.now.to_i}", "#{rev.strip}"]
end
end
begin
parallel = false
if ARGV.length == 0 || ARGV[0] == "--help" then
puts "time.sh - command timing script"
puts "This script reports cpu and real time consumed by the command"
puts "Usage:"
puts "\t./time.sh [command]\t\t for usage in single-threaded context"
puts "\t./time.sh --parallel [command]\t if multiple commands are run concurrently"
exit false
end
if ARGV[0] == "--parallel" then
parallel = true
ARGV.shift
end
cmd = ARGV.join(' ')
mod = ARGV.last.sub(/\.v/, "")
modname = mod.sub("theories/", "")
timestamp = Time.now.strftime("%H:%M:%S")
est, eta = readETA(mod)
eststr = "#{col(12, cyan(est))}" + (parallel ? (est == "" ? blue("ETA unavailable") : "ETA #{eta}") : "")
print "#{timestamp} #{cyan('>>>')} #{col(35, modname)}#{eststr}#{(parallel ? "\n" : "")}"
start = Time.now
cstdin, cstdout, cstderr, waitthr = Open3.popen3("bash -c \"time #{cmd}\"")
waitthr.join
time = Time.now - start
success = waitthr.value.to_i == 0
color = lambda { |s| success ? (green s) : (red s) }
serr = cstderr.read
user = serr.match(/.*user[ \t]*([0123456789]+)m([0123456789\.]+)s.*/m)
sys = serr.match(/.*sys[ \t]*([0123456789]+)m([0123456789\.]+)s.*/m)
cpu = user[1].to_f * 60 + user[2].to_f + sys[1].to_f * 60 + sys[2].to_f
timing = "#{cpu.round(2)}"
changesec = (time - est.to_f)
changeperc = 100*changesec/est.to_f
changesecstr = sprintf("%+.2f (%+.1f%%)", changesec, changeperc)
change = est == "" ? blue("n/a") : (clr_diff_str(-changeperc, 0, 1, changesecstr))
line_count = `wc -l "#{mod}.v"`.strip.split(' ')[0].to_i
lps = (line_count / cpu).round(0)
vosize = File.size?("#{mod}.vo").to_f
vokps = (vosize / cpu / 1000).round(0)
speed = success ? rcol(9, "#{line_count} L,") +
rcol( 9, "#{clr(lps, 15, 75)} L/s,") +
rcol(11, "#{clr(vokps, 15, 75)} vok/s") : ""
if success then
writeETA(mod, cpu)
end
if !parallel then
print col(12, color[timing]), col(15, change), speed, "\n"
end
serrs = serr.lines[1...-4] ? serr.lines[1...-4].join : ""
sout = cstdout.read + serrs
if !sout.strip.empty? then
print "#{Time.now.strftime("%H:%M:%S")} ", color["==="], " #{col(35, modname)} ", "OUTPUT FOLLOWS" , "\n"
print sout.gsub!(/^/, ' ')
end
last_times = @times.last(7).map { |t| clr_diff(t.round(2), cpu.round(2))}.join(" ")
if parallel then
print "#{Time.now.strftime("%H:%M:%S")} ", color[success ? "<<<" : "!!!"], " #{col(35, modname)}", col(12, color[timing]), col(15, change), speed,
((@width > 150 && @times.size > 0) ? " #{last_times} avg #{clr_diff(avg(@times.last(7)), cpu.round(2))}" : "" ), "\n"
end
exit success
rescue SignalException => e
exit false
end