替换大字符串中的多个字符串的最快方法

2024-06-30

我正在寻找替换大(~1mb)字符串的多个(~500)子字符串的最快方法。无论我尝试过什么,String.Replace 似乎都是最快的方法。

我只关心最快的方式。不是代码的可读性、可维护性等。我不在乎是否需要使用不安全的代码或预处理原始字符串。

每次替换迭代都会将字符串上的 ABC 替换为其他字符串(每次替换迭代都不同)。要替换的字符串将始终相同 - ABC 将始终是 ABC。从来没有ABD。所以如果有400.000数千次替换迭代。相同的字符串 - ABC - 每次都会被替换为其他(不同的)字符串。

我可以控制 ABC 是什么。我可以把它弄得超短或超长,只要不影响结果。显然 ABC 不能hello因为 hello 在大多数输入字符串中都会作为单词存在。

输入示例:ABCDABCABCDABCABCDABCABCDABCD

从字符串替换示例:BC

用字符串替换示例:AA, BB, CC, DD, EE (5 iterations)

示例输出:

AAADAAAAAADAAAAAADAAAAAADAAAD
ABBDABBABBDABBABBDABBABBDABBD
ACCDACCACCDACCACCDACCACCDACCD
ADDDADDADDDADDADDDADDADDDADDD
AEEDAEEAEEDAEEAEEDAEEAEEDAEED

平均情况:输入字符串为 100-200kb,具有 40.000 次替换迭代。 最坏情况:输入字符串为 1-2mb,有 400.000 次替换迭代。

我什么事都能做。并行执行、不安全执行等等。我如何执行并不重要。重要的是它需要尽可能快。


Using unsafe并编译为 x64

result:

Implementation       | Exec   | GC
#1 Simple            | 4706ms |  0ms
#2 Simple parallel   | 2265ms |  0ms
#3 ParallelSubstring |  800ms | 21ms
#4 Fredou unsafe     |  432ms | 15ms

取代码Erti-Chris Eelmaa并用这个替换我之前的。

我不认为我会进行另一次迭代,但我确实学到了一些不安全的东西,这是一件好事:-)

    private unsafe static void FredouImplementation(string input, int inputLength, string replace, string[] replaceBy)
    {
        var indexes = new List<int>();

        //input = "ABCDABCABCDABCABCDABCABCDABCD";
        //inputLength = input.Length;
        //replaceBy = new string[] { "AA", "BB", "CC", "DD", "EE" };

        //my own string.indexof to save a few ms
        int len = inputLength;

        fixed (char* i = input, r = replace)
        {
            int replaceValAsInt = *((int*)r);

            while (--len > -1)
            {
                if (replaceValAsInt == *((int*)&i[len]))
                {
                    indexes.Add(len--);
                }
            }                
        }

        var idx = indexes.ToArray();
        len = indexes.Count;

        Parallel.For(0, replaceBy.Length, l =>
            Process(input, inputLength, replaceBy[l], idx, len)
        );
    }

    private unsafe static void Process(string input, int len, string replaceBy, int[] idx, int idxLen)
    {
        var output = new char[len];

        fixed (char* o = output, i = input, r = replaceBy)
        {
            int replaceByValAsInt = *((int*)r);

            //direct copy, simulate string.copy
            while (--len > -1)
            {
                o[len] = i[len];
            }

            while (--idxLen > -1)
            {
                ((int*)&o[idx[idxLen]])[0] = replaceByValAsInt;
            }
        }

        //Console.WriteLine(output);
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

替换大字符串中的多个字符串的最快方法 的相关文章

随机推荐