【问题标题】:Is is better to Stream.Write multiple times or concatenate string and Stream.Write once?Stream.Write 多次或连接字符串和 Stream.Write 一次更好?
【发布时间】:2015-02-23 23:45:56
【问题描述】:

我只是想知道,就性能而言,哪个更好(我在 FileStream 中使用 StreamWriter):

  1. 多次调用 Stream.Write():

StreamWriter sw = new StreamWriter(fs);
for (int i = 0; i < 100; i++)
{
    sw.Write(myList[i].ToString());
}

  1. 将我所有的字符串连接成一个字符串,然后调用 Steam.Write() 一次:

StreamWriter sw = new StreamWriter(fs);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++)
{
    sb.Append(myList[i].ToString());
}
sw.Write(sb.ToString());

谢谢!

【问题讨论】:

  • 在哪些方面更好?速度?记忆? BTW:你可能会喜欢这个博客ericlippert.com/2012/12/17/performance-rant
  • 你应该写nonce
  • 您注意到了哪些性能问题?当我们知道我们要解决的问题时,我们可以更轻松地帮助您解决问题。
  • 为什么不自己试试呢?
  • 在第二次调用 stringbuilder.Append() 也是多次

标签: c# .net file stream


【解决方案1】:

对此没有单一的答案。您可以想象,逐字节或逐字符写入通常会导致开销,因为每个数据块都经过抽象层。

但是您也可以想象尽可能多地缓冲可能不是最佳的,即。如果您通过网络流发送数据,您希望网络尽快开始传输数据。而且您的应用程序正忙于缓冲,所以也许您只是在移动延迟而不是修复任何东西。

FileStream 的情况下,操作系统负责缓冲,在正常情况下,您可能不会注意到两种方法之间的任何区别。

只需编写最适合您的应用程序的数据,如果您发现这是您的应用程序的瓶颈,请在StreamWriter 和底层Stream 之间实现缓冲流层来解决问题。

【讨论】:

    【解决方案2】:

    根据我的个人经验,在选择一个或另一个之前,您还应该考虑其他一些事情:如果您逐行写入流,则完整文本的每一行都有可能发生 I/O 异常(特别是当写入磁盘);因此,您要编写的行越多,您的代码就越容易出错。因此,如果您的两种方法之间没有显着差异,请考虑第二种方法,或者在编写一半完整文本时发生异常时让您的代码准备好恢复。

    【讨论】:

    • 并非每次调用 StreamWriter.WriteLine() 都会导致实际的写入操作,因为 StreamWriter 在刷新数据之前会缓存数据。
    【解决方案3】:

    我使用 3 种不同的方法测量持续时间:

    class Program
    {
        private static readonly int NumLines = 100000;
        private static readonly int NumWords = 200;
        private static readonly string Word = "Oberbuergermeister";
    
        static void Main(string[] args)
        {
            var stopWatch = new Stopwatch();
    
            // approach 1: use string builder to cache all, then write
            stopWatch.Start();
            Approach1();
            stopWatch.Stop();
            Console.WriteLine(stopWatch.Elapsed.ToString());
            stopWatch.Reset();
    
            // approach 2: write stuff line by line
            stopWatch.Start();
            Approach2();
            stopWatch.Stop();
            Console.WriteLine(stopWatch.Elapsed.ToString());
            stopWatch.Reset();
    
            // approach 3: write stuff string by string
            stopWatch.Start();
            Approach3();
            stopWatch.Stop();
            Console.WriteLine(stopWatch.Elapsed.ToString());
        }
    
        private static void Approach1()
        {
            var writer = new System.IO.StreamWriter("C:\\temp\\1");
    
            var builder = new StringBuilder();
            for (int cnt1 = 0; cnt1 < NumLines; cnt1++)
            {
                for (int cnt2 = 0; cnt2 < NumWords; cnt2++)
                {
                    builder.Append(Word);
                    builder.Append(";");
                }
                builder.AppendLine();
            }
    
            writer.WriteLine(builder.ToString());
    
            writer.Close();
        }
    
        private static void Approach2()
        {
            var writer = new System.IO.StreamWriter("C:\\temp\\2");
    
            var builder = new StringBuilder();
            for (int cnt1 = 0; cnt1 < NumLines; cnt1++)
            {
                for (int cnt2 = 0; cnt2 < NumWords; cnt2++)
                {
                    builder.Append(Word);
                    builder.Append(";");
                }
                writer.WriteLine(builder.ToString());
                builder.Clear();
            }
    
            writer.Close();
        }
    
        private static void Approach3()
        {
            var writer = new System.IO.StreamWriter("C:\\temp\\3");
    
            for (int cnt1 = 0; cnt1 < NumLines; cnt1++)
            {
                for (int cnt2 = 0; cnt2 < NumWords; cnt2++)
                {
                    writer.Write(Word);
                    writer.Write(";");
                }
                writer.WriteLine();
            }
    
            writer.Close();
        }
    }
    

    这是输出:

    00:00:02.8457431
    00:00:01.5492287
    00:00:01.4843888
    

    看起来最好尽可能多地调用StreamWriter.Write(),并将缓存完全留给.NET。我没有逐个字符地尝试过,但无论如何,逐行似乎已经足够了。

    【讨论】:

      猜你喜欢
      • 2020-04-18
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-02
      相关资源
      最近更新 更多