本文介绍了使用StringBuilder的删除方法更多的内存比创建循环中的一个新的StringBuilder效率?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C#这是更多的内存效率:选项1或选项2



 公共无效TestStringBuilder()$ B? $ b {
//可能与几百项的集合:
的String [] = outputStrings新的字符串[] {测试1,测试2,TEST3};

//选项#1
StringBuilder的formattedOutput =新的StringBuilder();
的foreach(在outputStrings串outputString)
{
formattedOutput.Append(前​​缀);
formattedOutput.Append(outputString);
formattedOutput.Append(后缀);

字符串输出= formattedOutput.ToString();
ExistingOutputMethodThatOnlyTakesAString(输出);

//清除现有的字符串,以准备下一次迭代:
formattedOutput.Remove(0,output.Length);
}

//选项#2
的foreach(在outputStrings串outputString)
{
StringBuilder的formattedOutputInsideALoop =新的StringBuilder();

formattedOutputInsideALoop.Append(前​​缀);
formattedOutputInsideALoop.Append(outputString);
formattedOutputInsideALoop.Append(后缀);

ExistingOutputMethodThatOnlyTakesAString(
formattedOutputInsideALoop.ToString());
}
}

私人无效ExistingOutputMethodThatOnlyTakesAString(字符串输出)
{
//此方法实际上写入到文件中。
的System.Console.WriteLine(输出);
}


解决方案

若干问题的答案轻轻建议我下车,我和达夫弄清楚它所以下面我是我的结果。我认为,意欲普遍违背本网站的粮食,但如果你想要的东西做对,你不妨做....:)



我修改选项# 1取@Ty建议的优势,使用StringBuilder.Length = 0,而不是删除方法。这使得两个选项比较类似的代码。这两个差异是现在为StringBuilder的构造是否还是跳出循环和选项#1现在使用长度的方法清除的StringBuilder。这两个选项都设置为运行在一个outputStrings阵列100,000元素,使垃圾收集器做一些工作。



一对夫妇的答案提供线索来看看各种PerfMon计数器和放大器;这样和使用结果来选择一个选项。我做了一些研究和最终使用内置的,我在工作的Visual Studio团队系统开发版的性能资源管理器。我发现了一个多系列的第二篇博客条目解释了如何设置它在这里一>。基本上,你连线了单元测试,你要分析的代码点;经过一个向导和放大器;一些配置;和发射单元测试分析。我启用了.NET对象分配和放大器;寿命指标。该分析的结果,其中很难格式化这个答案,所以我将它们放置在最后。如果您复制和粘贴文本到Excel和按摩他们一点,他们就会是可读的。



选项#1是最记忆效率,因为它使垃圾收集器少做一点工作,它分配一半的内存和实例StringBuilder对象比方案#2。对于日常编码,采摘选项#2是完全正常的。



如果你还在读书,我问这个问题,因为方案2将的内存泄漏检测器经验C / C ++开发暴走。如果StringBuilder的实例没有被重新分配之前发布将出现一个巨大的内存泄漏。当然,我们C#开发人员不必担心这些事情(直到他们跳起来咬我们)。感谢所有!




 类名实例TotalBytesAllocated Gen0_InstancesCollected Gen0BytesCollected Gen1InstancesCollected Gen1BytesCollected 
=======选项#1
System.Text.StringBuilder 100,001 2000020 100016 2000320 2 40
System.String 301020 32587168 201147 11165268 3 246
System.Char [] 200000 8977780 200022 8979678 2 90
System.String [] 1 400016 26 1512 0 0
System.Int32 100000 1200000 100061 1200732 2 24
System.Object的[] 100000 2000000 100070 2004092 2 40
======选项#2
System.Text.StringBuilder 200000 4000000 200011 4000220 4 80
System.String 401018 37587036 301127 16164318 3 214
System.Char [] 200000 9377780 200024 9379768 0 0
System.String [] 1 400016 20 1208 0 0
System.Int32 100000 1200000 100051 1200612 1 12
System.Object的[] 100000 2000000 100058 2003004 1 20


In C# which is more memory efficient: Option #1 or Option #2?

public void TestStringBuilder()
{
    //potentially a collection with several hundred items:
    string[] outputStrings = new string[] { "test1", "test2", "test3" };

    //Option #1
    StringBuilder formattedOutput = new StringBuilder();
    foreach (string outputString in outputStrings)
    {
        formattedOutput.Append("prefix ");
        formattedOutput.Append(outputString);
        formattedOutput.Append(" postfix");

        string output = formattedOutput.ToString();
        ExistingOutputMethodThatOnlyTakesAString(output);

        //Clear existing string to make ready for next iteration:
        formattedOutput.Remove(0, output.Length);
    }

    //Option #2
    foreach (string outputString in outputStrings)
    {
        StringBuilder formattedOutputInsideALoop = new StringBuilder();

        formattedOutputInsideALoop.Append("prefix ");
        formattedOutputInsideALoop.Append(outputString);
        formattedOutputInsideALoop.Append(" postfix");

        ExistingOutputMethodThatOnlyTakesAString(
           formattedOutputInsideALoop.ToString());
    }
}

private void ExistingOutputMethodThatOnlyTakesAString(string output)
{
    //This method actually writes out to a file.
    System.Console.WriteLine(output);
}
解决方案

Several of the answers gently suggested that I get off my duff and figure out it myself so below are my results. I think that sentiment generally goes against the grain of this site but if you want something done right, you might as well do.... :)

I modified option #1 to take advantage of @Ty suggestion to use StringBuilder.Length = 0 instead of the Remove method. This made the code of the two options more similar. The two differences are now whether the constructor for the StringBuilder is in or out of the loop and option #1 now uses the the Length method to clear the StringBuilder. Both options were set to run over an outputStrings array with 100,000 elements to make the garbage collector do some work.

A couple answers offered hints to look at the various PerfMon counters & such and use the results to pick an option. I did some research and ended up using the built-in Performance Explorer of the Visual Studio Team Systems Developer edition that I have at work. I found the second blog entry of a multipart series that explained how to set it up here. Basically, you wire up a unit test to point at the code you want to profile; go through a wizard & some configurations; and launch the unit test profiling. I enabled the .NET object allocation & lifetime metrics. The results of the profiling where difficult to format for this answer so I placed them at the end. If you copy and paste the text into Excel and massage them a bit, they'll be readable.

Option #1 is the most memory efficiency because it makes the garbage collector do a little less work and it allocates half the memory and instances to the StringBuilder object than Option #2. For everyday coding, picking option #2 is perfectly fine.

If you're still reading, I asked this question because Option #2 will make the memory leak detectors of an experience C/C++ developer go ballistic. A huge memory leak will occur if the StringBuilder instance is not released before being reassigned. Of course, we C# developers don't worry about such things (until they jump up and bite us). Thanks to all!!


ClassName   Instances	TotalBytesAllocated	Gen0_InstancesCollected	Gen0BytesCollected	Gen1InstancesCollected	Gen1BytesCollected
=======Option #1    				
System.Text.StringBuilder   100,001	2,000,020	100,016	2,000,320	2	40
System.String   301,020	32,587,168	201,147	11,165,268	3	246
System.Char[]   200,000	8,977,780	200,022	8,979,678	2	90
System.String[] 1	400,016	26	1,512	0	0
System.Int32    100,000	1,200,000	100,061	1,200,732	2	24
System.Object[] 100,000	2,000,000	100,070	2,004,092	2	40
======Option #2 				
System.Text.StringBuilder   200,000	4,000,000	200,011	4,000,220	4	80
System.String   401,018	37,587,036	301,127	16,164,318	3	214
System.Char[]   200,000	9,377,780	200,024	9,379,768	0	0
System.String[] 1	400,016	20	1,208	0	0
System.Int32    100,000	1,200,000	100,051	1,200,612	1	12
System.Object[] 100,000	2,000,000	100,058	2,003,004	1	20

这篇关于使用StringBuilder的删除方法更多的内存比创建循环中的一个新的StringBuilder效率?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 20:58