请大家也试试这个Performance Quiz吧
园子里首页上基本都是些博主bala bala跟大家分享经验的文章,我来个换个话题,希望大家能喜欢。
这个问题其实是Rico Mariani零四年发布在他blog中的一个非常棒的帖子,最终演化成了一个系列。(可能有人要问Rico Mariani是谁,嗯,基本上没有人比他更有资格谈.net performance了),我在这里发的其实就是此系列的第一篇。
sw.WriteLine(subject + ": " + message);
sw.WriteLine("{0}: {1}", subject, message);

sw.Write(subject);
sw.Write(": ");
sw.WriteLine(message);
分析用程序
其结果如下:(具体的结果也可以去看他的blog)
Option1: 4 calls, 2 allocations, for 94 bytes
说明:
Option2 分析结果
说明:
读完的朋友感觉怎么样,没想到小小一行平时常见的代码里面的竟包含这么多东西吧。主要总结如下:
这个问题其实是Rico Mariani零四年发布在他blog中的一个非常棒的帖子,最终演化成了一个系列。(可能有人要问Rico Mariani是谁,嗯,基本上没有人比他更有资格谈.net performance了),我在这里发的其实就是此系列的第一篇。
考虑下面三种选择
1

2.



3




请回答下面的问题:
Q1. 哪种选择的性能最好?
Q2: 你能分别说明每种选择的内存分配情况吗?
Q3: 哪种选择会是performance team推荐的,为什么?
Q4: 什么特殊的因素会影响上面推荐的选择?
Q5: 在回答问题时,你需要对sw做哪些假设?
我也模仿下ricom,先不在这说答案和给出他blog的链接了,大家可以仔细想想,踊跃发言哈。
_____________________________________________________________________________________
谢谢大家的和发言,下面是Rico给出的答案,大家看看和自己想的一样不一样呢。(提示,rico的分析很长,但后面可能会帮助很多人纠正一些认识上的误区,所在要耐心看哦,这个是它的原文链接,感兴趣的可以去看看原文click here。
Q1. 哪种选择的性能最好?
- 唯一可能确定的是#2的性能比#1性能差
- 如果有输出缓冲(buffer)的话,#3的性能最好
- 相反,如果没有输出缓冲的话,#1的性能最好
Q2: 你能分别说明每种选择的内存分配情况吗?
- 一次连结(concat)操作,一个临时string对象,总共两次分配。
- 多次内存分配,包括string builder, underlying string buffer等。
- 一次。
Q3: 哪种选择会是performance team推荐的,为什么?
- #2会是CLR Performance Architects推荐的,虽然它性能最差,但直观而且易于维护。
Q4: 什么特殊的因素会影响上面推荐的选择?
- Specific measurements indicating that the code path had become a hotspot. (不好意思,我不知道code path应该怎么说,所以还是贴原句吧)
Q5: 在回答问题时,你需要对sw做哪些假设?
Rico用CLRProfiler对下面的程序进行了分析并进行了说明。
- stream没有额外的行为并且是有输出缓冲的。如果不是这样的话,1,2,3的语法就会有显著的区别并且可能性能差别会很大。

Option1: 4 calls, 2 allocations, for 94 bytes
static void Test.Test::Test1()
static String System.String::Concat(String,String,String)
System.String(48 bytes)
void System.IO.TextWrite::WriteLine(String)
System.Char[] (46 bytes)
void System.String.CopyTo(int32,wchar[], int32, int32)
void System.IO.StreamWriter::Write(wchar[], int32, int32)
static String System.String::Concat(String,String,String)
System.String(48 bytes)
void System.IO.TextWrite::WriteLine(String)
System.Char[] (46 bytes)
void System.String.CopyTo(int32,wchar[], int32, int32)
void System.IO.StreamWriter::Write(wchar[], int32, int32)
说明:
Option2: 30 function calls. 5 allocations. 184 bytes allocated (结果有些出乎意料吧?)
- 只有一次连结操作(Concat),所以也只有一次为temp string分配内存。
- WriteLine方法并没有使用string builder对输出进行formatting.当参数只有一个时,WriteLine方法不会进行formatting.
- 当对单个参数 string调用WriteLine时,其实会将string转换成 char[]并在后面加上换行符。
- 转换后的char[]再加上换行符的总长度要小于原string,这是因为没有了string object overhead并且可能去掉了string终止符.

Option3: 7 function calls. 1 allocation. 32 bytes allocated
- 第一次分配把两个固定的参数放至同一个object array中,以便WriteLine使用同一path.
- 第二次分配创建string builder来进行formating,只有string builder可以进行formatting.
- 第三次是分配用于初始化string buidler的buffer.
- 第四次将用于WriteLine输出的格式化好的string转换成char[]
- char[]后面加上换行符。
static void Test.Test::Test3()
void System.IO.StreamWriter::Write(String)
void System.String::CopyTo(int32, wchar[], int32, int32)
void System.IO.StreamWriter::Write(String)
void System.String::CopyTo(int32, wchar[], int32, int32)
void System.IO.StreamWriter::WriteLine(String)
System.Char[] (32 bytes)
void System.String::CopyTo(int32, wchar[], int32, int32)
void System.IO.StreamWriter::Write(wchar[], int32, int32)
同Option1,无formatting,只创建了一个string用于WriteLine.void System.IO.StreamWriter::Write(String)
void System.String::CopyTo(int32, wchar[], int32, int32)
void System.IO.StreamWriter::Write(String)
void System.String::CopyTo(int32, wchar[], int32, int32)
void System.IO.StreamWriter::WriteLine(String)
System.Char[] (32 bytes)
void System.String::CopyTo(int32, wchar[], int32, int32)
void System.IO.StreamWriter::Write(wchar[], int32, int32)
读完的朋友感觉怎么样,没想到小小一行平时常见的代码里面的竟包含这么多东西吧。主要总结如下:
- 只有一个参数时,WriteLine不会进行formatting.
- 很多人认为WriteLine方面MS会做特别的优化处理,其实是没有,我们也看到了首先要转换成char[]然后再加上换行符。
分类:
.Net
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?