3 回答
TA贡献1784条经验 获得超2个赞
虽然您可以进行许多小的优化,但真正让您丧命的是垃圾收集器,因为所有的分配。
你的代码在我的机器上运行需要 12 秒。读取文件使用了这 12 秒中的 2 秒。
通过使用评论中提到的所有优化(使用File.ReadLines, StringSplitOptions.RemoveEmptyEntries,也使用float.Parse(f, CultureInfo.InvariantCulture)而不是调用string.Replace),我们将时间缩短到 9 秒。仍有很多分配已完成,尤其是File.ReadLines. 我们能做得更好吗?
只需在 app.config 中激活服务器 GC:
<runtime>
<gcServer enabled="true" />
</runtime>
这样,使用您的代码执行时间下降到 6 秒,使用上述优化后执行时间下降到 3 秒。那时,文件 I/O 占用了超过 60% 的执行时间,因此不值得进一步优化。
代码的最终版本:
var lines = File.ReadLines(filePath);
var separator = new[] {','};
var result = lines.AsParallel().AsOrdered().Select((line, index) =>
{
var values = line?.Split(separator, StringSplitOptions.RemoveEmptyEntries)
.Select(f => float.Parse(f, CultureInfo.InvariantCulture)).ToArray();
return (index, values);
}).ToDictionary(d => d.Item1, d => d.Item2);
TA贡献1772条经验 获得超8个赞
用手动解析替换SplitandReplace并使用InvariantInfo接受句点作为小数点,然后删除浪费ReadAllLines().ToList()并AsParallel()在解析时从文件中读取,在我的 PC 上加速了大约四倍。
var lines = File.ReadLines(filepath);
var result = lines.AsParallel().AsOrdered().Select((line, index) => {
var values = new List<float>(10000);
var pos = 0;
while (pos < line.Length) {
var commapos = line.IndexOf(',', pos);
commapos = commapos < 0 ? line.Length : commapos;
var fs = line.Substring(pos, commapos - pos);
if (fs != String.Empty) // remove if no value is ever missing
values.Add(float.Parse(fs, NumberFormatInfo.InvariantInfo));
pos = commapos + 1;
}
return values;
}).ToList();
也用 a代替ToArray,因为它通常更快(优于)。valuesListToListToArray
TA贡献1779条经验 获得超6个赞
using Microsoft.VisualBasic.FileIO;
protected void CSVImport(string importFilePath)
{
string csvData = System.IO.File.ReadAllText(importFilePath, System.Text.Encoding.GetEncoding("WINDOWS-1250"));
foreach (string row in csvData.Split('\n'))
{
var parser = new TextFieldParser(new StringReader(row));
parser.HasFieldsEnclosedInQuotes = true;
parser.SetDelimiters(",");
string[] fields;
fields = parser.ReadFields();
//do what you need with data in array
}
}
- 3 回答
- 0 关注
- 172 浏览
添加回答
举报
