将5000万条记录保存为CSV文件,每个文件保存20万条记录
本文关键字:文件 保存 记录 20万 5000万 CSV | 更新日期: 2023-09-27 18:17:22
我有一个生成数字并将其存储到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);
}
Shuffle是这个答案的扩展方法。
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
。
我怎样才能加快速度并消除错误?
代码中最有问题的行是:
List<int> myResults = Enumerable.Range(1, 50000000).ToList();
:
foreach (int res in myResults.Shuffle())
尽量避免在堆上创建100亿个对象。相反,可以连续生成数据并立即将其写入磁盘,而不必将其保存在内存中。否则,内存管理和垃圾收集将成为瓶颈。
并将洗牌移到计时代码之外。我敢肯定相当多的时间都被拖拖拉拉的人占用了。
所以目前你衡量的是。net垃圾收集和排序算法的效率,而不是你真正想要衡量的,即写CSV文件需要多长时间。
我在我的笔记本上运行这段代码,不使用shuffle方法,耗时22秒。所以我想大部分时间都是用那个方法。
我建议你也不要在使用数据之前创建数据,因为这会消耗大量内存。创建一个枚举方法并逐行返回数据。
你还做了很多非常小的IO操作。更少的大的写操作,所以尝试批量写到磁盘。使用StringBuilder或类似的工具创建更大的数据块进行写入。您还可以查看BufferedWriter类。