2011-04-19 85 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)