| #!/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]) |