优化Benchmark测试初始参数

起因

在 <<在.Net 7中String的Equals和StartWith性能优化>> 一文中,今天在看初始化性能基准测试参数代码时,感觉这一块还是可以调整一下的.

本文比较水,优化代码的方式可以以前写的文章: 编码中代码优化 ,使用硬件指令优化,是这几年.Net社区一直在做的事情,从.Net Core 3.1开始,到.Net 7(从X86到ARM,使用更多的硬件指令优化).
看最近在ARM架构优化:
.Net 7 针对ARM架构使用了指令优化

调整后代码

namespace net6perf.StringFunction
{
    [DisassemblyDiagnoser(printSource: true, maxDepth: 3)]
    [MemoryDiagnoser]
    public class CharTest
    {
        [Params(1024, 2048, 4096)]
        public int Count;

        /// <summary>
        /// 第一版
        /// </summary>
        [Benchmark]
        public void Test1()
        {
            char[] chars = new char[52];
            for (int i = 0; i < Count; i++)
            {
                int index = 0;
                for (int j = 65; j < 123; j++)
                {
                    if (j > 90 && j < 97)
                    {
                        continue;
                    }

                    chars[index] = (char)j;
                    index++;
                }
            }
        }

        /// <summary>
        /// 第二版 减少循环中判断,提高CPU分支预测的命中率
        /// 将循环拆分为2个循环
        /// </summary>
        [Benchmark]
        public void Test2()
        {
            char[] chars = new char[52];
            for (int i = 0; i < Count; i++)
            {
                for (int j = 0; j < 26; j++)
                {
                    chars[j] = (char)(j + 65);
                }
                for (int j = 0; j < 26; j++)
                {
                    chars[j + 26] = (char)(j + 97);
                }
            }
        }

        /// <summary>
        /// 第三版 循环展开,减少循环的次数 
        /// 1. 一次处理 chars[0] ='A'; chars[26] = 'a';
        /// 2. 减少计算次数 (char)j+65
        /// 3. 减少加法运算,使用位或运算
        /// </summary>
        [Benchmark]
        public void Test3()
        {
            char[] chars = new char[52];
            for (int i = 0; i < Count; i++)
            {
                for (int j = 0; j < 26; j++)
                {
                    char c = (char)(j + 65);
                    chars[j] = c;
                    chars[j + 26] = (char)(c | 32);
                }
            }
        }
    }
}

BenchmarkDotNet性能基准测试结果.

通过在循环中减少判断分支和循环展开,性能提升还是明显的
Test2将循环拆分为2个,不在进行条件判断,在性能上比Test1提高3倍多,Test3比Test2提升不明显,提高了3微妙.

秋风 2022-02-20