Files
wordZero/benchmark/python/benchmark_test.py
zero 3114980412 - 增加基准测试
- 修复模板继承问题
- 优化wiki文档
2025-06-02 15:00:06 +08:00

328 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Python Word操作性能基准测试
使用python-docx库进行Word文档操作的性能测试
与Golang WordZero库进行对比。
"""
import os
import sys
import time
import json
import tracemalloc
import psutil
from pathlib import Path
from typing import List, Dict, Any
from datetime import datetime
import pytest
from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
# 确保输出目录存在
OUTPUT_DIR = Path("../results/python")
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
# 统一的测试配置,与其他语言保持一致
TEST_ITERATIONS = {
"basic": 50, # 基础文档创建
"complex": 30, # 复杂格式化
"table": 20, # 表格操作
"largeTable": 10, # 大表格处理
"largeDoc": 5, # 大型文档
"memory": 10, # 内存使用测试
}
class PerformanceTester:
"""性能测试工具类"""
def __init__(self):
self.results = []
def run_test(self, name: str, test_function, iterations: int = 10):
"""运行性能测试"""
print(f"\n开始测试: {name}")
times = []
for i in range(iterations):
start_time = time.perf_counter()
test_function(i)
end_time = time.perf_counter()
duration = (end_time - start_time) * 1000 # 转换为毫秒
times.append(duration)
if i % max(1, iterations // 10) == 0:
print(f" 进度: {i + 1}/{iterations}")
avg_time = sum(times) / len(times)
min_time = min(times)
max_time = max(times)
result = {
'name': name,
'avgTime': round(avg_time, 2),
'minTime': round(min_time, 2),
'maxTime': round(max_time, 2),
'iterations': iterations
}
self.results.append(result)
print(f" 平均耗时: {result['avgTime']}ms")
print(f" 最小耗时: {result['minTime']}ms")
print(f" 最大耗时: {result['maxTime']}ms")
return result
def generate_report(self):
"""生成性能测试报告"""
print('\n=== Python 性能测试报告 ===')
for result in self.results:
print(f"{result['name']}: {result['avgTime']}ms (平均)")
# 保存详细报告
report_path = OUTPUT_DIR / 'performance_report.json'
report_data = {
'timestamp': datetime.now().isoformat(),
'platform': 'Python',
'pythonVersion': f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
'results': self.results
}
with open(report_path, 'w', encoding='utf-8') as f:
json.dump(report_data, f, indent=2, ensure_ascii=False)
print(f"\n详细报告已保存到: {report_path}")
def test_basic_document_creation(index: int):
"""基础文档创建测试"""
doc = Document()
doc.add_paragraph("这是一个基础性能测试文档")
doc.add_paragraph("测试内容包括基本的文本添加功能")
filename = OUTPUT_DIR / f"basic_doc_{index}.docx"
doc.save(filename)
def test_complex_formatting(index: int):
"""复杂格式化测试"""
doc = Document()
# 添加标题
title = doc.add_heading("性能测试报告", level=1)
subtitle = doc.add_heading("测试概述", level=2)
# 添加格式化文本
para = doc.add_paragraph()
# 粗体文本
run = para.add_run("粗体文本")
run.bold = True
para.add_run(" ")
# 斜体文本
run = para.add_run("斜体文本")
run.italic = True
para.add_run(" ")
# 彩色文本
run = para.add_run("彩色文本")
run.font.color.rgb = RGBColor(255, 0, 0) # 红色
# 添加多个格式化段落
for j in range(10):
para = doc.add_paragraph(f"这是第{j + 1}个段落,包含复杂格式化")
para.alignment = WD_ALIGN_PARAGRAPH.CENTER
filename = OUTPUT_DIR / f"complex_formatting_{index}.docx"
doc.save(filename)
def test_table_operations(index: int):
"""表格操作测试"""
doc = Document()
# 添加标题
doc.add_heading("表格性能测试", level=1)
# 创建10行5列的表格
table = doc.add_table(rows=10, cols=5)
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# 填充表格数据
for row_idx, row in enumerate(table.rows):
for col_idx, cell in enumerate(row.cells):
cell.text = f"R{row_idx + 1}C{col_idx + 1}"
filename = OUTPUT_DIR / f"table_operations_{index}.docx"
doc.save(filename)
def test_large_table(index: int):
"""大表格测试"""
doc = Document()
# 添加标题
doc.add_heading("大表格性能测试", level=1)
# 创建100行10列的大表格
table = doc.add_table(rows=100, cols=10)
table.alignment = WD_TABLE_ALIGNMENT.CENTER
# 填充表格数据
for row_idx, row in enumerate(table.rows):
for col_idx, cell in enumerate(row.cells):
cell.text = f"数据_{row_idx + 1}_{col_idx + 1}"
filename = OUTPUT_DIR / f"large_table_{index}.docx"
doc.save(filename)
def test_large_document(index: int):
"""大型文档测试"""
doc = Document()
# 添加主标题
doc.add_heading("大型文档性能测试", level=1)
# 添加1000个段落
for j in range(1000):
if j % 10 == 0:
# 每10个段落添加一个标题
doc.add_heading(f"章节 {j // 10 + 1}", level=2)
doc.add_paragraph(
f"这是第{j + 1}个段落。Lorem ipsum dolor sit amet, consectetur "
f"adipiscing elit. Sed do eiusmod tempor incididunt ut labore et "
f"dolore magna aliqua."
)
# 添加一个中等大小的表格
table = doc.add_table(rows=20, cols=8)
for row_idx, row in enumerate(table.rows):
for col_idx, cell in enumerate(row.cells):
cell.text = f"表格数据{row_idx + 1}-{col_idx + 1}"
filename = OUTPUT_DIR / f"large_document_{index}.docx"
doc.save(filename)
def test_memory_usage(index: int):
"""内存使用测试"""
# 开始内存追踪
tracemalloc.start()
initial_memory = tracemalloc.get_traced_memory()[0]
doc = Document()
# 创建复杂内容
for j in range(100):
doc.add_paragraph(f"段落{j + 1}: 这是一个测试段落,用于测试内存使用情况")
# 添加表格
table = doc.add_table(rows=50, cols=6)
for row_idx, row in enumerate(table.rows):
for col_idx, cell in enumerate(row.cells):
cell.text = f"单元格{row_idx + 1}-{col_idx + 1}"
# 保存文档
filename = OUTPUT_DIR / f"memory_test_{index}.docx"
doc.save(filename)
# 检查内存使用
final_memory = tracemalloc.get_traced_memory()[0]
if index == 0:
memory_used = (final_memory - initial_memory) / 1024 # 转换为KB
print(f" 内存使用: {memory_used:.0f}KB")
tracemalloc.stop()
# pytest benchmark 测试函数
def test_benchmark_basic_document(benchmark):
"""pytest-benchmark: 基础文档创建"""
benchmark(test_basic_document_creation, 0)
def test_benchmark_complex_formatting(benchmark):
"""pytest-benchmark: 复杂格式化"""
benchmark(test_complex_formatting, 0)
def test_benchmark_table_operations(benchmark):
"""pytest-benchmark: 表格操作"""
benchmark(test_table_operations, 0)
def test_benchmark_large_table(benchmark):
"""pytest-benchmark: 大表格"""
benchmark(test_large_table, 0)
def test_benchmark_large_document(benchmark):
"""pytest-benchmark: 大型文档"""
benchmark(test_large_document, 0)
def test_benchmark_memory_usage(benchmark):
"""pytest-benchmark: 内存使用"""
benchmark(test_memory_usage, 0)
class TestPerformanceComparison:
"""性能对比测试类"""
def test_performance_comparison(self):
"""运行完整的性能对比测试"""
print('开始 Python (python-docx库) 性能基准测试...')
print(f'Python 版本: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')
print(f'输出目录: {OUTPUT_DIR}')
tester = PerformanceTester()
# 运行各项测试(使用统一的迭代次数配置)
tester.run_test('基础文档创建', test_basic_document_creation, TEST_ITERATIONS["basic"])
tester.run_test('复杂格式化', test_complex_formatting, TEST_ITERATIONS["complex"])
tester.run_test('表格操作', test_table_operations, TEST_ITERATIONS["table"])
tester.run_test('大表格处理', test_large_table, TEST_ITERATIONS["largeTable"])
tester.run_test('大型文档', test_large_document, TEST_ITERATIONS["largeDoc"])
tester.run_test('内存使用测试', test_memory_usage, TEST_ITERATIONS["memory"])
# 生成报告
tester.generate_report()
def main():
"""主函数,直接运行时执行"""
print("开始 Python 性能基准测试...")
tester = PerformanceTester()
try:
# 使用统一的迭代次数配置
tester.run_test('基础文档创建', test_basic_document_creation, TEST_ITERATIONS["basic"])
tester.run_test('复杂格式化', test_complex_formatting, TEST_ITERATIONS["complex"])
tester.run_test('表格操作', test_table_operations, TEST_ITERATIONS["table"])
tester.run_test('大表格处理', test_large_table, TEST_ITERATIONS["largeTable"])
tester.run_test('大型文档', test_large_document, TEST_ITERATIONS["largeDoc"])
tester.run_test('内存使用测试', test_memory_usage, TEST_ITERATIONS["memory"])
tester.generate_report()
print('\n所有测试完成!')
except Exception as e:
print(f'测试过程中发生错误: {e}')
raise
if __name__ == '__main__':
main()