4000 个我想对其进行字符串搜索的文件
Posted
技术标签:
【中文标题】4000 个我想对其进行字符串搜索的文件【英文标题】:4000 files that I want to do a string search on 【发布时间】:2013-06-19 00:53:54 【问题描述】:在多个文件中搜索字符串的最佳方法是什么?
目前我正在对每个文件进行 foreach 循环,但注意到它需要 4-5 分钟才能完成所有 4000 多个文件
是否有某种并行的方法可以做到这一点?
【问题讨论】:
1) 购买大 SSD,2) 购买大 RAID 阵列(然后才使用线程) 从一台物理设备按顺序读取是您在性能方面可以做的最好的事情。如果您一次打开 10 个文件并尝试扫描它们,则每次在硬盘驱动器上执行 io 操作时都会因过度搜索而受到惩罚。另外,您是否进行了测量并发现最大的等待时间在哪里? 如果您知道有关文件的任何具体信息...例如您要搜索的文本包含文件的前 100 个字节,则只需打开这些字节即可节省一些时间。更快的搜索/更快的关闭文件。 【参考方案1】:最好的方法是Producer Consumer model。你这样做是让一个线程从硬盘驱动器读取数据并将数据加载到队列中,然后你有不确定数量的其他线程处理数据。
所以说你的旧代码是这样的
foreach(var file in Directory.GetFiles(someSearch)
string textToRead = File.ReadAllText(file);
ProcessText(textToRead)
新代码是
var collection = new BlockingCollection<string>(); //You may want to set a max size so you don't use up all your memory
Task producer = Task.Run(() =>
foreach(var file in Directory.GetFiles(someSearch)
collection.Add(File.ReadAllText(file))
collection.CompleteAdding();
);
Parallel.ForEach(collection.GetConsumingEnumerable(), ProcessText); //Make sure any actions ProcessText does (like incrementing any variables in the class) is done in a thread safe manner.
它的作用是让一个线程从硬盘驱动器读取数据,而不是与任何其他线程争夺 I/O,但它允许多个线程同时处理所有读取的数据。
【讨论】:
我以前没有使用过 BlockingCollection,但如果我知道它在我早期的一些项目中是什么,我可能会使用它。 是的,它真的很棒,它为您处理所有线程安全问题,使用GetConsumingEnumerable()
使其使用起来超级简单。需要注意的一件事,默认情况下 BlockingCollection 使用 ConcurrentQueue 作为它的内部存储,如果你不关心从集合中出来的东西的顺序,你可以使用 different constructor 并传入 ConcurrentBag 和资源争用较少。
完美!所以我的下一个问题是,我有一个类,我正在更新每个方法,但不确定如何将类传递给我的“ProcessText”方法。我将如何处理?谢谢顺便说一句,这也是我第一次听说 BlockingCOllection :)
你可以使用匿名委托Parallel.ForEach(collection.GetConsumingEnumerable(), (text) => ProcessText(text,someOtherVariable));
我注意到这个过程占用了大量的内存,由于某种原因,我正在查看大约 600mb,这也比原来的方法花费了很多时间。有什么建议吗?【参考方案2】:
如果您定期进行此搜索,请考虑使用某些搜索引擎(如 Solr)为您的文件编制索引。文件被索引后,搜索需要几毫秒。
您还可以在您的应用中嵌入搜索引擎,例如,使用 Lucene 库。
【讨论】:
【参考方案3】:很可能大部分时间都花在等待从磁盘读取文件上。在这种情况下,多线程不会对您有太大帮助 - 现在有多个线程等待磁盘 IO,而不是让一个线程等待磁盘 IO。
【讨论】:
不一定,如果您将文件缓存到 RAM 中并且文件大小为几兆,则搜索的动作可能会比读取它的速度慢很多。【参考方案4】:此操作主要受 I/O 限制,因此并行处理不会真正为您带来任何额外的性能。您可以尝试使用 3rd-party 搜索库对文件进行索引,但就软件而言,这实际上是您所能做的。如果可以的话,将文件拆分到多个驱动器并为每个驱动器使用不同的线程有助于加快处理速度。
【讨论】:
对于几兆字节的文件,搜索可能比加载文件慢得多。 考虑到典型的内存带宽与 I/O 速度,这似乎不太可能。考虑到数千个文件可能不在连续空间中,大多数等待时间可能都花在等待磁盘的寻道头重新定位上。只是我的想法。以上是关于4000 个我想对其进行字符串搜索的文件的主要内容,如果未能解决你的问题,请参考以下文章