从clr profiler的角度看string concat 和stringbuilder的性能差别

private int BUFSIZE = 10000;
private void button1_Click(object sender, System.EventArgs e)
{
 string s = "";
 long t1 = System.DateTime.Now.Ticks;
 for(int i=0;i<BUFSIZE;i++)s += "a";
 long t2 = System.DateTime.Now.Ticks;
 button1.Text = Convert.ToString(t2-t1);
}

private void button2_Click(object sender, System.EventArgs e)
{
 long t1 = System.DateTime.Now.Ticks;
 System.Text.StringBuilder sb = new System.Text.StringBuilder(BUFSIZE);
 for(int i=0;i<BUFSIZE;i++)sb.Append("a");
 long t2 = System.DateTime.Now.Ticks;
 button2.Text = Convert.ToString(t2-t1);
}

代码很简单,地球人也都知道,StringBuilder要比String的cat快很多。原理大家应该也都清楚,StringBuilder会预先分配2*capacity大小的内存来放置字符串内容。以后append的时候,尽可能的在当前内存块内操作。而String却是每次都重新new一个新对象。
现在我们从clr profiler的角度来看一下这个问题。

首先看strcat方式下的objects分配情况,如下图:

红色的string和黄色的byte[],一共分配了473966+67134=大约540K大小的内存。其中,黄色的byte[]被“挤”到了GC的第二代上。红色的目前是在第0代上,很少量的绿色object[](13K)被挤到了第1代上。
我们再看GC在压缩、回收的过程表现:

大概在第6秒的时候,注意上面白色的部分,和红色的尖峰部分。内存不定的被释放(free),然后不停的被申请,大概到第7.5秒的时候,内存释放与申请达到了一个平滑状态。

我们再看StringBuilder的表现,依旧是先看objects的分配状况:

红色的string和黄色的byte[],一共分配了133588+94911=大约127K大小的内存。其中,黄色的byte[]被“挤”到了GC的第1代上。红色的目前是在第0代上,很少量的cyan色char[](35K)被挤到了第1代上。
我们再看GC在压缩、回收的过程表现:

从图示中可以看到,没有白色的free的legend,即:没有发生此过程。为什么会这样?因为我们再StringBuilder的构造方法中,分配了2*BUFSIZE的大小。
那么,这个猜测是否正确呢?我们修改上面的button2_click的代码,修改为:

private void button2_Click(object sender, System.EventArgs e)
{
 long t1 = System.DateTime.Now.Ticks;
 System.Text.StringBuilder sb = new System.Text.StringBuilder(10);
 for(int i=0;i<BUFSIZE;i++)sb.Append("a");
 long t2 = System.DateTime.Now.Ticks;
 button2.Text = Convert.ToString(t2-t1);
}
然后再看看objects的分布和gc timeline的情况:

嘿嘿,还是没有free再malloc的过程。但是注意的一点是,最上面那一大块红色,变厚了(内存地址空间增大了),变短了(时间降低了)。

我没有做过多次试验,但是我猜测,因为GC本身回收的时机不确定,所以上面最后两个图看不出太大的区别了。

偶没仔细研究过stringbuilder的代码,所以上面的表述不一定完全正确,呵呵。

posted @   鞠强  阅读(3943)  评论(14编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述

hello

world

点击右上角即可分享
微信分享提示