GNU Linux-libre 6.8.7-gnu
[releases.git] / tools / crypto / tcrypt / tcrypt_speed_compare.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: GPL-2.0
3 #
4 # Copyright (C) xFusion Digital Technologies Co., Ltd., 2023
5 #
6 # Author: Wang Jinchao <wangjinchao@xfusion.com>
7 #
8 """
9 A tool for comparing tcrypt speed test logs.
10
11 Please note that for such a comparison, stability depends
12 on whether we allow frequency to float or pin the frequency.
13
14 Both support tests for operations within one second and
15 cycles of operation.
16 For example, use it in the bash script below.
17
18 ```bash
19 #!/bin/bash
20
21 # log file prefix
22 seq_num=0
23
24 # When sec=0, it will perform cycle tests;
25 # otherwise, it indicates the duration of a single test
26 sec=0
27 num_mb=8
28 mode=211
29
30 # base speed test
31 lsmod | grep pcrypt && modprobe -r pcrypt
32 dmesg -C
33 modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3
34 modprobe tcrypt mode=${mode} sec=${sec} num_mb=${num_mb}
35 dmesg > ${seq_num}_base_dmesg.log
36
37 # new speed test
38 lsmod | grep pcrypt && modprobe -r pcrypt
39 dmesg -C
40 modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3
41 modprobe tcrypt mode=${mode} sec=${sec} num_mb=${num_mb}
42 dmesg > ${seq_num}_new_dmesg.log
43 lsmod | grep pcrypt && modprobe -r pcrypt
44
45 tools/crypto/tcrypt/tcrypt_speed_compare.py \
46     ${seq_num}_base_dmesg.log \
47     ${seq_num}_new_dmesg.log  \
48         >${seq_num}_compare.log
49 grep 'average' -A2 -B0 --group-separator="" ${seq_num}_compare.log
50 ```
51 """
52
53 import sys
54 import re
55
56
57 def parse_title(line):
58     pattern = r'tcrypt: testing speed of (.*?) (encryption|decryption)'
59     match = re.search(pattern, line)
60     if match:
61         alg = match.group(1)
62         op = match.group(2)
63         return alg, op
64     else:
65         return "", ""
66
67
68 def parse_item(line):
69     pattern_operations = r'\((\d+) bit key, (\d+) byte blocks\): (\d+) operations'
70     pattern_cycles = r'\((\d+) bit key, (\d+) byte blocks\): 1 operation in (\d+) cycles'
71     match = re.search(pattern_operations, line)
72     if match:
73         res = {
74             "bit_key": int(match.group(1)),
75             "byte_blocks": int(match.group(2)),
76             "operations": int(match.group(3)),
77         }
78         return res
79
80     match = re.search(pattern_cycles, line)
81     if match:
82         res = {
83             "bit_key": int(match.group(1)),
84             "byte_blocks": int(match.group(2)),
85             "cycles": int(match.group(3)),
86         }
87         return res
88
89     return None
90
91
92 def parse(filepath):
93     result = {}
94     alg, op = "", ""
95     with open(filepath, 'r') as file:
96         for line in file:
97             if not line:
98                 continue
99             _alg, _op = parse_title(line)
100             if _alg:
101                 alg, op = _alg, _op
102                 if alg not in result:
103                     result[alg] = {}
104                 if op not in result[alg]:
105                     result[alg][op] = []
106                 continue
107             parsed_result = parse_item(line)
108             if parsed_result:
109                 result[alg][op].append(parsed_result)
110     return result
111
112
113 def merge(base, new):
114     merged = {}
115     for alg in base.keys():
116         merged[alg] = {}
117         for op in base[alg].keys():
118             if op not in merged[alg]:
119                 merged[alg][op] = []
120             for index in range(len(base[alg][op])):
121                 merged_item = {
122                     "bit_key": base[alg][op][index]["bit_key"],
123                     "byte_blocks": base[alg][op][index]["byte_blocks"],
124                 }
125                 if "operations" in base[alg][op][index].keys():
126                     merged_item["base_ops"] = base[alg][op][index]["operations"]
127                     merged_item["new_ops"] = new[alg][op][index]["operations"]
128                 else:
129                     merged_item["base_cycles"] = base[alg][op][index]["cycles"]
130                     merged_item["new_cycles"] = new[alg][op][index]["cycles"]
131
132                 merged[alg][op].append(merged_item)
133     return merged
134
135
136 def format(merged):
137     for alg in merged.keys():
138         for op in merged[alg].keys():
139             base_sum = 0
140             new_sum = 0
141             differ_sum = 0
142             differ_cnt = 0
143             print()
144             hlen = 80
145             print("="*hlen)
146             print(f"{alg}")
147             print(f"{' '*(len(alg)//3) + op}")
148             print("-"*hlen)
149             key = ""
150             if "base_ops" in merged[alg][op][0]:
151                 key = "ops"
152                 print(f"bit key | byte blocks | base ops    | new ops     | differ(%)")
153             else:
154                 key = "cycles"
155                 print(f"bit key | byte blocks | base cycles | new cycles  | differ(%)")
156             for index in range(len(merged[alg][op])):
157                 item = merged[alg][op][index]
158                 base_cnt = item[f"base_{key}"]
159                 new_cnt = item[f"new_{key}"]
160                 base_sum += base_cnt
161                 new_sum += new_cnt
162                 differ = round((new_cnt - base_cnt)*100/base_cnt, 2)
163                 differ_sum += differ
164                 differ_cnt += 1
165                 bit_key = item["bit_key"]
166                 byte_blocks = item["byte_blocks"]
167                 print(
168                     f"{bit_key:<7} | {byte_blocks:<11} | {base_cnt:<11} | {new_cnt:<11} | {differ:<8}")
169             average_speed_up = "{:.2f}".format(differ_sum/differ_cnt)
170             ops_total_speed_up = "{:.2f}".format(
171                 (base_sum - new_sum) * 100 / base_sum)
172             print('-'*hlen)
173             print(f"average differ(%s)    | total_differ(%)")
174             print('-'*hlen)
175             print(f"{average_speed_up:<21} | {ops_total_speed_up:<10}")
176             print('='*hlen)
177
178
179 def main(base_log, new_log):
180     base = parse(base_log)
181     new = parse(new_log)
182     merged = merge(base, new)
183     format(merged)
184
185
186 if __name__ == "__main__":
187     if len(sys.argv) != 3:
188         print(f"usage: {sys.argv[0]} base_log new_log")
189         exit(-1)
190     main(sys.argv[1], sys.argv[2])