当前位置:  开发笔记 > 编程语言 > 正文

String.Replace .NET Framework的内存效率和性能

如何解决《String.Replace.NETFramework的内存效率和性能》经验,为你挑选了2个好方法。

.NET字符串中的所有字符都是"unicode chars".你的意思是他们不是ascii吗?这不应该有任何可能性 - 除非你遇到组合问题,例如当你试图取代"急性"时不会被替换为"e +急性重音".

您可以尝试使用正则表达式Regex.Replace,或StringBuilder.Replace.这里的示例代码与两者做同样的事情:

using System;
using System.Text;
using System.Text.RegularExpressions;

class Test
{
    static void Main(string[] args)
    {
        string original = "abcdefghijkl";

        Regex regex = new Regex("a|c|e|g|i|k", RegexOptions.Compiled);

        string removedByRegex = regex.Replace(original, "");
        string removedByStringBuilder = new StringBuilder(original)
            .Replace("a", "")
            .Replace("c", "")
            .Replace("e", "")
            .Replace("g", "")
            .Replace("i", "")
            .Replace("k", "")
            .ToString();

        Console.WriteLine(removedByRegex);
        Console.WriteLine(removedByStringBuilder);
    }
}

我不想猜哪个更有效 - 你必须根据你的具体应用进行基准测试.正则表达式方式可以在一次传递中完成所有操作,但与StringBuilder中的许多替换相比,该传递将相对CPU密集.



1> Jon Skeet..:

.NET字符串中的所有字符都是"unicode chars".你的意思是他们不是ascii吗?这不应该有任何可能性 - 除非你遇到组合问题,例如当你试图取代"急性"时不会被替换为"e +急性重音".

您可以尝试使用正则表达式Regex.Replace,或StringBuilder.Replace.这里的示例代码与两者做同样的事情:

using System;
using System.Text;
using System.Text.RegularExpressions;

class Test
{
    static void Main(string[] args)
    {
        string original = "abcdefghijkl";

        Regex regex = new Regex("a|c|e|g|i|k", RegexOptions.Compiled);

        string removedByRegex = regex.Replace(original, "");
        string removedByStringBuilder = new StringBuilder(original)
            .Replace("a", "")
            .Replace("c", "")
            .Replace("e", "")
            .Replace("g", "")
            .Replace("i", "")
            .Replace("k", "")
            .ToString();

        Console.WriteLine(removedByRegex);
        Console.WriteLine(removedByStringBuilder);
    }
}

我不想猜哪个更有效 - 你必须根据你的具体应用进行基准测试.正则表达式方式可以在一次传递中完成所有操作,但与StringBuilder中的许多替换相比,该传递将相对CPU密集.


@Ahmed:我宁愿相信实际的基准而不仅仅是收到的智慧 - 我怀疑它依赖于数据*.
@Atømix:不,编译器不会将""更改为String.Empty.他们*是*不同的东西......我碰巧发现""更具可读性.

2> John Leidegr..:

如果你想要非常快,我的意思是非常快,你必须超越StringBuilder并编写优秀的代码.

你的计算机不喜欢做的一件事就是分支,如果你可以编写一个在固定数组(char*)上运行的替换方法而且没有分支你就有很好的性能.

你要做的是替换操作将搜索一系列字符,如果找到任何这样的子字符串,它将替换它.实际上,您将复制字符串,并在执行此操作时,执行查找和替换.

您将依赖这些函数来选择一些缓冲区的索引来读/写.目标是预先形成替换方法,这样当没有什么必须改变时,你写垃圾而不是分支.

您应该能够在没有单个if语句的情况下完成此操作并记住使用不安全的代码.否则,您将为每个元素访问支付索引检查费用.

unsafe
{
    fixed( char * p = myStringBuffer )
    {
        // Do fancy string manipulation here
    }
}

我在C#中编写了这样的代码以获得乐趣,并且看到了显着的性能改进,几乎300%的速度用于查找和替换.虽然.NET BCL(基类库)执行得很好,但它充满了分支结构和异常处理,如果你使用内置的东西,这将减慢代码的速度.此外,JIT编译器不会执行完美声音的这些优化,您必须将代码作为发布版本运行,而无需附加任何调试器,以便能够观察到大量的性能提升.

我可以为您提供更完整的代码,但这是一项大量的工作.但是,我可以向您保证,它将比目前为止提出的任何其他建议更快.


如果您仔细查看实际的实现,可以做一些事情,但是很遗憾,我没有CLR源的访问权限。我敢打赌,这很好,但并不特别。通过不确定基于后缀数组的实现,可以更快地解决大字符串中的替换问题,尽管不确定是否存在引爆点,但即使是最琐碎的线性搜索算法,也可以通过利用托管中没有的新硬件和内在函数来更快地完成码。您可以付出很多努力并使其更快,但是在某些时候很难捍卫您花费在它上面的时间。
推荐阅读
跟我搞对象吧
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有