将5000万条记录保存到CSV文件,每个文件节省20万条

时间:2015-10-13 12:19:53

标签: c# performance io

我有生成数字并将其存储到List<int>的功能 现在我必须尽快将这些结果存储到文件中。

到目前为止,这是我的代码:

private void Save_Click(object sender, EventArgs e)
{
    //this is just for tests
    List<int> myResults = Enumerable.Range(1, 50000000).ToList();
    const string dir = @"D:\TESTS";

    int fileCount = 1;
    var file = Path.Combine(dir, string.Format("{0}.csv", fileCount));
    var sw = new StreamWriter(file, false);
    int i = 0;

    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();

    foreach (int res in myResults.Shuffle())
    {
        sw.WriteLine(res);
        i++;
        if (i%200000 != 0) continue;
        fileCount++;
        sw.Close();
        file = Path.Combine(dir, string.Format("{0}.csv", fileCount));
        sw = new StreamWriter(file, false);
    }

    sw.Close();
    stopwatch.Stop();

    label3.Text = string.Format("Save time(s): {0:0.##}", stopwatch.Elapsed.TotalSeconds);
}

随机播放是从this answer获取的扩展方法。

public static class Extensions
{
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng = null)
    {
        if (rng == null)
            rng = new Random();

        T[] elements = source.ToArray();
        for (int i = elements.Length - 1; i > 0; i--)
        {
            int swapIndex = rng.Next(i + 1);
            yield return elements[swapIndex];
            elements[swapIndex] = elements[i];
        }
        yield return elements[0];
    }
}

我的问题是我的电脑上保存大约需要5-7分钟,当我将结果数量增加到1亿时,我得到OutOfMemoryException

如何加快速度并消除错误?

2 个答案:

答案 0 :(得分:4)

代码中最有问题的行是:

List<int> myResults = Enumerable.Range(1, 50000000).ToList();

foreach (int res in myResults.Shuffle())

尽量避免在堆上创建100m对象。相反,连续生成数据并立即将其写入磁盘而不将其保留在内存中。否则内存管理和垃圾收集成为瓶颈。

然后在定时代码之外移动洗牌。我很确定洗牌会吃掉相当多的时间。

因此,目前您测量的是.NET垃圾收集和混洗算法的效率,而不是您真正想要测量的效率,即编写CSV文件所需的时间。

答案 1 :(得分:1)

我在我的笔记本上运行了这个代码,没有shuffle方法,花了22秒。 所以我认为大部分时间可能都是采用这种方法。

我建议您在使用之前也不要创建数据,因为这会占用大量内存。创建一个枚举方法并按行返回数据。

您还在进行大量非常小的IO操作。 而是更少的更大的写入,所以尝试批量写入磁盘。 使用StringBuilder或类似的东西来创建更大的数据块来编写。 您还可以查看BufferedWriter类。