您的位置:首页 > 产品设计 > UI/UE

请大家也试试这个Performance Quiz吧

2007-10-18 00:24 351 查看
园子里首页上基本都是些博主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);

请回答下面的问题:

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做哪些假设?



stream没有额外的行为并且是有输出缓冲的。如果不是这样的话,1,2,3的语法就会有显著的区别并且可能性能差别会很大。

Rico用CLRProfiler对下面的程序进行了分析并进行了说明。

Option2 分析结果

static void Test.Test::Test2()

void System.IO.TextWriter::WriteLine(String, Object, Object)

System.Object[] (24 bytes)

static String System.String::Format(System.IFormatProvider, String, Object[])

System.Text.StringBuilder (20 bytes)

void System.Text.StringBuilder::.ctor(String, int32)

void System.Text.StringBuilder::.ctor(String, int32, int32)

static String System.String::GetStringForStringBuilder(String, int32, int32, int32)

System.String (66 bytes)

void System.String::NullTerminate()

System.Text.StringBuilder System.Text.StringBuilder::AppendFormat(System.IFormatProvider, String, Object[])

wchar[] System.String::ToCharArray(int32, int32)

System.Char[] (28 bytes)

String System.String::ToString()

System.Text.StringBuilder System.Text.StringBuilder::Append(String)

static bool System.IntPtr::op_Inequality(int,int)

void System.String::AppendInPlace(String,int32)

void System.String::NullTerminate()

System.Text.StringBuilder System.Text.StringBuilder::Append(wchar[], int32, int32)

String System.Text.StringBuilder::GetThreadSafeString(int&)

static bool System.IntPtr::op_Equality(int,int)

void System.String::AppendInPlace(wchar[], int32, int32, int32)

void System.String::NullTerminate()

String System.Text.StringBuilder::ToString()

static bool System.IntPtr::op_InEquality(int,int)

static bool System.IntPtr::op_InEquality(int,int)

void System.String::ClearPostNullChar()

void System.IO.TextWriter::WriterLine(String)

System.Char[] (46 bytes)

void System.String.CopyTo(int32,wchar[], int32, int32)

void System.IO.StreamWriter::Write(wchar[], int32, int32)

说明:



第一次分配把两个固定的参数放至同一个object array中,以便WriteLine使用同一path.
第二次分配创建string builder来进行formating,只有string builder可以进行formatting.
第三次是分配用于初始化string buidler的buffer.
第四次将用于WriteLine输出的格式化好的string转换成char[]
char[]后面加上换行符。

Option3: 7 function calls. 1 allocation. 32 bytes allocated

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.

读完的朋友感觉怎么样,没想到小小一行平时常见的代码里面的竟包含这么多东西吧。主要总结如下:



只有一个参数时,WriteLine不会进行formatting.
很多人认为WriteLine方面MS会做特别的优化处理,其实是没有,我们也看到了首先要转换成char[]然后再加上换行符。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: