aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2019-07-22 19:26:05 -0400
committerPaul Duncan <pabs@pablotron.org>2019-07-22 19:26:05 -0400
commit21361f9fcaca4833f3f14a1778fedc7444653292 (patch)
treedb0d4402f2551de63f15aa1131d330ac95c75111
parent07d8c85c105120afecc613729006e581a0217b63 (diff)
downloadpi4-bench-21361f9fcaca4833f3f14a1778fedc7444653292.tar.bz2
pi4-bench-21361f9fcaca4833f3f14a1778fedc7444653292.zip
cleanups, start refactoring parsers
-rw-r--r--config.yaml2
-rwxr-xr-xrun.rb278
2 files changed, 202 insertions, 78 deletions
diff --git a/config.yaml b/config.yaml
index 9f2f44d..6cced1e 100644
--- a/config.yaml
+++ b/config.yaml
@@ -34,7 +34,7 @@ hosts:
- name: "i78650u-flex"
host: "flex"
- text: "Intel i7-8650U (Lenovo X1 Carbon 6th Gen)"
+ text: "Intel i7-8650U (Lenovo X1 Carbon, 6th Gen)"
arch: "amd64"
pi: false
diff --git a/run.rb b/run.rb
index aff3588..f87f8c3 100755
--- a/run.rb
+++ b/run.rb
@@ -89,15 +89,27 @@ module PiBench
hosts: [{
id: 'name',
name: 'Name',
- }, {
- id: 'arch',
- name: 'Architecture',
+ tip: 'System name.',
}, {
id: 'text',
name: 'Description',
+ tip: 'System description.',
+ }, {
+ id: 'architecture',
+ name: 'Architecture',
+ tip: 'Processor architecture.',
+ }, {
+ id: 'mhz',
+ name: 'Speed (MHz)',
+ tip: 'Maximum CPU speed, in MHz.',
+ }, {
+ id: 'aes',
+ name: 'AES?',
+ tip: 'Does this CPU have hardware-accelerated AES instructions?',
}, {
id: 'openssl',
name: 'OpenSSL Version',
+ tip: 'OpenSSL version.',
}],
}.freeze
@@ -106,7 +118,7 @@ module PiBench
#
ARCHS = {
all: {
- name: 'All Systems',
+ name: 'All System',
text: %{
<p>
OpenSSL speed test results by algorithm across all systems.
@@ -123,7 +135,7 @@ module PiBench
},
arm: {
- name: 'Raspberry Pis',
+ name: 'Raspberry Pi',
text: %{
<p>
OpenSSL speed test results by algorithm for Raspberry Pi
@@ -190,7 +202,7 @@ module PiBench
</ul>
<section>
- <h2>Systems</h2>
+ <h2>Test System Details</h2>
<p>
Test system details.
@@ -214,11 +226,26 @@ module PiBench
<tbody>
%{rows}
</tbody>
+
+ <tfoot>
+ <tr>
+ <td colspan='%{cols|size|h}'>
+ <a
+ href='csvs/hosts.csv'
+ title='Download test system details as a CSV.'
+ >
+ Download
+ </a>
+ </td>
+ </tr>
+ </tfoot>
</table>
}.strip,
col: %{
- <th>%{name|h}</th>
+ <th title='%{tip|h}'>
+ %{name|h}
+ </th>
}.strip,
row: %{
@@ -226,11 +253,13 @@ module PiBench
}.strip,
cell: %{
- <td>%{text|h}</td>
+ <td title='%{tip|h}'>
+ %{text|h}
+ </td>
}.strip,
svg_title: %{
- OpenSSL Speed Test Results: %{arch|h}, %{algo|h}
+ %{arch|h} Test Results: %{algo|h}
}.strip,
svg: %{
@@ -284,7 +313,7 @@ module PiBench
section: %{
<section>
- <h2>%{name|h} Results</h2>
+ <h2>%{name|h} Test Results</h2>
%{text}
%{svgs}
</section>
@@ -438,9 +467,104 @@ module PiBench
end
end
+ class Parser
+ def self.run(model)
+ new(model).run
+ end
+
+ def initialize(model)
+ @model = model
+ end
+
+ protected
+
+ def out_dir
+ @model.out_dir
+ end
+ end
+
+ #
+ # Parse openssl benchmark data into a nested map of architecture
+ # sets, algorithms, and rows.
+ #
+ class OpenSSLSpeedParser < Parser
+ def run
+ @model.config['hosts'].reduce(Hash.new do |h, k|
+ h[k] = Hash.new do |h2, k2|
+ h2[k2] = { max: 0, rows: [] }
+ end
+ end) do |r, row|
+ # build absolute path to openssl speed data files
+ glob = '%s/hosts/%s/speed-*.txt' % [out_dir, row['name']]
+
+ # parse speed files
+ Dir[glob].each do |path|
+ # get arch
+ arch = row['pi'] ? 'arm' : 'x86'
+
+ # parse file
+ lines = File.readlines(path).select { |line|
+ # match on result rows
+ line =~ /^\+F:/
+ }.each do |line|
+ # split to results
+ vals = line.strip.split(':')
+
+ # build algorithm name
+ algo = vals[2].gsub(/\s+/, '-')
+
+ # walk block sizes
+ SIZES.each_with_index do |size, i|
+ 4.times.map { |j|
+ {
+ algo: ((j & 1) != 0) ? 'all' : algo,
+ arch: ((j & 2) != 0) ? 'all' : arch,
+ }
+ }.each do |agg|
+ val = vals[i + 3].to_f
+ max = r[agg[:arch]][agg[:algo]][:max]
+ r[agg[:arch]][agg[:algo]][:max] = val if val > max
+
+ r[agg[:arch]][agg[:algo]][:rows] << (if agg[:algo] == 'all'
+ # build row for all-*.csv
+ [row['name'], algo, size, val]
+ else
+ # row for algo-specific CSV
+ [row['name'], size, val]
+ end)
+ end
+ end
+ end
+ end
+
+ r
+ end
+ end
+ end
+
+ #
+ # Parse OpenSSL version data into a map of host to version.
+ #
+ class OpenSSLVersionParser < Parser
+ def run
+ @model.config['hosts'].reduce({}) do |r, row|
+ r[row['name']] = File.read('%s/hosts/%s/version.txt' % [
+ out_dir,
+ row['name'],
+ ]).strip.split(/\s+/)[1]
+
+ r
+ end
+ end
+ end
+
class Runner
include BG
+ attr_reader :config
+ attr_reader :log
+ attr_reader :data
+
#
# Allow one-shot invocation.
#
@@ -478,6 +602,13 @@ module PiBench
save_index_html(html)
end
+ #
+ # Get output directory.
+ #
+ def out_dir
+ @config['out_dir']
+ end
+
private
#
@@ -537,60 +668,8 @@ module PiBench
HostQueue.run(@log, queues)
end
- #
- # Parse openssl benchmark data into a map of algorithm => rows
- #
def parse_data
- @config['hosts'].reduce(Hash.new do |h, k|
- h[k] = Hash.new do |h2, k2|
- h2[k2] = { max: 0, rows: [] }
- end
- end) do |r, row|
- # build absolute path to openssl speed data files
- glob = '%s/hosts/%s/speed-*.txt' % [out_dir, row['name']]
-
- # parse speed files
- Dir[glob].each do |path|
- # get arch
- arch = row['pi'] ? 'arm' : 'x86'
-
- # parse file
- lines = File.readlines(path).select { |line|
- # match on result rows
- line =~ /^\+F:/
- }.each do |line|
- # split to results
- vals = line.strip.split(':')
-
- # build algorithm name
- algo = vals[2].gsub(/\s+/, '-')
-
- # walk block sizes
- SIZES.each_with_index do |size, i|
- 4.times.map { |j|
- {
- algo: ((j & 1) != 0) ? 'all' : algo,
- arch: ((j & 2) != 0) ? 'all' : arch,
- }
- }.each do |agg|
- val = vals[i + 3].to_f
- max = r[agg[:arch]][agg[:algo]][:max]
- r[agg[:arch]][agg[:algo]][:max] = val if val > max
-
- r[agg[:arch]][agg[:algo]][:rows] << (if agg[:algo] == 'all'
- # build row for all-*.csv
- [row['name'], algo, size, val]
- else
- # row for algo-specific CSV
- [row['name'], size, val]
- end)
- end
- end
- end
- end
-
- r
- end
+ OpenSSLSpeedParser.run(self)
end
#
@@ -706,7 +785,11 @@ module PiBench
'%s/csvs/hosts.csv' % [out_dir],
COLS[:hosts].map { |col| col[:name] },
@config['hosts'].map { |row|
- COLS[:hosts].map { |col| row[col[:id]] }
+ row.merge(get_host_data(row['name']))
+ }.map { |row|
+ COLS[:hosts].map { |col|
+ row[col[:id]] || row[col[:id].intern]
+ }
}
)
end
@@ -721,15 +804,13 @@ module PiBench
}.join,
rows: @config['hosts'].map { |row|
- path = '%s/hosts/%s/version.txt' % [out_dir, row['name']]
- row.merge({
- 'openssl' => File.read(path).strip,
- })
+ row.merge(get_host_data(row['name']))
}.map { |row|
TEMPLATES[:row].run({
row: COLS[:hosts].map { |col|
TEMPLATES[:cell].run({
- text: row[col[:id]]
+ tip: col[:tip] || '',
+ text: row[col[:id]] || row[col[:id].intern]
})
}.join
})
@@ -737,12 +818,60 @@ module PiBench
})
end
+ def get_host_data(host)
+ @host_data ||= {}
+
+ unless @host_data.key?(host)
+ lscpu = get_host_lscpu(host)
+ @host_data[host] = lscpu.merge({
+ mhz: (lscpu['cpu-max-mhz'] || lscpu['cpu-mhz']).to_f.round,
+ aes: lscpu['flags'] =~ /aes/ ? 'Yes' : 'No',
+ openssl: get_host_openssl_version(host),
+ }).tap do |data|
+ @log.debug('get_host_data') do
+ JSON.unparse({
+ host: host,
+ data: data,
+ })
+ end
+ end
+ end
+
+ @host_data[host]
+ end
+
+ def get_host_openssl_version(host)
+ File.read('%s/hosts/%s/version.txt' % [
+ out_dir,
+ host,
+ ]).strip.split(/\s+/)[1]
+ end
+
+ #
+ # Parse host lscpu output.
+ #
+ def get_host_lscpu(host)
+ path = '%s/hosts/%s/lscpu.txt' % [out_dir, host]
+
+ File.readlines(path).reduce({}) do |r, line|
+ row = line.strip.split(/:\s+/)
+ key = row[0].downcase
+ .gsub(/\(s\)/, 's')
+ .gsub(/[^a-z0-9-]+/, '-')
+ .gsub(/--/, '-')
+
+ r[key] = row[1]
+
+ r
+ end
+ end
+
#
# Generate and write out/index.html.
#
def save_index_html(html)
File.write('%s/index.html' % [out_dir], TEMPLATES[:index].run({
- title: 'OpenSSL Benchmark Results',
+ title: 'OpenSSL Speed Test Results',
hosts: html[:hosts],
links: LINKS.map { |row|
@@ -881,19 +1010,14 @@ module PiBench
raise err
end
end
-
- #
- # Get output directory.
- #
- def out_dir
- @config['out_dir']
- end
end
#
# Allow one-shot invocation.
#
def self.run(app, args)
+ Luigi::FILTERS[:size] = proc { |v| v.size }
+
# check command-line arguments
unless config_path = args.shift
raise "Usage: #{app} config.yaml"