C# 优化嵌套循环
我的应用程序有一个嵌套for循环,内存有问题,我不知道如何改进它。我尝试过使用linq,但我想在内部是一样的,因为内存泄漏仍然存在 编辑:根据要求,我将提供有关我的问题的更多信息 我在Lucene文档库中为我的所有客户(约40万)编制了索引。每个客户都可以在多个机构中出现,其中一些机构的退出人数可以超过200-300个机构 我需要从“全球”客户索引中检索我的所有客户,并为每个机构建立一个单独的索引,只包含它可以看到的客户。有一些业务规则和安全规则需要应用于每个机构索引,所以现在,我不能为我的所有机构维护一个单一的客户索引 我的流程如下所示:C# 优化嵌套循环,c#,.net,lucene.net,C#,.net,Lucene.net,我的应用程序有一个嵌套for循环,内存有问题,我不知道如何改进它。我尝试过使用linq,但我想在内部是一样的,因为内存泄漏仍然存在 编辑:根据要求,我将提供有关我的问题的更多信息 我在Lucene文档库中为我的所有客户(约40万)编制了索引。每个客户都可以在多个机构中出现,其中一些机构的退出人数可以超过200-300个机构 我需要从“全球”客户索引中检索我的所有客户,并为每个机构建立一个单独的索引,只包含它可以看到的客户。有一些业务规则和安全规则需要应用于每个机构索引,所以现在,我不能为我的所有
int numDocuments = 400000;
// Get a Lucene Index Searcher from an Index Factory
IndexSearcher searcher = SearcherFactory.Instance.GetSearcher(Enums.CUSTOMER);
// Builds a query that gets everything in the index
Query query = QueryHelper.GetEverythingQuery();
Filter filter = new CachingWrapperFilter(new QueryWrapperFilter(query));
// Sorts by Agency Id
SortField sortField = new SortField("AgencyId, SortField.LONG);
Sort sort = new Sort(sortField);
TopDocs documents = searcher.Search(query, filter, numDocuments, sort);
for (int i = 0; i < numDocuments; i++)
{
Document document = searcher.Doc(documents.scoreDocs[i].doc);
// Builds a customer object from the lucene document
Customer customer = new Customer(document);
// If this nested loop is removed, the memory doesn't grow
foreach(Agency agency in customer.Agencies)
{
// Gets a writer from a factory for the agency id.
IndexWriter writer = WriterFactory.Instance.GetWriter(agency.Id);
// Builds an agency-specific document from the customer
Document customerDocument = customer.GetAgencyDocument(agency.Id);
// Adds the document to the agency's lucene index
writer.AddDocument(customerDocument);
}
}
int numDocuments=400000;
//从索引工厂获取Lucene索引搜索器
IndexSearcher searcher=SearcherFactory.Instance.GetSearcher(Enums.CUSTOMER);
//生成获取索引中所有内容的查询
Query Query=QueryHelper.GetEverythingQuery();
Filter Filter=new CachingWrapperFilter(new QueryWrapperFilter(query));
//按机构Id排序
SortField SortField=新的SortField(“AgencyId,SortField.LONG”);
排序=新排序(sortField);
TopDocs documents=searcher.Search(查询、筛选、numDocuments、排序);
对于(int i=0;i
编辑:解决方案
问题是我没有重用内部循环中“Document”对象的实例,这导致了我的服务内存使用量的不正常增长。仅在整个过程中重用单个Document实例就解决了我的问题
谢谢大家。关键可能是如何初始化
客户
和客户机构
。如果可以,不要返回一种类型的列表
,而是将返回类型设置为IEnumerable
和IEnumerable
。这可能会导致延迟执行,这会消耗更少的内存,但是可能会使手术时间更长
另一种选择是分批运行代码,因此请使用上面的代码,但要分批填充
列出客户
,例如,一次10000个。正如@RedFilter所说,尝试在使用yield语句时使用IEnumerable
这可能有助于:
在内存中循环一个allready加载到内存中的列表,您不会更改该列表正在使用的内存量 一定是您对列表中的项目所做的操作导致了内存使用
您需要查看您试图实现的目标,并重新设计您的程序,使其不会同时将所有数据存储在内存中。如果您的意思是要减少内存使用,那么基本的答案是将其分解 因此,将一家机构的所有客户纳入CustomerForagency集合,然后进行处理 清除或让CustomerForAgency集合超出范围,将使所有这些客户和(可选的)代理超出范围,从而允许.net重用内存
当然,这是假设大部分内存分配是为客户分配的,而不是用于处理的其他持久性实例,您可以简化它。我认为这里发生的是: 循环中创建的对象太多。如果可能,请不要使用new()循环内的关键字。初始化可跨循环重用的对象,并将数据传递给它们进行处理。不要在这么多的循环内构造新对象,因为垃圾回收将成为一个严重问题,垃圾回收器可能无法跟上您的进度,并将延迟回收
如果这是真的,你可以做的第一件事就是尝试每X个循环强制垃圾收集,并等待挂起的终结器。如果这会降低内存,你知道这是问题所在。解决方法很简单:不要每次循环迭代都创建新实例。首先,你应该重新使用
文档和字段
传递给IndexWriter.AddDocument()
的实例,以最小化内存使用并减轻垃圾收集器的压力
•重复使用Lucene 2.3中的文档和现场实例
允许您更改字段值的setValue(…)方法。
这允许您跨多个添加的字段重复使用单个字段实例
文档,这可以节省大量的GC成本。最好创建一个
单个文档实例,然后向其中添加多个字段实例,但
保留这些字段实例,并通过更改它们的
每个添加文档的值。例如,您可能有一个idField,
bodyField、nameField、storedField1等。添加文档后,
然后直接更改字段值(idField.setValue(…),
等),然后重新添加文档实例
请注意,不能在文档中重复使用单个字段实例,
并且,您不应该在文档关闭之前更改字段的值
包含该字段的已添加到索引中
这实际上取决于你在做什么,这段代码由itse编写