2011-04-19 88 views
3

在我的计划,我需要写大量的文本文件(〜300 MB),文本文件包含由空格分隔的数字,我使用这个代码:增强性能

TextWriter guessesWriter = TextWriter.Synchronized(new StreamWriter("guesses.txt")); 

private void QueueStart() 
    { 
     while (true) 
     { 
      if (writeQueue.Count > 0) 
      { 
       guessesWriter.WriteLine(writeQueue[0]); 
       writeQueue.Remove(writeQueue[0]); 
      } 
     } 
    } 

private static void Check() 
    { 
     TextReader tr = new StreamReader("data.txt"); 

     string guess = tr.ReadLine(); 
     b = 0; 
     List<Thread> threads = new List<Thread>(); 
     while (guess != null) // Reading each row and analyze it 
     { 
      string[] guessNumbers = guess.Split(' '); 
      List<int> numbers = new List<int>(); 
      foreach (string s in guessNumbers) // Converting each guess to a list of numbers 
       numbers.Add(int.Parse(s)); 

      threads.Add(new Thread(GuessCheck)); 
      threads[b].Start(numbers); 
      b++; 

      guess = tr.ReadLine(); 
     } 
    } 

    private static void GuessCheck(object listNums) 
    { 
     List<int> numbers = (List<int>) listNums; 

     if (!CloseNumbersCheck(numbers)) 
     { 
      writeQueue.Add(numbers[0] + " " + numbers[1] + " " + numbers[2] + " " + numbers[3] + " " + numbers[4] + " " + numbers[5] + " " + numbers[6]); 
     } 
    } 

    private static bool CloseNumbersCheck(List<int> numbers) 
    { 
     int divideResult = numbers[0]/10; 
     for (int i = 1; i < 6; i++) 
     { 
      if (numbers[i]/10 != divideResult) 
       return false; 
     } 
     return true; 
    } 

文件data.txt中包含的数据格式为:(点意味着遵循同样的逻辑更多的数字)

1 2 3 4 5 6 1 
1 2 3 4 5 6 2 
1 2 3 4 5 6 3 
. 
. 
. 
1 2 3 4 5 6 8 
1 2 3 4 5 7 1 
. 
. 
. 

我知道这是不是很有效,我一直在寻找如何使人们更快一些建议。 如果你知道如何节省大量的数字比.txt更有效,我将不胜感激。

+0

什么样的对象是writeQueue? – 2011-04-19 15:44:06

+0

TextWriter.Synchronized()似乎无用,因为您只能从一个线程(QueueStart())访问文件。但是你的队列或者列表“writeQueue”应该是同步的,如果不是的话。 – Kipotlov 2011-04-19 15:48:01

+0

writeQueue是一个列表,我增加了缓冲区大小为64K(感谢Gabe),我把它全部变成了1个线程(谢谢Jeffery),它确实做得更快。该程序sopused做削减关于彩票号码,而不是pin码... – ofirl 2011-04-19 16:47:55

回答

1

使用BinaryWriter可以提高效率。然后你可以直接写出整数。这将允许您跳过对读取的解析步骤以及写入时的ToString转换。

它也看起来像你正在创建一个在那里的线程。其他线程会降低性能。你应该在单个线程上完成所有的工作,因为线程是非常重量级的对象。

这是一个或多或少的直接转换你的代码来使用BinaryWriter。 (这没有解决线程问题。)

BinaryWriter guessesWriter = new BinaryWriter(new StreamWriter("guesses.dat")); 
    private void QueueStart() 
    { 
     while (true) 
     {    
      if (writeQueue.Count > 0) 
      { 
       lock (guessesWriter) 
       { 
        guessesWriter.Write(writeQueue[0]); 
       } 
       writeQueue.Remove(writeQueue[0]); 
      } 
     } 
    } 
    private const int numbersPerThread = 6; 
    private static void Check() 
    { 
     BinaryReader tr = new BinaryReader(new StreamReader("data.txt")); 
     b = 0; 
     List<Thread> threads = new List<Thread>(); 
     while (tr.BaseStream.Position < tr.BaseStream.Length) 
     { 
      List<int> numbers = new List<int>(numbersPerThread); 
      for (int index = 0; index < numbersPerThread; index++) 
      { 
       numbers.Add(tr.ReadInt32()); 
      } 
      threads.Add(new Thread(GuessCheck)); 
      threads[b].Start(numbers); 
      b++; 
     } 
    } 
+0

+1二进制是前进的方式 – MattDavey 2011-04-19 15:43:41

+0

我试图使用二进制,但构造函数想要一个流,我不能访问从主窗体中的流构造函数我的应用程序,我错过了什么? – ofirl 2011-04-19 16:50:07

+0

@ofirl - 我在我的答案中添加了一些代码。我不知道为什么你不能访问Stream构造函数。它与BinaryReader本身位于同一个命名空间中。 – 2011-04-19 17:20:56

1

尝试使用缓冲区之间。有一个BGufferdSTream。现在你使用非常低效的光盘访问模式。

1

而不是逐行读写(ReadLine和WriteLine),您应该读写大块数据(ReadBlock和Write)。通过这种方式,您可以更少地访问磁盘,并且可以大幅提升性能。但是你需要管理每一行的结尾(查看Environment.NewLine)。

2

提高效率的一种方法是在输出流中使用更大的缓冲区。你正在使用默认值,它可能会给你一个1k的缓冲区,但你不会看到最低性能不足64k的缓冲区。打开你的文件是这样的:

new StreamWriter("guesses.txt", new UTF8Encoding(false, true), 65536)