Lucene.Net 2.9.2: исключение OOM при добавлении большого количества документов - PullRequest
1 голос
/ 28 августа 2011

Я пытаюсь проиндексировать около 10.000.000 документов с помощью Lucene.NET 2.9.2. Эти документы (сообщения на форуме разной длины) берутся большими партиями по 10.000 из базы данных MSSQL, а затем передаются в мой класс-оболочку Lucene.NET с именем LuceneCorpus:

public static void IndexPosts(LuceneCorpus luceneCorpus, IPostsRepository postsRepository, int chunkSize)
{
    // omitted: this whole method is executed in a background worker to enable GUI feedback
    // chunkSize is 10.000
    int count = 0;
    // totalSteps is ~10.000.000
    int totalSteps = postsRepository.All.Count();
    while (true)
    {
        var posts = postsRepository.All.Skip(count).Take(chunkSize).ToList();
        if (posts.Count == 0)
            break;
        luceneCorpus.AddPosts(posts);
        count += posts.Count;                   
    }
    luceneCorpus.OptimizeIndex();
}

Я прочитал, что рекомендуется использовать один IndexWriter вместо открытия и закрытия нового для каждой группы документов. Поэтому мой класс LuceneCorpus выглядит так:

public class LuceneCorpus
{
    private Analyzer _analyzer;
    private Directory _indexDir;
    private IndexWriter _writer;

    public LuceneCorpus(DirectoryInfo indexDirectory)
    {
        _indexDir = FSDirectory.Open(indexDirectory);
        _analyzer = new StandardAnalyzer(Version.LUCENE_29);
        _writer = new IndexWriter(_indexDir, _analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);
        _writer.SetRAMBufferSizeMB(128);
    }

    public void AddPosts(IEnumerable<Post> posts)
    {
        List<Document> docs = new List<Document>();
        foreach (var post in posts)
        {
            var doc = new Document();
            doc.Add(new Field("SimplifiedBody", post.SimplifiedBody, Field.Store.NO, Field.Index.ANALYZED));
            _writer.AddDocument(doc);
        }
        _writer.Commit();
    }

    public void OptimizeIndex()
    {
        _writer.Optimize();
    }
}

Теперь моя проблема заключается в том, что потребление памяти постоянно заполняется, пока я, наконец, не достигну исключения из-за нехватки памяти после индексации около 700 000 документов где-нибудь в методе IndexPosts.

Насколько я знаю, средство записи индекса должно сбрасываться, когда оно достигает либо RAMBufferSize (128 МБ), либо при вызове Commit (). На самом деле, писатель определенно делает сброс и даже отслеживает приливы, но память все равно продолжает заполняться. Писатель как-то хранит ссылку на документы, чтобы они не были собраны в мусор, или что мне здесь не хватает?

Заранее спасибо!

Редактировать: Я также попытался инициализировать Writer, Analyzer и indexDir в области действия метода AddPosts вместо общеклассного, но это также не предотвращает исключение OOM.

Ответы [ 3 ]

1 голос
/ 28 августа 2011

Попробуйте самое последнее и лучшее.В ней исправлены некоторые утечки памяти.

https://svn.apache.org/repos/asf/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/

0 голосов
/ 29 августа 2011

Очевидно, Lucene не вызывал утечку памяти, но был DataContext моего PostsRepository. Я решил это, используя временный DC без отслеживания для каждой итерации «Take».

Извините и спасибо в любом случае!

0 голосов
/ 28 августа 2011

Я прочитал, что рекомендуется использовать один IndexWriter вместо открытия и закрытия нового для каждого большого объема документов.

Это может быть правдой в целом, но вашдело, кажется, требует другого подхода.Вы должны попробовать писателя в партии.Потребность в большом объеме памяти вынуждает вас использовать решение с неоптимальной эффективностью.Обменять память на скорость и наоборот - это обычное дело.

...