| #!/usr/bin/env python3 | |
| # SPDX-License-Identifier: GPL-2.0 | |
| # | |
| # Copyright (C) xFusion Digital Technologies Co., Ltd., 2023 | |
| # | |
| # Author: Wang Jinchao <wangjinchao@xfusion.com> | |
| # | |
| """ | |
| A tool for comparing tcrypt speed test logs. | |
| Please note that for such a comparison, stability depends | |
| on whether we allow frequency to float or pin the frequency. | |
| Both support tests for operations within one second and | |
| cycles of operation. | |
| For example, use it in the bash script below. | |
| ```bash | |
| #!/bin/bash | |
| # log file prefix | |
| seq_num=0 | |
| # When sec=0, it will perform cycle tests; | |
| # otherwise, it indicates the duration of a single test | |
| sec=0 | |
| num_mb=8 | |
| mode=211 | |
| # base speed test | |
| lsmod | grep pcrypt && modprobe -r pcrypt | |
| dmesg -C | |
| modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3 | |
| modprobe tcrypt mode=${mode} sec=${sec} num_mb=${num_mb} | |
| dmesg > ${seq_num}_base_dmesg.log | |
| # new speed test | |
| lsmod | grep pcrypt && modprobe -r pcrypt | |
| dmesg -C | |
| modprobe tcrypt alg="pcrypt(rfc4106(gcm(aes)))" type=3 | |
| modprobe tcrypt mode=${mode} sec=${sec} num_mb=${num_mb} | |
| dmesg > ${seq_num}_new_dmesg.log | |
| lsmod | grep pcrypt && modprobe -r pcrypt | |
| tools/crypto/tcrypt/tcrypt_speed_compare.py \ | |
| ${seq_num}_base_dmesg.log \ | |
| ${seq_num}_new_dmesg.log \ | |
| >${seq_num}_compare.log | |
| grep 'average' -A2 -B0 --group-separator="" ${seq_num}_compare.log | |
| ``` | |
| """ | |
| import sys | |
| import re | |
| def parse_title(line): | |
| pattern = r'tcrypt: testing speed of (.*?) (encryption|decryption)' | |
| match = re.search(pattern, line) | |
| if match: | |
| alg = match.group(1) | |
| op = match.group(2) | |
| return alg, op | |
| else: | |
| return "", "" | |
| def parse_item(line): | |
| pattern_operations = r'\((\d+) bit key, (\d+) byte blocks\): (\d+) operations' | |
| pattern_cycles = r'\((\d+) bit key, (\d+) byte blocks\): 1 operation in (\d+) cycles' | |
| match = re.search(pattern_operations, line) | |
| if match: | |
| res = { | |
| "bit_key": int(match.group(1)), | |
| "byte_blocks": int(match.group(2)), | |
| "operations": int(match.group(3)), | |
| } | |
| return res | |
| match = re.search(pattern_cycles, line) | |
| if match: | |
| res = { | |
| "bit_key": int(match.group(1)), | |
| "byte_blocks": int(match.group(2)), | |
| "cycles": int(match.group(3)), | |
| } | |
| return res | |
| return None | |
| def parse(filepath): | |
| result = {} | |
| alg, op = "", "" | |
| with open(filepath, 'r') as file: | |
| for line in file: | |
| if not line: | |
| continue | |
| _alg, _op = parse_title(line) | |
| if _alg: | |
| alg, op = _alg, _op | |
| if alg not in result: | |
| result[alg] = {} | |
| if op not in result[alg]: | |
| result[alg][op] = [] | |
| continue | |
| parsed_result = parse_item(line) | |
| if parsed_result: | |
| result[alg][op].append(parsed_result) | |
| return result | |
| def merge(base, new): | |
| merged = {} | |
| for alg in base.keys(): | |
| merged[alg] = {} | |
| for op in base[alg].keys(): | |
| if op not in merged[alg]: | |
| merged[alg][op] = [] | |
| for index in range(len(base[alg][op])): | |
| merged_item = { | |
| "bit_key": base[alg][op][index]["bit_key"], | |
| "byte_blocks": base[alg][op][index]["byte_blocks"], | |
| } | |
| if "operations" in base[alg][op][index].keys(): | |
| merged_item["base_ops"] = base[alg][op][index]["operations"] | |
| merged_item["new_ops"] = new[alg][op][index]["operations"] | |
| else: | |
| merged_item["base_cycles"] = base[alg][op][index]["cycles"] | |
| merged_item["new_cycles"] = new[alg][op][index]["cycles"] | |
| merged[alg][op].append(merged_item) | |
| return merged | |
| def format(merged): | |
| for alg in merged.keys(): | |
| for op in merged[alg].keys(): | |
| base_sum = 0 | |
| new_sum = 0 | |
| differ_sum = 0 | |
| differ_cnt = 0 | |
| print() | |
| hlen = 80 | |
| print("="*hlen) | |
| print(f"{alg}") | |
| print(f"{' '*(len(alg)//3) + op}") | |
| print("-"*hlen) | |
| key = "" | |
| if "base_ops" in merged[alg][op][0]: | |
| key = "ops" | |
| print(f"bit key | byte blocks | base ops | new ops | differ(%)") | |
| else: | |
| key = "cycles" | |
| print(f"bit key | byte blocks | base cycles | new cycles | differ(%)") | |
| for index in range(len(merged[alg][op])): | |
| item = merged[alg][op][index] | |
| base_cnt = item[f"base_{key}"] | |
| new_cnt = item[f"new_{key}"] | |
| base_sum += base_cnt | |
| new_sum += new_cnt | |
| differ = round((new_cnt - base_cnt)*100/base_cnt, 2) | |
| differ_sum += differ | |
| differ_cnt += 1 | |
| bit_key = item["bit_key"] | |
| byte_blocks = item["byte_blocks"] | |
| print( | |
| f"{bit_key:<7} | {byte_blocks:<11} | {base_cnt:<11} | {new_cnt:<11} | {differ:<8}") | |
| average_speed_up = "{:.2f}".format(differ_sum/differ_cnt) | |
| ops_total_speed_up = "{:.2f}".format( | |
| (base_sum - new_sum) * 100 / base_sum) | |
| print('-'*hlen) | |
| print(f"average differ(%s) | total_differ(%)") | |
| print('-'*hlen) | |
| print(f"{average_speed_up:<21} | {ops_total_speed_up:<10}") | |
| print('='*hlen) | |
| def main(base_log, new_log): | |
| base = parse(base_log) | |
| new = parse(new_log) | |
| merged = merge(base, new) | |
| format(merged) | |
| if __name__ == "__main__": | |
| if len(sys.argv) != 3: | |
| print(f"usage: {sys.argv[0]} base_log new_log") | |
| exit(-1) | |
| main(sys.argv[1], sys.argv[2]) |