2012-12-02 3 views
0

Я пишу очень большие документы (как размер, так и число) в индекс solr (100 полей полей со многими числовыми и некоторыми текстовыми полями). Я использую Tomcat 7 на W7 x64.Solrnet/Tomcat 7 - запись нескольких больших объемов памяти памяти растет тревожно

На основе @ Maurico-х suggestion when indexing millions of documents я распараллелить операцию записи (см пример кода ниже)

Запись в методе Solr в настоящее время «Задача» ред из основного контура (Примечание: Поручаю его после записи op занимает слишком много времени и занимает основное приложение)

Проблема в том, что потребление памяти растет неуправляемо, виновником является операция записи solr (когда я прокомментирую их, работа работает нормально). Как я могу справиться с этой проблемой? через Tomcat? или SolrNet?

Спасибо за ваши предложения.

 //main loop: 
     { 
       : 
       : 
       : 
      //indexDocsList is the list I create in main loop and "chunk" it out to send to the task. 
       List<IndexDocument> indexDocsList = new List<IndexDocument>(); 
       for(int n = 0; n< N; n++) 
       { 
        indexDocsList.Add(new IndexDocument{X=1, Y=2.....}); 
        if(n%5==0) //every 5th time we write to solr 
        { 
        var chunk = new List<IndexDocument>(indexDocsList); 
        indexDocsList.Clear(); 
        Task.Factory.StartNew(() => WriteToSolr(chunk)).ContinueWith(task => chunk.Clear()); 
        GC.Collect(); 
        } 
       } 
     } 

     private void WriteToSolr(List<IndexDocument> indexDocsList) 
     { 

      try 
      { 
       if (indexDocsList == null) return; 
       if (indexDocsList.Count <= 0) return; 
       int fromInclusive = 0; 
       int toExclusive = indexDocsList.Count; 
       int subRangeSize = 25; 

       //TO DO: This is still leaking some serious memory, need to fix this 
       ParallelLoopResult results = Parallel.ForEach(Partitioner.Create(fromInclusive, toExclusive, subRangeSize), (range) => 
       { 
        _solr.AddRange(indexDocsList.GetRange(range.Item1, range.Item2 - range.Item1)); 
        _solr.Commit(); 
       }); 


       indexDocsList.Clear(); 
       GC.Collect(); 
      } 
      catch (Exception ex) 
      { 
       logger.ErrorException("WriteToSolr()", ex); 
      } 
      finally 
      { 

       GC.Collect(); 
      }; 
      return; 
     } 
+0

IMHO этот код является чрезмерно сложным ... почему бы не просто использовать код, который я разместил в своем блоге? –

+0

@Maurico - как это может измениться? Я использую только разную процедуру распараллеливания. – Mikos

+0

Я думаю, что моя забота - Томкат, похоже, пережевывает много памяти, я делаю что-то принципиально неправильно? – Mikos

ответ

3

Вы вручную регистрируетесь после каждой партии. Это самая дорогая операция для Solr. В вашем случае я бы рекомендовал autoCommit каждые x секунд и выполнить функцию softAutoCommit (Solr 4.0). Это должно заботиться о стороне Солра. Вам также придется настроить параметры сборки мусора JVM, чтобы вы не перестали глотать мир GC.