C# string 拼接操作性能测试

一、C# 拼接字符串的几种方式和性能

  1. 对于少量固定的字符串拼接,如string s= "a" + "b" + "c",系统会优化成s= String.Concat("a","b","c"),不会新建多个字符串。然而如果写成string s="a"; s +="b"; s+="c";则会创建三个新的字符串。
  2. string s= String.Format("{0}{1}{2}","a","b","c"); 看一下源代码:
public static String Format( IFormatProvider provider, String format, params Object[] args) 
{
    if (format == null || args == null)
        throw new ArgumentNullException((format==null)?"format":"args");
    StringBuilder sb = new StringBuilder(format.Length + args.Length * 8);
    sb.AppendFormat(provider,format,args);
    return sb.ToString();
}

其内部封装了一个 StringBuilder, 效率比用 + 号要好;此方法非常适用于从少量组件字符串生成字符串的情况。

  1. StringBuilder 是预先创建一个比较大的内存,以后每次操作时判断容量上限是否不够用,如果不够用就自动把容量扩大一倍,修改的还是原来那个对象;字符串较少时,可以使用String.Format()代替;有些情况下,可能要将字符串合并在循环中,此时不知道要合并的源字符串的数量,而且源字符串的实际数量可能非常大。 StringBuilder 类专门用于此类方案

二、循环性能测试

  1. 编写如下代码:
        public static string ConcactTest()
        {
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            long start = GC.GetTotalMemory(true);
            
            // 在这里写需要被测试内存消耗的代码
            string ret = "";
            for (int i = 0; i < 100000; i++)
            {
                ret += i;
            }
            watch.Stop();
            var useTime = (double)watch.ElapsedMilliseconds / 1000;

            GC.Collect();
            // 确保所有内存都被GC回收
            GC.WaitForFullGCComplete();
            long end = GC.GetTotalMemory(true);
            long useMemory = end - start;
            Console.WriteLine($"ConcactTest: memory used[{useMemory}], time used[{useTime}]");
            return ret;
        }

        public static string FormatTest()
        {
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            long start = GC.GetTotalMemory(true);

            // 在这里写需要被测试内存消耗的代码
            string ret = "";
            for (int i = 0; i < 100000; i++)
            {
                ret = string.Format("{0}{1}", ret, i);
            }
            watch.Stop();
            var useTime = (double)watch.ElapsedMilliseconds / 1000;

            GC.Collect();
            // 确保所有内存都被GC回收
            GC.WaitForFullGCComplete();
            long end = GC.GetTotalMemory(true);
            long useMemory = end - start;
            Console.WriteLine($"FormatTest: memory used[{useMemory}], time used[{useTime}]");
            return ret;
        }

        public static string StringBuilderTest()
        {
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            long start = GC.GetTotalMemory(true);

            // 在这里写需要被测试内存消耗的代码,例如
            StringBuilder ret = new StringBuilder(10000);
            for (int i = 0; i < 100000; i++)
            {
                ret.Append(i);
            }
            watch.Stop();
            var useTime = (double)watch.ElapsedMilliseconds / 1000;

            GC.Collect();
            // 确保所有内存都被GC回收
            GC.WaitForFullGCComplete();
            long end = GC.GetTotalMemory(true);
            long useMemory = end - start;
            Console.WriteLine($"StringBuilderTest: memory used[{useMemory}], time used[{useTime}]");
            return ret.ToString();
        }
  1. 调用查看运行结果如下

ConcactTest: memory used[1960604], time used[17.636]
FormatTest: memory used[977616], time used[39.187]
StringBuilderTest: memory used[982440], time used[0.014]

可见内存时间占用 StringBuilder 更合适

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容