internal class Program { static void Main(string[] args) { ParameterPassingBenchmark.Run(); } } public class ParameterPassingBenchmark { private const int WarmupIterations = 100000; private const int BenchmarkIterations = 10000000; private const int BatchSize = 1000; // 批量调用次数,提高测量精度 private static readonly Random _random = new Random(42);
// x64平台前4个参数通过寄存器传递 [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static int Register4Params(int a, int b, int c, int d) => a + b + c + d;
// 第5个参数通过栈传递 [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static int Stack1Param(int a, int b, int c, int d, int e) => a + b + c + d + e;
// 第5-8个参数通过栈传递 [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static int Stack4Params(int a, int b, int c, int d, int e, int f, int g, int h) => a + b + c + d + e + f + g + h;
public static void Run() { Console.WriteLine($"参数传递性能测试 - 预热: {WarmupIterations:N0}, 测试: {BenchmarkIterations:N0} 次"); Console.WriteLine("----------------------------------------------------------------");
// 生成随机输入数据以避免优化 var inputData = GenerateInputData();
// 预热 Warmup(inputData);
// 测试 var reg4Time = Measure(() => Register4ParamsTest(inputData)); var stack1Time = Measure(() => Stack1ParamTest(inputData)); var stack4Time = Measure(() => Stack4ParamsTest(inputData));
// 输出结果 Console.WriteLine("\n===== 测试结果 ====="); Console.WriteLine($"4寄存器参数: {reg4Time,12:N2} ns/次"); Console.WriteLine($"4寄存器+1栈参数: {stack1Time,10:N2} ns/次 ({((double)stack1Time / reg4Time - 1) * 100:F1}% 性能下降)"); Console.WriteLine($"4寄存器+4栈参数: {stack4Time,10:N2} ns/次 ({((double)stack4Time / reg4Time - 1) * 100:F1}% 性能下降)"); }
private static (int[], int[], int[]) GenerateInputData() { var data4 = new int[BenchmarkIterations * 4]; var data5 = new int[BenchmarkIterations * 5]; var data8 = new int[BenchmarkIterations * 8];
for (int i = 0; i < BenchmarkIterations; i++) { for (int j = 0; j < 4; j++) data4[i * 4 + j] = _random.Next(); for (int j = 0; j < 5; j++) data5[i * 5 + j] = _random.Next(); for (int j = 0; j < 8; j++) data8[i * 8 + j] = _random.Next(); }
return (data4, data5, data8); }
private static void Warmup((int[], int[], int[]) inputData) { Console.Write("预热中..."); var (data4, data5, data8) = inputData;
for (int i = 0; i < WarmupIterations; i++) { Register4Params(data4[i * 4], data4[i * 4 + 1], data4[i * 4 + 2], data4[i * 4 + 3]); Stack1Param(data5[i * 5], data5[i * 5 + 1], data5[i * 5 + 2], data5[i * 5 + 3], data5[i * 5 + 4]); Stack4Params(data8[i * 8], data8[i * 8 + 1], data8[i * 8 + 2], data8[i * 8 + 3], data8[i * 8 + 4], data8[i * 8 + 5], data8[i * 8 + 6], data8[i * 8 + 7]); } Console.WriteLine("完成"); }
private static long Measure(Func<long> testMethod) { // 强制GC并等待完成 GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
// 冷启动 testMethod();
// 实际测量 var stopwatch = Stopwatch.StartNew(); long result = testMethod(); stopwatch.Stop();
// 使用结果以避免被优化掉 if (result == 0) Console.WriteLine("警告: 结果为0,可能存在优化问题");
// 计算平均时间(纳秒) long totalNs = stopwatch.ElapsedTicks * 10000000L / Stopwatch.Frequency; return totalNs / (BenchmarkIterations / BatchSize); // 除以实际调用批次 }
private static long Register4ParamsTest((int[], int[], int[]) inputData) { var (data4, _, _) = inputData; long sum = 0; int index = 0;
for (int i = 0; i < BenchmarkIterations / BatchSize; i++) { // 批量调用以提高测量精度 for (int j = 0; j < BatchSize; j++) { sum += Register4Params( data4[index++], data4[index++], data4[index++], data4[index++] ); } }
return sum; }
private static long Stack1ParamTest((int[], int[], int[]) inputData) { var (_, data5, _) = inputData; long sum = 0; int index = 0;
for (int i = 0; i < BenchmarkIterations / BatchSize; i++) { // 批量调用以提高测量精度 for (int j = 0; j < BatchSize; j++) { sum += Stack1Param( data5[index++], data5[index++], data5[index++], data5[index++], data5[index++] ); } }
return sum; }
private static long Stack4ParamsTest((int[], int[], int[]) inputData) { var (_, _, data8) = inputData; long sum = 0; int index = 0;
for (int i = 0; i < BenchmarkIterations / BatchSize; i++) { // 批量调用以提高测量精度 for (int j = 0; j < BatchSize; j++) { sum += Stack4Params( data8[index++], data8[index++], data8[index++], data8[index++], data8[index++], data8[index++], data8[index++], data8[index++] ); } }
return sum; } }
评论