-
Notifications
You must be signed in to change notification settings - Fork 256
/
xtime.rb
executable file
·105 lines (89 loc) · 2.25 KB
/
xtime.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
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'fileutils'
require 'socket'
PAGE_SIZE = `getconf PAGESIZE`.to_i
HAS_MEM = File.file?('/proc/self/statm')
RESULTS_LOG = 'target/results.log'
def read_mem(pid)
if HAS_MEM
begin
stat = File.read("/proc/#{pid}/statm").split
PAGE_SIZE * stat[1].to_i # man 5 proc
rescue Errno::ENOENT
0
end
else
0
end
end
# Container for energy stats
class EnergyStats
PATH = '/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj'
attr_reader :has_energy_metrics
def initialize
@acc_e = 0
@e = 0
@has_energy_metrics = FileTest.readable?(PATH)
@max_e = File.read(PATH).to_i if @has_energy_metrics
end
def update
return unless @has_energy_metrics
new_e = File.read(PATH).to_i
if @e.zero?
# first reading
@acc_e = 0
elsif new_e > @e
@acc_e += new_e - @e
elsif new_e < @e
# counter has been reset
@acc_e += @max_e - @e + new_e
end
@e = new_e
end
def val
0.000001 * @acc_e
end
end
energy_stats = EnergyStats.new
server = TCPServer.new("::", 9001)
spawned_pid = Process.spawn(*ARGV.to_a)
begin
client = server.accept_nonblock
rescue IO::WaitReadable
exit(1) unless Process.waitpid(spawned_pid, Process::WNOHANG).nil?
IO.select([server], nil, nil, 1)
retry
end
test_data = client.gets.strip.split("\t")
test_name = test_data[0]
pid = test_data[1].to_i
p test_name
t = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
mem = read_mem(pid)
base_mem = mem
energy_stats.update
while IO.select([server], nil, nil, 0.01).nil?
m = read_mem(pid)
mem = m if m > mem
energy_stats.update
end
client = server.accept
client.gets
energy_stats.update
t_diff = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - t
stats = "#{(t_diff / 1e9).round(3)} s, #{(mem / 1_048_576).round(1)} Mb"
FileUtils.mkdir_p File.dirname(RESULTS_LOG)
if energy_stats.has_energy_metrics
stats += ", #{energy_stats.val.round(1)} J"
File.open(RESULTS_LOG, 'a') do |f|
f.puts "#{test_name}\t#{t_diff}\t#{base_mem}\t#{mem}\t#{energy_stats.val}"
end
else
stats += ', 0.0 J'
File.open(RESULTS_LOG, 'a') do |f|
f.puts "#{test_name}\t#{t_diff}\t#{base_mem}\t#{mem}\t0.0"
end
end
Process.wait spawned_pid
warn stats