首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >StringBuilder到FileStream与直接FileStream性能的比较

StringBuilder到FileStream与直接FileStream性能的比较
EN

Stack Overflow用户
提问于 2014-04-26 20:39:50
回答 2查看 1.7K关注 0票数 1

我正在以增量的方式将大量文本数据写入FileStream,而且速度相当慢。如果我将文本写到内存中的StringBuilder中,然后将StringBuilder批发地转储到FileStream中,会更快吗?我认为这样做可能可以利用FileStream中的某种缓冲,但我对FileStream的工作原理不太了解,无法判断。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-29 21:32:55

由于我们没有序列化代码,而且您怀疑使用优化的Stream和/或StringBuilder可以提高性能,因此我在LinqPad中设置了一个测试平台,以构建具有长字符串属性和其他一些属性的类的列表。该列表被序列化为磁盘。

Xml序列化后磁盘上的大小为115.910.381字节(110 MB)。

试验台

代码语言:javascript
复制
void Main()
{
    var list = new List<Test>();
    for(int k=0;k<100;k++) list.Add(
        new Test { Prop1 = Rnd(), /* random string of 1 MB */
                 Prop2 =k, Prop3=k*k, Prop4= DateTime.Now});
    BinaryFormatter(list);
    DataContractJsonSerializer(list);
    XmlSerializer(list);
    XmlSerializerBuffered(list);
    XmlSerializerMemory(list);
    XmlSerializerStringBuilder(list);
}

由于Xml序列化程序花费的时间最多,我决定只在该变体中尝试不同的技术。

直接法

代码语言:javascript
复制
void XmlSerializer(List<Test> list)
{
    var sw = new Stopwatch();
    sw.Start();
    var s = new FileStream("c:\\temp\\test.xml", FileMode.Create);
    var x = new XmlSerializer(typeof(List<Test>));
    x.Serialize(s,list);
    s.Close();
    sw.Stop();
    
    sw.Elapsed.Dump("Xml");
}

缓冲流

代码语言:javascript
复制
void XmlSerializerBuffered(List<Test> list)
{
    var sw = new Stopwatch();
    sw.Start();
    var s = new FileStream("c:\\temp\\test.xmlbuf", FileMode.Create);
    var b = new BufferedStream(s);
    var x = new XmlSerializer(typeof(List<Test>));
    x.Serialize(b,list);
    b.Close();
    s.Close();
    sw.Stop();
    
    sw.Elapsed.Dump("Xml Buffered");
}

首先在MemoryStream中,然后复制

代码语言:javascript
复制
void XmlSerializerMemory(List<Test> list)
{
    var sw = new Stopwatch();
    sw.Start();
    var s = new FileStream("c:\\temp\\test.xmlmem", FileMode.Create);
    var m = new MemoryStream(1024*1024);  // INITIAL BUFFER SIZE (can and will grow!)
    // also works but is slower: var m = new MemoryStream();     
   var x = new XmlSerializer(typeof(List<Test>));
    x.Serialize(m,list);
    
    m.Position=0;
    m.CopyTo(s);
    m.Close();
    s.Close();
    sw.Stop();
    
    sw.Elapsed.Dump("Xml Mem");
}

StringBuilder

代码语言:javascript
复制
void XmlSerializerStringBuilder(List<Test> list)
{
    var sw = new Stopwatch();
    sw.Start();
    var s = new StreamWriter("c:\\temp\\test.xmlsb");
    var sb = new StringBuilder();
    var m = new StringWriter(sb);
    var x = new XmlSerializer(typeof(List<Test>));
    x.Serialize(m,list);
    s.Write(sb.ToString()); // http://stackoverflow.com/a/5027483/578411
    s.Close();
    sw.Stop();
    sw.Elapsed.Dump("Xml StringBuilder");
}

我的结果(在Win7(64位)/.Net 4.0/x86/4GB/RAID 0+1上)

典型的结果如下:

代码语言:javascript
复制
Xml                00:00:01.5116768 
Xml Buffered       00:00:01.3149263 
Xml Mem            00:00:01.2465760 
Xml StringBuilder  00:00:02.1440784 

所有数据首先写入内存流,然后一次复制到流的变体总是最快的。

StringBuilder总是最慢的,但是XmlSerializer中没有过载可以直接“写”到StrigBuilder。因此,使用一个StringWriter作为额外的间接,这需要时间。

现在,请记住,这只是丑陋的、非优化的测试代码,只是为了了解哪些测试代码可能有效。仅根据数据设置中的实际性能数据进行优化。在同一时间改变一件事,并继续测量。

数据类

代码语言:javascript
复制
[Serializable]
public class Test
{
     public string Prop1 {get; set;}
     public int Prop2 {get;set;}
     public double Prop3 {get;set;}
     public DateTime Prop4 {get;set;}
     
}
票数 3
EN

Stack Overflow用户

发布于 2014-04-26 21:06:52

StringBuilder可以帮助您减少创建的字符串数量。如果您有许多独特的字符串写入您的filestream,这可能会造成一些实际的开销。与您讨论字符串连接时的讨论相同(请参阅Most efficient way to concatenate strings?)。在这种情况下,您感觉到的不良性能可能不是FileStream。

做最好的事?运行性能分析工具。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23316271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档