如何在Python中仅编译一次C#代码并多次执行以优化排序测试?
解决C#冒泡排序测试中重复编译导致的耗时异常问题
问题根源
你当前用dotnet run执行C#代码时,每次都会触发重新编译,编译时间被计入了排序测试的总耗时,这就是数据异常的原因。提前编译一次C#程序,之后多次直接运行编译好的可执行文件并传入不同参数是完全可行的,这样测得的耗时就只包含排序逻辑的执行时间,曲线趋势会和其他语言的测试结果一致。
具体实现步骤
1. 提前编译C#程序
先通过dotnet build命令编译出优化后的可执行文件(推荐用Release模式,避免Debug模式的性能损耗)。可以手动在CSharp目录下执行:
dotnet build -c Release
编译完成后,可执行文件的路径根据系统不同略有差异:
- Windows:
CSharp/bin/Release/netX.X/BubbleSort.exe(netX.X替换为你的.NET版本,比如net6.0) - Linux/macOS:
CSharp/bin/Release/netX.X/BubbleSort
2. 修改Python调用代码
调整后的函数会先完成编译(仅执行一次),之后循环调用已编译的可执行文件,避免重复编译:
import time import subprocess csharpTimes = [] def runCSharp(debug): # 先编译C#程序,仅执行一次 build_args = ['dotnet', 'build', '-c', 'Release'] build_p = subprocess.Popen(build_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', cwd="CSharp") build_out, build_err = build_p.communicate() if debug: print("编译输出:", build_out) if build_err: print("编译错误:", build_err) # 根据系统选择可执行文件路径,注释掉不需要的那一行 exe_path = "CSharp/bin/Release/net6.0/BubbleSort.exe" # Windows # exe_path = "CSharp/bin/Release/net6.0/BubbleSort" # Linux/macOS for size in range(1000, 10001, 1000): if debug: print("开始排序", size, "个整数") tic = time.time() # 直接运行编译好的可执行文件,传入参数 args = [exe_path, str(size)] p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8') output, err = p.communicate() toc = time.time() # 修正原代码中计时位置错误 if debug: print(output) if err: print(err) print("C#冒泡排序耗时:%0.6f 秒" % (toc - tic)) csharpTimes.append(toc - tic) return csharpTimes
3. 额外优化建议
- 修正C#文件路径:原C#代码中
StreamReader的路径是相对路径,编译后运行可能找不到文件,可以改成基于程序目录的动态路径:string appDir = AppDomain.CurrentDomain.BaseDirectory; string filePath = Path.Combine(appDir, @"../../../../numbers.txt"); reader = new StreamReader(filePath); - 坚持用Release编译:Debug模式包含调试检查,会拖慢运行速度,Release模式是优化后的版本,更符合性能测试的要求。
可行性说明
这种方案完全可行。提前编译后,每次运行的都是二进制可执行文件,不再包含编译环节的耗时,此时测得的排序耗时会严格遵循冒泡排序O(n²)的时间复杂度,曲线趋势会和其他语言的测试结果一致。
内容的提问来源于stack exchange,提问作者NyanSequitur
相关产品推荐
相关产品推荐

