我有一个运行的服务,它会定期检查文件夹中的文件,然后对其进行处理。 (读取它,提取数据,将其存储在sql中)
所以我在一个测试盒上运行它,预计需要更长的时间。 该文件有160万行,6小时后它仍在运行(然后我回家了)。
问题是它运行的盒子现在已经完全瘫痪了 - 远程桌面超时了所以我甚至无法停下来停止这个过程,或者附上一个调试器来看看有多远等等。 它坚固地使用90%以上的CPU,所有其他正在运行的服务或应用程序正在受到影响。
代码是(从内存中,可能无法编译):
List<ItemDTO> items = new List<ItemDTO>();
using (StreamReader sr = fileInfo.OpenText())
{
while (!sr.EndOfFile)
{
string line = sr.ReadLine()
try {
string s = line.Substring(0,8);
double y = Double.Parse(line.Substring(8,7));
//If the item isnt already in the collection, add it.
if (items.Find(delegate(ItemDTO i) { return (i.Item == s); }) == null)
items.Add(new ItemDTO(s,y));
}
catch { /*Crash*/ }
}
return items;
}
- 所以我正在努力改进代码(任何提示赞赏)。
但它仍然可能是一个缓慢的事情,这很好,我没有问题,只要不杀死我的服务器需要很长时间。
所以我想要你好人是: 1)我的代码是否可靠地未经优化? 2)我可以限制代码块可能使用的CPU数量吗?
干杯全部
答案 0 :(得分:10)
不是限制其CPU使用率,而是将其设置为空闲优先级可能会更好,所以它只会在没有其他任何东西可以运行的情况下运行。其他人已经提到了优化的可能性,所以我不会尝试进入那个部分。
答案 1 :(得分:8)
在列表上执行查找是O(n)操作,这意味着当列表变长时,搜索项目需要更长时间。您可以考虑将项目放入.NET 4.0 / 3.5中的HashSet或使用Dictionary用于早期版本的.NET,它可以像索引一样,如果您需要列表中的项目来维护你可以继续将它们放在列表中的原始顺序,但使用HashSet / Dictionary进行检查。
您还可以在BackgroundWorker线程中运行此代码,这有助于在流程运行时保持UI响应。
答案 2 :(得分:4)
列表中的查找是O(n)。如果文件有160万行(即160万个项目),那么你将反复走过一百多万行的列表,这会浪费很多时间。
正如其他人所建议的那样,如果你进行了大量的搜索,那么你需要一个更好的数据结构。一个专为更快搜索而设计的。
如果使用.NET 3.5,则可以使用HashSet集合,该集合为搜索提供分摊的O(1)。或者字典集合使用的是.NET 2.0
接下来你必须问自己,如果文件有160万行,你有足够的内存吗?如果你这样做,那么在内存中解析文件比将其发送到数据库以处理重复文件更快,但如果你没有足够的内存,那么你将进行分页。很多。 (这可能是现在发生的事情)。
答案 3 :(得分:3)
正如其他人所说,修复数据结构。
现在,我的眼睛点击了这句话“定期检查文件夹中的文件,然后对其进行处理。”经常“定期”以及为什么处理可能没有改变的文件?
您可能需要查看System.IO.FileSystemWatcher http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
答案 4 :(得分:1)
您无法使用SqlBulkCopy Class批量加载此文件,然后在数据库服务器上进行处理吗?
答案 5 :(得分:1)
回答1)我会使用排序列表(如果有大量冗余数据)或哈希字典而不是常规字典来加速搜索。
以下是another post,可帮助您决定两种方法。
问题2的),我将线程优先级设置为低于正常值。请参阅here。
答案 6 :(得分:0)
您真的需要将所有数据保存在内存中吗?您可以将它存储在数据库中(如果您需要使用简单且功能强大的Sqlite)并使用sql进行处理。
答案 7 :(得分:0)
答案 8 :(得分:0)
我不是一个c#程序员,但看着我认为的逻辑
每次在循环中创建一个新的字符串对象。如果我必须在java中这样做, 而不是使用字符串对象,我会使用StringBuffer。
您的数据文件很大,所以我认为您应该有清除信息的逻辑 每'n'个记录后的数据库。您需要额外的逻辑来记录哪些 记录被清除到目前为止。或者,因为您的逻辑仅捕获第一行数据 &安培;忽略后续的重复,而不是使用Find方法,你不能只是尝试插入 数据并捕获sql失败。
处理逻辑应位于单独的线程中以保持系统响应。