Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: tcrypt - add script tcrypt_speed_compare.py

Create a script for comparing tcrypt speed test logs.
The script will systematically analyze differences item
by item and provide a summary (average).
This tool is useful for evaluating the stability of
cryptographic module algorithms and assisting with
performance optimization.

Please note that for such a comparison, stability depends
on whether we allow frequency to float or pin the frequency.

The script produces comparisons in two scenes:

1. For operations in seconds
================================================================================
rfc4106(gcm(aes)) (pcrypt(rfc4106(gcm_base(ctr(aes-generic),ghash-generic))))
encryption
--------------------------------------------------------------------------------
bit key | byte blocks | base ops | new ops | differ(%)
160 | 16 | 66439 | 63063 | -5.08
160 | 64 | 62220 | 57439 | -7.68
...
288 | 4096 | 15059 | 16278 | 8.09
288 | 8192 | 9043 | 9526 | 5.34
--------------------------------------------------------------------------------
average differ(%s) | total_differ(%)
--------------------------------------------------------------------------------
5.70 | -4.49
================================================================================

2. For avg cycles of operation
================================================================================
rfc4106(gcm(aes)) (pcrypt(rfc4106(gcm_base(ctr(aes-generic),ghash-generic))))
encryption
--------------------------------------------------------------------------------
bit key | byte blocks | base cycles | new cycles | differ(%)
160 | 16 | 32500 | 35847 | 10.3
160 | 64 | 33175 | 45808 | 38.08
...
288 | 4096 | 131369 | 132132 | 0.58
288 | 8192 | 229503 | 234581 | 2.21
--------------------------------------------------------------------------------
average differ(%s) | total_differ(%)
--------------------------------------------------------------------------------
8.41 | -6.70
================================================================================

Signed-off-by: WangJinchao <wangjinchao@xfusion.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

WangJinchao and committed by
Herbert Xu
bfcec4c6 3139ebf7

+196
+6
MAINTAINERS
··· 5536 5536 F: include/linux/crypto* 5537 5537 F: lib/crypto/ 5538 5538 5539 + CRYPTO SPEED TEST COMPARE 5540 + M: Wang Jinchao <wangjinchao@xfusion.com> 5541 + L: linux-crypto@vger.kernel.org 5542 + S: Maintained 5543 + F: tools/crypto/tcrypt/tcrypt_speed_compare.py 5544 + 5539 5545 CRYPTOGRAPHIC RANDOM NUMBER GENERATOR 5540 5546 M: Neil Horman <nhorman@tuxdriver.com> 5541 5547 L: linux-crypto@vger.kernel.org
+190
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])