【发布时间】:2015-08-24 18:38:08
【问题描述】:
我正在开发一个项目(在 .NET 3.5 中),它读取 2 个文件,然后比较它们并找到丢失的对象。
基于这些数据,我需要进一步解析并定位对象位置。我将尝试进一步解释:
我有 2 个列表: 1 列表是服务器上所有文件的非常长的列表,以及它们在服务器或其他服务器上的物理地址,该文件的长度超过 10 亿行,并且还在不断增长(我知道有点荒谬)。目前文件大小约为 160MB。 另一个列表是显示服务器上丢失文件的报告列表。与列表 1 相比,此列表很小,通常小于 1MB。
我必须将列表 2 与列表 1 相交并确定丢失对象的位置。列表中的项目如下所示(不幸的是,它是空格分隔的,而不是 CSV 文档): filename.extension rev rev# source server:harddriveLocation\|filenameOnServer.extension origin
使用流,我将两个文件读入单独的字符串列表。然后我使用一个正则表达式并将列表 2 中的项目解析为包含 filename.extension、rev 和 rev# 的第三个列表。所有这一切都非常有效,它的表现让我很生气。
我希望有一种更有效的方法来做我正在做的事情。
foreach (String item in slMissingObjectReport)
{
if (item.Contains(".ext1") || item.Contains(".ext2") || item.Contains(".ext3"))
{
if (!item.Contains("|"))
{
slMissingObjects.Add(item + "," + slMissingObjectReport[i + 1] + "," + slMissingObjectReport[i + 2]); //object, rev, version
}
}
i++;
}
int j = 1; //debug only
foreach (String item in slMissingObjects)
{
IEnumerable<String> found = Enumerable.Empty<String>();
Stopwatch matchTime = new Stopwatch(); //used for debugging
matchTime.Start(); //start the stop watch
foreach (String items in slAllObjects.Where(s => s.Contains(item.Remove(item.IndexOf(',')))))
{
slFoundInAllObjects.Add(item);
}
matchTime.Stop();
tsStatus.Text = "Missing Object Count: " + slMissingObjects.Count + " | " + "All Objects count: " + slAllObjects.Count + " | Time elapsed: " + (taskTime.ElapsedMilliseconds) * 0.001 + "s | Items left: " + (slMissingObjects.Count - j).ToString();
j++;
}
taskTime.Stop();
lstStatus.Items.Add(("Time to complete all tasks: " + (taskTime.ElapsedMilliseconds) * 0.001) + "s");
这可行,但由于目前我的丢失对象列表中有 1300 个丢失项目,因此平均需要 8 到 12 分钟才能完成。耗时最长的部分是
foreach (String items in slAllObjects.Where(s => s.Contains(item.Remove(item.IndexOf(',')))))
{
slFoundInAllObjects.Add(item);
}
我只需要指出正确的方向,或许还需要帮助我了解如何改进我正在编写的代码。 LINQ 看起来并不是杀手,它把它添加到一个似乎会扼杀性能的列表中。
【问题讨论】:
-
为什么不使用数据库?
-
列表插入是 O(n),因此您永远不会对使用列表作为数据结构的插入进行顶级优化。堆栈或哈希表呢?此外,您是否对其进行了分析以确保您发现了代码的慢速部分?
-
如果是预分配的,列表插入可以是 O(1),你可以预分配吗?至少给出一个合理的期望?
-
不要使用列表。使用 HashSet。
-
slFoundInAllObjects.AddRange(slObjects.Where.....);为什么不使用 AddRange ?试试这个,看看。但是,问题也可能出在其他地方
标签: c# performance linq list hashset