增强c#中流写入器的性能
本文关键字:性能 增强 | 更新日期: 2023-09-27 17:50:29
在我的程序中,我需要写大的文本文件(~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文件更有效地保存大量的数字,我将不胜感激。
提高效率的一种方法是在输出流上使用更大的缓冲区。您使用的是默认值,它可能为您提供1k的缓冲区,但如果缓冲区小于64k,您将无法获得最佳性能。像这样打开你的文件:
new StreamWriter("guesses.txt", new UTF8Encoding(false, true), 65536)
不要一行一行地读写(ReadLine和WriteLine),你应该读写大块的数据(ReadBlock和write)。这样,您访问磁盘的次数就会大大减少,性能也会大大提高。但是您需要管理每行的末尾(参见Environment.NewLine)。
使用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++;
}
}
尝试在两者之间使用缓冲区。有一个BGufferdSTream。