2013-05-01 2 views
10

this 또는 this에 따르면 동일한 스레드 검색기를 여러 스레드에서 사용했습니다. 하지만 FsDirectory에서 MMapDirectory로 전환했을 때 흥미로운 예외가있었습니다.흥미로운 Lucene.net 예외

이 잘 작동 :

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)); 
     } 
    } 
} 

그러나이와 :

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() 

또는

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() 
:

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)); 
     } 
    } 
} 

내가 좋아하는 다양한 예외를 얻을

concurrentTaskCount 변수를 1로 설정하여 마지막 코드가 올바르게 작동합니다.

내가 누락 되었습니까? 나는 그게 뭔지 알아 내지 못합니다. 사실

, 나는 경로를 해달라고

D : \ Lucene.Net \ FullRepo 트렁크 \의 SRC \ 코어 \ 저장 \ \ BufferedIndexInput.cs

나는 심지어이없는 "d"문자가있는 드라이브

+1

예외 스택 추적에 언급 된 경로는 시스템이 아닌 이진 파일을 작성한 시스템에서 가져옵니다. – sisve

+0

MMapDirectory .Net 구현 내에서 동시성 버그를 발견했다고 생각하면 Lucene.net projet offical bugtracking 시스템에보고해야합니다. –

+0

@JfBeaulac 그는 버그인지 여부를 알지 못합니다 (Lucene에 게시되었습니다. .NET 메일 링리스트), 여기에 게시하십시오. – casperOne

답변

3

source for MMapDirectory은이 클래스가 예상대로 memory-mapped files을 사용하지 않는다고 나타냅니다. MemoryStream 객체를 사용하여 모든 인덱스 파일을 메모리에로드합니다. 다른 스레드가 검색하고 읽을 때 이러한 스트림이 문제의 원인이라고 추측 할 수 있습니다.

RAMDirectory에 메모리 기반 색인을로드하여 가져올 수 있습니다. 이것은 당신의 시험을 통과합니다. (하지만 MMapDirectory가 현재하고있는 것을 수행합니다. 반드시 수행 할 작업이 아닙니다 ...)

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

물론 그렇지 않습니다. 그것의 mmapfiles가 유형으로 존재하지 않는 자바에서 포트. 자바 소스를 살펴 본다면 똑같은 시간이 걸린다. FsDirectory 구현이 더 큰 인덱스의 경우 느리면 RAMDirectory는 좋지만 인덱스는 사용 가능한 메모리 크기보다 훨씬 큽니다. 심지어 더 작을지라도 GC 중지로 어려움을 겪을 수 있습니다. –

+0

Java에 "이 채널의 파일 영역을 메모리에 직접 매핑"하는 FileChannel.map이 있습니다. MMapIndexInput 생성자에서 호출을 찾을 수 있습니다. 이것은 .NET 4에서 사용 가능한 MemoryMappedFile.CreateViewStream 메서드와 일치하지만 포트는 메모리 매핑 된 파일을 사용하지 않습니다 (이름에 따라 예상 한 것). – sisve

+0

아. 나는 지금 본다. 고마워. T –