-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanalyze.py
executable file
·157 lines (148 loc) · 7.02 KB
/
analyze.py
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
148
149
150
151
152
153
154
155
156
#!/usr/bin/env python
#----------------------------------------------------------------------------
# aesbench - Copyright (c) 2024, Thierry Lelegard
# BSD 2-Clause License, see LICENSE file.
# A Python module to analyze results files and produce a table.
#----------------------------------------------------------------------------
import re, os, sys
GIGA = 1000000000.0
SEPARATOR = ' '
##
# Load and analyze a "results" structure.
#
# A "results" structure is a list of dictionaries. Each dictionary describes one test.
# In a test dictionary, the two mandatory fields are 'frequency' (in GHz) and 'file'
# (containing the output of aesbench).
#
# @param [in,out] results List of results. Each result is updated with data from the file.
# @param [in] input_dir Base directory for input file names. All file names are updated.
# @return A list of algorithm names.
#
def load_results(results, input_dir='.'):
algos = []
count = 0
# Load all files.
for res in results:
res['freq'] = '%.2f GHz' % (res['frequency'])
if not 'openssl' in res:
res['openssl'] = ''
res['data'] = {}
res['index'] = count
count += 1
if not os.path.isabs(res['file']):
res['file'] = os.path.abspath(input_dir + os.path.sep + res['file'])
with open(res['file'], 'r') as input:
algo = None
for line in input:
line = [field.strip() for field in line.split(':')]
if len(line) >= 2:
if line[0] == 'algo':
algo = line[1]
if algo.startswith('id-aes'):
algo = 'AES-' + algo[6:]
if algo not in algos:
algos += [algo]
res['data'][algo] = {
'encrypt': {'bitrate': {'value': 0, 'string': '', 'rank': 0},
'bitcycle': {'value': 0.0, 'string': '', 'rank': 0}},
'decrypt': {'bitrate': {'value': 0, 'string': '', 'rank': 0},
'bitcycle': {'value': 0.0, 'string': '', 'rank': 0}}
}
elif line[0] == 'openssl' and not res['openssl']:
match = re.search(r'([0-9\.]+[a-zA-Z]*)', line[1])
if match is not None:
res['openssl'] = match.group(1)
elif (line[0] == 'encrypt-bitrate' or line[0] == 'decrypt-bitrate') and algo is not None:
data = res['data'][algo][line[0].split('-')[0]]
bitcycle = float(line[1]) / (res['frequency'] * GIGA)
data['bitrate']['value'] = int(line[1])
data['bitrate']['string'] = '%.3f' % (float(line[1]) / GIGA)
data['bitcycle']['value'] = bitcycle
if bitcycle >= 10.0:
data['bitcycle']['string'] = '%.1f' % bitcycle
elif bitcycle >= 1.0:
data['bitcycle']['string'] = '%.2f' % bitcycle
else:
data['bitcycle']['string'] = '%.3f' % bitcycle
# Build rankings for each operation.
for algo in algos:
for op in ['encrypt', 'decrypt']:
for value in ['bitrate', 'bitcycle']:
dlist = [(res['index'], res['data'][algo][op][value]['value']) for res in results]
dlist.sort(key=lambda x: x[1], reverse=True)
for rank in range(len(dlist)):
res = next(r for r in results if r['index'] == dlist[rank][0])
res['data'][algo][op][value]['rank'] = rank + 1
for res in results:
res['width'] = 0
res['ranks'] = {'bitrate': {'min': 1000, 'max': 0}, 'bitcycle': {'min': 1000, 'max': 0}}
for algo in algos:
for op in ['encrypt', 'decrypt']:
for value in ['bitrate', 'bitcycle']:
data = res['data'][algo][op][value]
res['ranks'][value]['min'] = min(res['ranks'][value]['min'], data['rank'])
res['ranks'][value]['max'] = max(res['ranks'][value]['max'], data['rank'])
for algo in algos:
for op in ['encrypt', 'decrypt']:
for value in ['bitrate', 'bitcycle']:
data = res['data'][algo][op][value]
space = ' '
if res['ranks'][value]['min'] < 10 and res['ranks'][value]['max'] >= 10 and data['rank'] < 10:
space = ' '
data['string'] += '%s(%d)' % (space, data['rank'])
res['width'] = max(res['width'], len(data['string']))
# End of analysis, return the list of algos.
return algos
##
# Generate a text table of results.
#
# @param [in] results Table results.
# @param [in] algos List of algorithms to display.
# @param [in] headers List of headers, by key from result.
# @param [in] value_name Key of result to display, typically 'bitrate' or 'bitcycle'.
# @param [in] file Output file handler.
# @param [in] colsep Separator between columns.
#
def display_one_table(results, algos, headers, value_name, file, colsep=SEPARATOR):
# Max width of first column.
w0 = max(max([len(s) for s in headers.values()]), max([len(s) for s in algos]) + len(' encrypt'))
# Max line of each column, depending on headers.
for res in results:
res['_width'] = max(res['width'], max([len(res[k]) for k in headers.keys()]))
# Output headers lines.
for k in headers.keys():
line = headers[k].ljust(w0)
for res in results:
line += colsep + res[k].rjust(res['_width'])
print(line.rstrip(), file=file)
line = w0 * '-'
for res in results:
line += colsep + (res['_width'] * '-')
print(line.rstrip(), file=file)
# Output one line per AES operation.
for algo in algos:
for op in ['encrypt', 'decrypt']:
line = (algo + ' ' + op).ljust(w0)
for res in results:
if algo in res['data'] and op in res['data'][algo]:
line += colsep + res['data'][algo][op][value_name]['string'].rjust(res['_width'])
else:
line += colsep + res['_width'] * ' '
print(line.rstrip(), file=file)
##
# Generate the final text file.
#
# @param [in] results Table results.
# @param [in] algos List of algorithms to display.
# @param [in] headers List of headers, by key from result.
# @param [in] file Output file handler.
# @param [in] colsep Separator between columns.
#
def display_tables(results, algos, headers, file, colsep=SEPARATOR):
print('ENCRYPTION / DECRYPTION BITRATE (Gb/s)', file=file)
print('', file=file)
display_one_table(results, algos, headers, 'bitrate', file, colsep)
print('', file=file)
print('ENCRYPTED / DECRYPTED BITS PER PROCESSOR CYCLE', file=file)
print('', file=file)
display_one_table(results, algos, headers, 'bitcycle', file, colsep)