2013-05-01 17 views
10

Zgodnie z this lub this użyłem tego samego narzędzia indeksującego według wielu wątków. Ale kiedy przestawiłem się z FsDirectory na MMapDirectory, otrzymałem interesujące wyjątki.Interesujący wyjątek Lucene.net

Ten drobny praca:

static void Main(string[] args) 
{ 
    DirectoryInfo directoryInfo = new DirectoryInfo(@"C:\Users\Tams\Desktop\new\"); 
    var directory = FSDirectory.Open(directoryInfo); 
    var indexSearcher = new IndexSearcher(directory); 

    const int times = 100; 
    const int concurrentTaskCount = 5; 
    var task = new Task[concurrentTaskCount]; 
    for (int i = 0; i < concurrentTaskCount; i++) 
    { 
     task[i] = new Task(() => Search(indexSearcher, times)); 
     task[i].Start(); 
    } 

    Task.WaitAll(task); 
} 

static void Search(IndexSearcher reader, int times) 
{ 
    List<Document> docs = new List<Document>(10000); 
    for (int i = 0; i < times; i++) 
    { 
     var q = new TermQuery(new Term("title", "volume")); 
     foreach (var scoreDoc in reader.Search(q, 100).ScoreDocs) 
     { 
      docs.Add(reader.Doc(scoreDoc.Doc)); 
     } 
    } 
} 

Ale z tym:

static void Main(string[] args) 
{ 
    DirectoryInfo directoryInfo = new DirectoryInfo(@"C:\Users\Tams\Desktop\new\"); 
    var directory = new MMapDirectory(directoryInfo); // CHANGED 
    var indexSearcher = new IndexSearcher(directory); 

    const int times = 100; 
    const int concurrentTaskCount = 5; 
    var task = new Task[concurrentTaskCount]; 
    for (int i = 0; i < concurrentTaskCount; i++) 
    { 
     task[i] = new Task(() => Search(indexSearcher, times)); 
     task[i].Start(); 
    } 

    Task.WaitAll(task); 
} 

static void Search(IndexSearcher reader, int times) 
{ 
    List<Document> docs = new List<Document>(10000); 
    for (int i = 0; i < times; i++) 
    { 
     var q = new TermQuery(new Term("title", "volume")); 
     foreach (var scoreDoc in reader.Search(q, 100).ScoreDocs) 
     { 
      docs.Add(reader.Doc(scoreDoc.Doc)); 
     } 
    } 
} 

uzyskać różne wyjątki, takie jak:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative 
            and less than the size of the collection. 
Parameter name: index 
at System.ThrowHelper.ThrowArgumentOutOfRangeException() 
at System.Collections.Generic.List`1.get_Item(Int32 index) 
at Lucene.Net.Index.FieldInfos.FieldInfo(Int32 fieldNumber) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\FieldInfos.cs:line 378 
at Lucene.Net.Index.FieldsReader.Doc(Int32 n, FieldSelector fieldSelector) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\FieldsReader.cs:line 234 
at Lucene.Net.Index.SegmentReader.Document(Int32 n, FieldSelector fieldSelector) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\SegmentReader.cs:line 1193 
at Lucene.Net.Index.DirectoryReader.Document(Int32 n, FieldSelector fieldSelector) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\DirectoryReader.cs:line 686 
at Lucene.Net.Index.IndexReader.Document(Int32 n) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\IndexReader.cs:line 732 
at Lucene.Net.Search.IndexSearcher.Doc(Int32 i) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Search\IndexSearcher.cs:line 162 
at PerformanceTest.Program.Search(IndexSearcher reader, Int32 times) 
    in c:\Users\Tams\Documents\Visual Studio 2012\Projects\BookCatalog\PerformanceTest\Program.cs:line 28 
at PerformanceTest.Program.<>c__DisplayClass2.<Main>b__0() 
    in c:\Users\Tams\Documents\Visual Studio 2012\Projects\BookCatalog\PerformanceTest\Program.cs:line 43 
at System.Threading.Tasks.Task.InnerInvoke() 
at System.Threading.Tasks.Task.Execute() 

Albo

System.IO.IOException: read past EOF 
at Lucene.Net.Store.BufferedIndexInput.Refill() 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Store\BufferedIndexInput.cs:line 179 
at Lucene.Net.Store.BufferedIndexInput.ReadByte() 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Store\BufferedIndexInput.cs:line 41 
at Lucene.Net.Store.IndexInput.ReadVInt() 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Store\IndexInput.cs:line 88 
at Lucene.Net.Index.FieldsReader.Doc(Int32 n, FieldSelector fieldSelector) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\FieldsReader.cs:line 230 
at Lucene.Net.Index.SegmentReader.Document(Int32 n, FieldSelector fieldSelector) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\SegmentReader.cs:line 1193 
at Lucene.Net.Index.DirectoryReader.Document(Int32 n, FieldSelector fieldSelector) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\DirectoryReader.cs:line 686 
at Lucene.Net.Index.IndexReader.Document(Int32 n) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Index\IndexReader.cs:line 732 
at Lucene.Net.Search.IndexSearcher.Doc(Int32 i) 
    in d:\Lucene.Net\FullRepo\trunk\src\core\Search\IndexSearcher.cs:line 162 
at PerformanceTest.Program.Search(IndexSearcher reader, Int32 times) 
    in c:\Users\Tams\Documents\Visual Studio 2012\Projects\BookCatalog\PerformanceTest\Program.cs:line 28 
at PerformanceTest.Program.<>c__DisplayClass2.<Main>b__0() 
    in c:\Users\Tams\Documents\Visual Studio 2012\Projects\BookCatalog\PerformanceTest\Program.cs:line 43 
at System.Threading.Tasks.Task.InnerInvoke() 
at System.Threading.Tasks.Task.Execute() 

Ostatni kod działa poprawnie, z ustawieniem zmiennej concurrentTaskCount na 1.

Czy brakuje mi czegoś? Nie mogę zrozumieć, co to jest.

Właściwie nie mam ścieżkę

d: \ Lucene.Net \ FullRepo \ trunk \ src \ rdzeń \ Store \ BufferedIndexInput.cs

ja nawet nie mają dysk z literą "d"

+1

Ścieżka wymienione w stacktrace wyjątków pochodzi z maszyny, która zbudowana binarny, a nie maszyny. – sisve

+0

Jeśli sądzisz, że znalazłeś błąd współbieżności w ramach implementacji MMapDirectory .Net, powinieneś zgłosić to do oficjalnego systemu śledzenia ścieżek Lucene.net –

+0

@JfBeaulac Nie wie, czy to błąd (został on wysłany do Lucene'a .NET mailing list), stąd zamieszczanie tutaj. – casperOne

Odpowiedz

3

W przypadku source for MMapDirectory widać, że ta klasa nie używa memory-mapped files, zgodnie z oczekiwaniami. Ładuje wszystkie pliki indeksu do pamięci za pomocą obiektów MemoryStream, i przypuszczam, że te strumienie są przyczyną problemu, gdy różne wątki szukają i czytają.

Można uzyskać indeks oparty na pamięci, ładując go do RAMDirectory. To mija twój test. (Ale robi to co robi obecnie MMapDirectory, niekoniecznie to, czego od niego oczekujesz ...)

var fsDirectory = FSDirectory.Open(directoryInfo); 
var directory = new RAMDirectory(fsDirectory); 
+0

Oczywiście, że nie. Jest to port z Java, gdzie mmapfiles nawet nie istnieje jako typ. Jeśli spojrzeć na źródło Java, to robi to samo. Implementacja FsDirectory jest wolniejsza dla większych indeksów, RAMDirectory byłoby świetne, ale mój indeks jest znacznie większy niż rozmiar dostępnej pamięci. Nawet gdyby był mniejszy, nadal cierpiałbyś na zatrzymania GC. –

+0

Java posiada FileChannel.map, który "mapuje region pliku tego kanału bezpośrednio do pamięci". Możesz znaleźć wywołanie w konstruktorze MMapIndexInput. Jest to zgodne z metodą MemoryMappedFile.CreateViewStream dostępną w .NET 4, ale port nie używa plików mapowanych w pamięci (co oczekiwałem, że zrobi, na podstawie nazwy). – sisve

+0

Ah. Teraz widzę. wielkie dzięki. T –