C# 优化嵌套循环

C# 优化嵌套循环,c#,.net,lucene.net,C#,.net,Lucene.net,我的应用程序有一个嵌套for循环,内存有问题,我不知道如何改进它。我尝试过使用linq,但我想在内部是一样的,因为内存泄漏仍然存在 编辑:根据要求,我将提供有关我的问题的更多信息 我在Lucene文档库中为我的所有客户(约40万)编制了索引。每个客户都可以在多个机构中出现,其中一些机构的退出人数可以超过200-300个机构 我需要从“全球”客户索引中检索我的所有客户,并为每个机构建立一个单独的索引,只包含它可以看到的客户。有一些业务规则和安全规则需要应用于每个机构索引,所以现在,我不能为我的所有

我的应用程序有一个嵌套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编写