增强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文件更有效地保存大量的数字,我将不胜感激。

增强c#中流写入器的性能

提高效率的一种方法是在输出流上使用更大的缓冲区。您使用的是默认值,它可能为您提供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。