Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<Version>3.0.54013</Version>
<FileVersion>3.0.54013.0</FileVersion>
<Version>3.0.54015</Version>
<FileVersion>3.0.54015.0</FileVersion>
<LangVersion>latest</LangVersion>
<DebugType>embedded</DebugType>

Expand Down
59 changes: 21 additions & 38 deletions src/Lucene.Net/Index/ArrayHolder.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,40 @@
using System;
using System.Buffers;
using System.Threading;
using Lucene.Net.Store;
using Lucene.Net.Util;

namespace Lucene.Net.Index
{
public class ArrayHolder : IDisposable
{
private readonly int _size;
private readonly Directory _directory;
private readonly string _name;
private readonly long[] _longArray;
private readonly TermInfo[] _termInfoArray;
private readonly HybridArray<long> _indexPointers;
private readonly HybridArray<TermInfo> _termInfos;
private readonly UnmanagedIndexTerms _unmanagedIndexTerms;

private int _usages;
private long _managedAllocations;

public Span<long> LongArray => _longArray.AsSpan(0, _size);
public Span<TermInfo> InfoArray => _termInfoArray.AsSpan(0, _size);
public HybridArray<long> IndexPointers => _indexPointers;
public HybridArray<TermInfo> TermInfos => _termInfos;
public UnmanagedIndexTerms UnmanagedIndexTerms => _unmanagedIndexTerms;
public int ActualArraySize => _longArray.Length;

public static Action<long> OnArrayHolderCreated;

public static Action<long> OnArrayHolderDisposed;

public const int ArrayPoolThreshold = 128 * 1024;
public long TotalManagedAllocations => _indexPointers.TotalManagedAllocations + _termInfos.TotalManagedAllocations + _unmanagedIndexTerms.TotalManagedAllocations;

public ArrayHolder(int size, Directory directory, string name)
public ArrayHolder(int size, Directory directory, string name, FieldInfos fieldInfos)
{
_size = size;
_directory = directory;
_name = name;

if (size > ArrayPoolThreshold)
{
_longArray = new long[size];
_termInfoArray = new TermInfo[size];
}
else
{
_longArray = ArrayPool<long>.Shared.Rent(size);
_termInfoArray = ArrayPool<TermInfo>.Shared.Rent(size);
}
_indexPointers = new HybridArray<long>(size, UnmanagedStringArray.Type.TermCache, clear: false);
_termInfos = new HybridArray<TermInfo>(size, UnmanagedStringArray.Type.TermCache, clear: false);

_unmanagedIndexTerms = new UnmanagedIndexTerms(size);
_unmanagedIndexTerms = new UnmanagedIndexTerms(size, fieldInfos);
}

public void AddRef()
Expand All @@ -67,20 +56,20 @@ public static ArrayHolder GenerateArrayHolder(Directory directory, string name,
{
int indexSize = 1 + ((int)indexEnum.size - 1) / indexDivisor; // otherwise read index

var holder = new ArrayHolder(indexSize, directory, name);
var holder = new ArrayHolder(indexSize, directory, name, fieldInfos);

for (int i = 0; indexEnum.Next(state); i++)
{
holder.UnmanagedIndexTerms.Add(i, indexEnum.Field, indexEnum.TextAsSpan);
holder.InfoArray[i] = indexEnum.TermInfo();
holder.LongArray[i] = indexEnum.indexPointer;
holder.UnmanagedIndexTerms.Add(i, indexEnum.FieldNumber, indexEnum.TextAsSpan);
holder.TermInfos[i] = indexEnum.TermInfo();
holder.IndexPointers[i] = indexEnum.indexPointer;

for (int j = 1; j < indexDivisor; j++)
if (!indexEnum.Next(state))
break;
}

holder._managedAllocations = (holder.ActualArraySize * (TermInfo.SizeOf + sizeof(long)));
holder._managedAllocations = holder.TotalManagedAllocations;

OnArrayHolderCreated?.Invoke(holder._managedAllocations);

Expand All @@ -98,18 +87,12 @@ public void Dispose()
{
GC.SuppressFinalize(this);

OnArrayHolderDisposed?.Invoke(_managedAllocations);

_unmanagedIndexTerms?.Dispose();

if (_size > ArrayPoolThreshold)
return;

if (_longArray != null)
ArrayPool<long>.Shared.Return(_longArray);

if (_termInfoArray != null)
ArrayPool<TermInfo>.Shared.Return(_termInfoArray);
using (_unmanagedIndexTerms)
using (_indexPointers)
using (_termInfos)
{
OnArrayHolderDisposed?.Invoke(_managedAllocations);
}
}

~ArrayHolder()
Expand Down
9 changes: 7 additions & 2 deletions src/Lucene.Net/Index/SegmentTermEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,11 @@ public System.Object Clone(IState state)
return clone;
}

internal void Seek(long pointer, long p, Term t, TermInfo ti, IState state)
internal void Seek(long pointer, long p, (string Field, UnmanagedStringArray.UnmanagedString Text) tuple, TermInfo ti, IState state)
{
input.Seek(pointer, state);
position = p;
termBuffer.Set(t);
termBuffer.Set(tuple);
prevBuffer.Reset();
termInfo.Set(ti);
}
Expand Down Expand Up @@ -202,6 +202,11 @@ public string Field
get { return termBuffer.Field; }
}

public int FieldNumber
{
get { return termBuffer.FieldNumber; }
}

public Span<char> TextAsSpan
{
get { return termBuffer.TextAsSpan; }
Expand Down
9 changes: 5 additions & 4 deletions src/Lucene.Net/Index/Term.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

using System;
using System.Runtime.CompilerServices;
using Lucene.Net.Util;
using StringHelper = Lucene.Net.Util.StringHelper;

namespace Lucene.Net.Index
Expand Down Expand Up @@ -141,12 +142,12 @@ public int CompareTo(Term other)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int CompareTo(UnmanagedTerm other)
public int CompareTo((string Field, UnmanagedStringArray.UnmanagedString Text) tuple)
{
if (ReferenceEquals(field, other.Field))
return -other.Text.CompareTo(text);
if (ReferenceEquals(field, tuple.Field))
return -tuple.Text.CompareTo(text);

return String.CompareOrdinal(field, other.Field);
return String.CompareOrdinal(field, tuple.Field);
}

///// <summary>Resets the field and text of a Term. </summary>
Expand Down
28 changes: 22 additions & 6 deletions src/Lucene.Net/Index/TermBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
* limitations under the License.
*/

using System;
using Lucene.Net.Store;
using Lucene.Net.Support;
using Lucene.Net.Util;
using System;
using IndexInput = Lucene.Net.Store.IndexInput;
using UnicodeUtil = Lucene.Net.Util.UnicodeUtil;

Expand All @@ -28,6 +29,7 @@ public sealed class TermBuffer : System.ICloneable
{

private System.String field;
private int fieldNumber = -1;
private Term term; // cached
private bool preUTF8Strings; // true if strings are stored in modified UTF8 encoding (LUCENE-510)
private bool dirty; // true if text was set externally (ie not read via UTF8 bytes)
Expand All @@ -37,6 +39,7 @@ public sealed class TermBuffer : System.ICloneable

public Span<char> TextAsSpan => new Span<char>(text.result, 0, text.length);
public string Field => field;
public int FieldNumber => fieldNumber;

public int CompareTo(TermBuffer other)
{
Expand Down Expand Up @@ -71,7 +74,7 @@ internal void SetPreUTF8Strings()
preUTF8Strings = true;
}

public void Read(IndexInput input, FieldInfos fieldInfos, IState state)
public void Read(IndexInput input, FieldInfos fieldInfos, IState state)
{
this.term = null; // invalidate cache
int start = input.ReadVInt(state);
Expand Down Expand Up @@ -102,10 +105,12 @@ public void Read(IndexInput input, FieldInfos fieldInfos, IState state)
UnicodeUtil.UTF8toUTF16(bytes.result, start, length, text);
}
}
this.field = fieldInfos.FieldName(input.ReadVInt(state));
}

this.fieldNumber = input.ReadVInt(state);
this.field = fieldInfos.FieldName(fieldNumber);
}

public void Set(Term term)
public void Set(Term term)
{
if (term == null)
{
Expand All @@ -121,17 +126,28 @@ public void Set(Term term)
this.term = term;
}

public void Set(TermBuffer other)
public void Set((string Field, UnmanagedStringArray.UnmanagedString Text) tuple)
{
text.SetLength(tuple.Text.Size);
TextSupport.GetCharsFromUnmanagedString(tuple.Text, text.result);
dirty = true;
field = tuple.Field;
term = null;
}

public void Set(TermBuffer other)
{
text.CopyText(other.text);
dirty = true;
field = other.field;
fieldNumber = other.fieldNumber;
term = other.term;
}

public void Reset()
{
field = null;
fieldNumber = -1;
text.SetLength(0);
term = null;
dirty = true;
Expand Down
2 changes: 0 additions & 2 deletions src/Lucene.Net/Index/TermInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ namespace Lucene.Net.Index

public struct TermInfo
{
public static int SizeOf = sizeof(int) + sizeof(long) + sizeof(long) + sizeof(int);

/// <summary>The number of documents which contain the term. </summary>
internal int docFreq;

Expand Down
32 changes: 13 additions & 19 deletions src/Lucene.Net/Index/TermInfosReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,13 @@ sealed class TermInfosReader : IDisposable
{
private readonly Directory directory;
private readonly String segment;
private readonly FieldInfos fieldInfos;

private bool isDisposed;

private readonly LightWeightThreadLocal<ThreadResources> threadResources = new LightWeightThreadLocal<ThreadResources>();
private readonly SegmentTermEnum origEnum;
private readonly long size;

private UnmanagedIndexTerms unmanagedIndexTerms => _termsIndexCache.UnmanagedIndexTerms;
private Span<TermInfo> indexInfos => _termsIndexCache.InfoArray;
private Span<long> indexPointers =>_termsIndexCache.LongArray;

private readonly int totalIndexInterval;

private const int DEFAULT_CACHE_SIZE = 1024;
Expand Down Expand Up @@ -101,16 +96,15 @@ internal TermInfosReader(Directory dir, System.String seg, FieldInfos fis, int r
{
directory = dir;
segment = seg;
fieldInfos = fis;

origEnum = new SegmentTermEnum(directory.OpenInput(segment + "." + IndexFileNames.TERMS_EXTENSION, readBufferSize, state), fieldInfos, false, state);
origEnum = new SegmentTermEnum(directory.OpenInput(segment + "." + IndexFileNames.TERMS_EXTENSION, readBufferSize, state), fis, false, state);
size = origEnum.size;

if (indexDivisor != - 1)
{
// Load terms index
totalIndexInterval = origEnum.indexInterval * indexDivisor;
_termsIndexCache = directory.GetCache(segment + "." + IndexFileNames.TERMS_INDEX_EXTENSION, fieldInfos, readBufferSize, indexDivisor, state);
_termsIndexCache = directory.GetCache(segment + "." + IndexFileNames.TERMS_INDEX_EXTENSION, fis, readBufferSize, indexDivisor, state);
_termsIndexCache.AddRef();
}
else
Expand Down Expand Up @@ -197,7 +191,7 @@ private ThreadResources GetThreadResources(IState state)
private unsafe int GetIndexOffset(Term term)
{
int lo = 0; // binary search unmanagedIndexTerms[]
int hi = unmanagedIndexTerms.Length - 1;
int hi = _termsIndexCache.UnmanagedIndexTerms.Length - 1;

byte[] arr = null;
Span<byte> stringAsBytes;
Expand All @@ -223,7 +217,7 @@ private unsafe int GetIndexOffset(Term term)
while (hi >= lo)
{
int mid = Number.URShift((lo + hi), 1);
int delta = CompareTerms(term.Field, stringAsBytes, stringAsSpan, unmanagedIndexTerms[mid]);
int delta = CompareTerms(term.Field, stringAsBytes, stringAsSpan, _termsIndexCache.UnmanagedIndexTerms[mid]);
if (delta < 0)
hi = mid - 1;
else if (delta > 0)
Expand All @@ -241,12 +235,12 @@ private unsafe int GetIndexOffset(Term term)
}
}

private static int CompareTerms(string field, Span<byte> stringAsBytes, ReadOnlySpan<char> stringAsChar, UnmanagedTerm unmanagedTerm)
private static int CompareTerms(string field, Span<byte> stringAsBytes, ReadOnlySpan<char> stringAsChar, (string Field, UnmanagedString Text) tuple)
{
if (ReferenceEquals(field, unmanagedTerm.Field))
return UnmanagedString.CompareOrdinal(stringAsBytes, stringAsChar, unmanagedTerm.Text);
if (ReferenceEquals(field, tuple.Field))
return UnmanagedString.CompareOrdinal(stringAsBytes, stringAsChar, tuple.Text);

return String.CompareOrdinal(field, unmanagedTerm.Field);
return String.CompareOrdinal(field, tuple.Field);
}

internal static Term DeepCopyOf(Term other)
Expand All @@ -257,8 +251,8 @@ internal static Term DeepCopyOf(Term other)
}

private void SeekEnum(SegmentTermEnum enumerator, int indexOffset, IState state)
{
enumerator.Seek(indexPointers[indexOffset], ((long)indexOffset * totalIndexInterval) - 1, unmanagedIndexTerms[indexOffset].ToTerm(), indexInfos[indexOffset], state);
{
enumerator.Seek(_termsIndexCache.IndexPointers[indexOffset], ((long)indexOffset * totalIndexInterval) - 1, _termsIndexCache.UnmanagedIndexTerms[indexOffset], _termsIndexCache.TermInfos[indexOffset], state);
}

/// <summary>Returns the TermInfo for a Term in the set, or null. </summary>
Expand Down Expand Up @@ -295,7 +289,7 @@ private TermInfo Get(Term term, bool useCache, IState state)
if (enumerator.Term != null && ((enumerator.Prev() != null && term.CompareTo(enumerator.Prev()) > 0) || term.CompareTo(enumerator.Term) >= 0))
{
int enumOffset = (int) (enumerator.position / totalIndexInterval) + 1;
if (unmanagedIndexTerms.Length == enumOffset || term.CompareTo(unmanagedIndexTerms[enumOffset]) < 0)
if (_termsIndexCache.UnmanagedIndexTerms.Length == enumOffset || term.CompareTo(_termsIndexCache.UnmanagedIndexTerms[enumOffset]) < 0)
{
// no need to seek

Expand Down Expand Up @@ -340,9 +334,9 @@ private TermInfo Get(Term term, bool useCache, IState state)
return ti;
}

private void EnsureIndexIsRead()
private void EnsureIndexIsRead()
{
if (unmanagedIndexTerms == null)
if (_termsIndexCache.UnmanagedIndexTerms == null)
{
throw new SystemException("terms index was not loaded when this reader was created");
}
Expand Down
Loading