我有一个3.6 gig的csv文件。我正在使用CsvHelper来处理它。当我使用linq查询它时,它需要几分钟,我看到CPU在我的电脑上最大只有25%。 Linq在执行此操作时似乎能够很好地处理内存,因为它根本没有用。
所以我想通过添加.AsParallel()我会看到一些性能提升。当我运行它时,我看到我的CPU上升到大约95%,但它需要同样长的时间。
为什么我不会看到.AsParallel()的性能提升,有没有办法让它获得更好的性能(将其作为csv)。
string path = @"C:\my_3_gig_file.csv";
using (var csv = new CsvHelper.CsvReader(new StreamReader(path, Encoding.Default)))
{
csv.Configuration.Delimiter = ",";
csv.Configuration.TrimFields = true;
var records = csv.GetRecords<MyClass>();
var q1 = (from a in records.AsParallel()
where a.MY_HOUR == "1"
&& a.MY_DATE == "14-JUN-13"
select a).ToList();
}
答案 0 :(得分:1)
通过尝试并行处理行,你将无法获得任何东西,所以没有必要尝试。您只能使用CsvHelper线性读取和处理文件。即便如此,那里还没有足够的工作来证明行的并行处理。什么可能伤害到你正在建立阅读的每一条记录。如果有很多列,那么每行处理很多。
您正在尝试过滤掉要在文件中使用的行。您应该直接读取行,检查列,然后随时构建记录。这样,你就不会浪费大量时间为每一行构建记录,只是为了将它扔掉。
这是你可以这样做的一种方式。
List<T> GetCsvRecordsFiltered<T>(string path, Func<CsvReader, bool> filter, Action<CsvConfiguration> configure = null) where T : class
{
using (var file = File.OpenText(path))
using (var reader = new CsvReader(file))
{
configure?.Invoke(reader.Configuration);
var result = new List<T>();
while (reader.Read())
if (filter(reader))
result.Add(reader.GetRecord<T>());
return result;
}
}
然后当你阅读文件时,你会这样做:
var q1 = GetCsvRecordsFiltered<MyClass>(path,
reader => reader["MY_HOUR"] == "1" && reader["MY_DATE"] == "14-JUN-13",
config => config.TrimFields = true
);
答案 1 :(得分:1)
使用AsParallel()
您不会看到任何性能提升,因为没有什么可以并行完成。
csv.GetRecords<MyClass>()
立即返回的原因是因为它yields会记录。在需要之前,它实际上不会读取任何文件。每个读取的记录只读取文件中的一条记录(实际上是数据缓冲区)。
当你使用linq时,它必须读取整个3.6 GB文件并解析它以获得结果。您无法执行where
子句并且无法读取整个文件。当有其他linq提供程序(如sql)时,没有发生的原因是因为构建了索引,并且sql只能提取它所需的记录。