Added
Search(Query, int, SortField)detects index-sort match and returns early after collecting topN live docs from postings iteration without scoring (dfecfdd58)FileOpenRetry.Move,.Copy,.Delete,.DeleteDirectory,.CreateDirectory,.ReadLines,.FileExists,.EnumerateFiles,.GetFileswith 5×10ms retry onIOException/UnauthorizedAccessExceptionto absorb transient Windows file locks from Defender and mmap handle release (839078bcb)ScheduleBackgroundMergenow logs merge exceptions viaTraceSwallowed("background-merge")for diagnosability (d50b1f881)- CodecKit trailer format (
[version][body][bodyLen:int64]) enabling zero-buffer streaming writes across all codec types (b69a4c0f, 3d3c1524c) StoredFieldsReader.DocCountandStoredFieldsReader.Compressionproperties exposing metadata from the stored-fields file headers (b69a4c0f)IndexSearcher.Search(Query, SearchOptions)andSearchAsync(Query, SearchOptions, CancellationToken)overloads that honourStreamResultsfor per-segment streaming without a global top-N heap (5573b0c1)IndexOpenGuardintegration tests (877682f5)- Added
FieldType.Int64andInt64Field, and the pipeline infrastructure (3dfb10a1) - Added codec constants, format entries, and file extension table entries for
.numl,.dvnl,.dsnl, and.bkdl(3dfb10a1) ConcurrentVsSequentialBenchmarkssuite comparingAddDocumentsConcurrentandAddDocumentLockFreethroughput against sequentialAddDocumentat batch sizes of 100, 1000, and 10 000 documents. Theconcurrent-writesuite name is registered in bothbenchmark.ps1andbenchmark.sh.- LINQ queryable provider via
LeanQueryable<T>and theLeanExpressionVisitorexpression-tree translator.Where,Select,First,Single,Count,Any,Take,Skip,OrderBy, andOrderByDescendingoperators are supported; lambda predicates (==,!=,>,>=,<,<=,&&,||,!,.Contains(),.StartsWith(),.EndsWith()) are translated into nativeQueryobjects and executed directly against the index with no intermediate SQL or reflection. The Roslyn source generator emits a zero-allocation field-descriptor switch expression and anAsQueryable(IndexSearcher)entry point for[LeanDocument]-annotated models.LeanField<TDoc,TVal>andLeanFieldBinding<TDoc>implementIFieldDescriptorfor AOT-compatible field resolution. Ships with unit, integration, and chaos test suites. - Multilingual Wikipedia download script (
scripts/download-wikipedia.sh) with BCP 47 language code support, jq-based null-delimited record extraction, and exponential backoff rate limiting for 300+ language editions. The PowerShell script (download-wikipedia.ps1) gained the same-Languageparameter for cross-language benchmark data collection. - LINQ queries tutorial (
docs/tutorials/searching/07-linq-queries.md) covering quick start, supported operators, LINQ methods, allocation profile, and AOT compatibility guidance. - Vector quantisation: scalar (float32 → int8) and binary (BBQ) with a
VectorQuantisationenum (None,Int8,BBQ), configurable per-field viaVectorFieldInfo.Quantisationand globally viaIndexWriterConfig.VectorQuantisation. HNSW graphs are built against quantised representations; includesInt8DistanceComputerandBBQDistanceComputerfor distance-aware KNN retrieval, plus an Int8 fast path in HNSW distance computation. - CodecKit: a composable binary codec framework with primitive codecs (VarInt, VarUInt, fixed-width integers, byte sequences), combinators (fixed-frame, length-prefixed, bytes-owned), integrity wrappers (CRC32, xxHash32, xxHash64 with header or trailer placement, version envelope), Deflate compression wrapping, and an immutable
CodecRegistry. Ships with unit, integration, chaos, and compression-parity test suites. - Five new scoring models:
Bm25PlusSimilarity,Bm25LSimilarity, and three TF-IDF variants (TfIdfAugmentedSimilarity,TfIdfDoubleNormSimilarity,TfIdfPivotedSimilarity). - Three language-model similarities:
LMJelinekMercerSimilarity(linear interpolation),DirichletSimilarity(Bayesian smoothing), andLMAbsoluteDiscountingSimilarity(absolute discounting). All consumeCollectionStatisticsfor term probability estimation. PostingsHighlighterandTermVectorHighlighterfor snippet extraction using stored term-vector offsets without re-analysing the original text.HybridHighlightercombines stored-field re-analysis with term-vector snippet placement.StoreDocValuesflag onStringField,TextField, andNumericField(defaults:trueforStringField/NumericField,falseforTextField). Whenfalse, the field skips populating sorted, sorted-set, numeric, and binary DocValues, cutting per-document buffer overhead and shrinking the flush I/O footprint.- Profiling project with
ActivitySource-based phased breakdown of indexing time (add_document,analyse,flush,commit,merge), plus a deletion-phased benchmark.
Changed
- Read, move, delete, copy, and directory-delete operations now use platform-aware transient retry with 5×200ms on Windows and zero overhead on Linux (e633ca4b)
FunctionScoreQuerywith aTermQueryinner now takes a dedicatedSearchCorefast path, reusingThreadStaticbuffers and eliminating the generic-pathPrecomputeGlobalDocFreqsandParallel.ForEachoverhead (a04036a42)SearchWithAggregations,SearchWithCollapse, andSearchWithFacetsnow use a single-pass postings iteration with side-collectors instead of executing two full searches (dfecfdd58)ExecuteFunctionScoreQueryuses inline scoring for TermQuery inners, eliminating the intermediateTopNCollector(reader.MaxDoc)allocation (dfecfdd58)ExecuteShouldOnlyHeapuses proper multi-way heap merge instead of full heap rebuild per iteration, and the heap threshold is raised from 16 to 64 (dfecfdd58)ExecuteMoreLikeThiscaches extracted candidate terms with ConcurrentDictionary generation-swap eviction and uses string-based qualified term lookups for FST cache hits (dfecfdd58)- All
File.*/Directory.*/FileStreamcalls across 15 files now route through FileOpenRetry wrappers, including IndexCodecMigrator, IndexRecovery, CommitManager, IndexWriter, deletion policies, SegmentMerger, IndexStats, IndexBackup, IndexMigrationRecovery, StoredFieldsStreamWriter, ParentBitSet, RoaringBitmap, SlowQueryLog, KStemLexicon, and ThaiTokeniser (839078bcb) - IndexAtomicFileWriter.Write uses FileOpenRetry.Move and FileOpenRetry.Delete instead of its own inline retry loop (839078bcb)
- During file teardown and cleanup bare exceptions are now routed through
TraceSwallowedso suppressed IO and permission errors are observable in diagnostic tooling (7f373517e) - Replaced exact float equality checks on Boost with
Math.Absepsilon comparison (1e-6f) in four locations flagged by SonarQube (190de56de) - Postings (
.pos) now uses a v2 streaming format without a body-length prefix, eliminating full-body buffering during merge, flush and migration (285c54f72) - Test cleanup across 33 files now uses
TestDirectoryFixture.TryDeleteDirectorywith a GC+retry loop instead of silently swallowingDirectory.Deletefailures (6421de1b) - Highlighter.ExtractTerms now collects terms from WildcardQuery, FuzzyQuery, TermInSetQuery, MultiPhraseQuery, CombinedFieldsQuery, and wrapper queries (ConstantScoreQuery, DisjunctionMaxQuery, FunctionScoreQuery), so highlighting works across more query families (503be7c2)
- IndexCodecMigrator now uses a mandatory staging directory for all migrations, writes migrated segments under new IDs, and atomically publishes the new commit; --in-place flag removed from CLI (d97a9927)
- ICollector is now wired into IndexSearcher via Search(Query, ICollector); Count(Query) returns total hits without materialising a scored heap; CountCollector is now thread-safe (19bf3cdb)
- QueryCache is now owned by SearcherManager and shared across searcher refreshes, so cached results survive when content hasn't changed (7ee5f977)
- FlushDwptPool now asserts that the caller holds WriteLock, making the lock contract explicit and catching misuse in debug builds (84cbc9fc)
- Moved AOT smoke console project into an xUnit 3 AOT test project. (e6741301, 7a79c1b1)
ShingleFilterandSynonymGraphFilternow buffer tokens inApplyand generate expansions inFinishinstead of being pass-through stubs.SnowballStemmerabstract base replaces seven duplicatedRemoveSuffiximplementations with a configurable N-step pipeline, pre/post-processing hooks, and per-language suffix arrays (Italian, Portuguese, Spanish, Dutch, French, German, Russian).SharedStandardIndexnow builds and caches a shared Lucene.NET index alongside the LeanCorpus one, stripping ~500 lines of duplicated Lucene setup/teardown from ten search benchmark suites.IndexWriter.Disposedrain timeout changed from throwing to logging viaTraceSwallowed.CombinedFieldsQueryBenchmarks,QueryCacheBenchmarks, andCollapseAndFacetBenchmarksuse sharedAddDocumentshelpers and pre-built queries to cut duplicated index construction.- KStemmer rule lookup uses a
FrozenDictionarykeyed by the last two characters of each suffix, with a one-character fallback, replacing linear scan of all rules.StemTokenFilteradded a character-based pre-filter that skips buffer allocation for tokens whose last character cannot begin a stemming suffix (~85% of tokens). - Wildcard query execution pre-narrows the FST traversal by walking a known literal prefix (≥2 characters) ahead of the automaton intersection, avoiding per-candidate string materialisation for suffix-only pattern matching.
TermDictionaryReadergainedGetTermsMatchingWithPrefixandGetTermOffsetsMatchingWithPrefix;IndexSearcherandSegmentReaderplumb through the prefix-narrowed overloads. - Pending deletion in
IndexWriteris now applied via a single FST prefix scan per unique field rather than per-term individual lookups, matching against aHashSet<string>of bare terms per field. Hard and soft deletes share the same scan infrastructure. Highlighterdetects matching tokens inline during tokenisation viaOffsetCapturingSink, removing the separate O(n) post-tokenisation match scan and its associatedList<int>buffer.- MoreLikeThis candidate selection replaced
List<(float,string,string)>+Sortwith a boundedPriorityQueuemin-heap and a reusable pooledchar[]buffer for qualified-term construction, eliminating per-term string allocations in the cross-segment DF scan. - Benchmark temp directories now live under
bench/tmp/(resolved relative to the repository root) instead of the system temp directory. A newBenchmarkHelpersclass centralises Create, Delete, and full-tree cleanup;Program.cscleans stale temp directories before and after the full benchmark run. Static Lucene.NET index resources are explicitly cleaned up by each search benchmark class.CountingTokenSinkis reused as a field across benchmark iterations to avoid skewing allocation measurements. - Positions in
PostingAccumulatorare now stored as VarInt delta-encoded bytes instead of rawint[], eliminating ~32 MB of GC pressure per 20K-document indexing run. - The indexing hot path uses an open-addressing byte-ref hash table (
BytesRefHash) for postings accumulation, removing per-token string allocations during tokenisation. - Character-offset array allocation in
PostingAccumulatoris gated onIndexWriterConfig.StoreTermVectors, reducing per-term allocations by ~5× when term vectors are disabled. ScoreTermscoring made branchless via DIM devirtualisation, and phrase queries now intersect candidate documents before decoding positional data.- SIMD-accelerated ASCII lowercasing added to stemmers,
LowercaseFilter, andStandardAnalyserviaAsciiCharInspector. Analyserconstructor now acceptsISpanTokeniserdirectly;IStemmerremoved in favour ofISpanStemmer.AnalyserFactoryprovides static construction helpers.RamBufferSizeMBdefault raised from 16 to 512.PushDepthwired into all nesting codecs to enforce a maximum nesting depth, preventing stack overflows on malformed inputs.- All per-codec format versions reset to 1 following the CodecKit migration. Legacy term dictionary v1/v2 codec,
ICompressionProviderabstraction, and old-format readers removed. - Kernel hints (
SequentialScan,WriteThrough) applied to merge I/O paths. - Concurrent indexing path: each DWPT partition now flushes its own segment to disk via
SegmentFlusher.FlushFromDwptinstead of merging into the main buffer.MergeDwpt,MergeMultiValuedDocValues, andAppendMergedStoredFieldare deleted. HNSW graph construction is skipped on segments with fewer than 128 documents. (ADR005) HnswGraph.FromFrozenno longer allocates a wasted mutable dictionary in the constructor. A private constructor accepts thefrozenflag and skips mutable-level initialisation, and_mutableLevelsis no longerreadonly.IndexWriter.Disposeno longer spins indefinitely waiting for in-flight indexing operations. A 30-second timeout prevents a stuckAddDocumentcall from hanging process shutdown.- Every swallowed exception across the library now logs via
LeanCorpusActivitySource.TraceSwallowed, writing toDebug.WriteLineso filesystem errors during cleanup, fsync, merge, and event dispatch are no longer silent. AddDocumentsConcurrentnow clears the DWPT betweenParallel.ForEachranges, preventing accumulated document data from inflating segment doc counts when a thread processes multiple ranges.QueryCache.Putno longer increments the approximate count on duplicate keys.Commitnow waits for the background merge to finish before returning, preventing a race where a reader opened immediately after commit could see a new commit referencing segment files the merge had not yet flushed to disk.QueryCacheusesConcurrentDictionarywith generation-swap eviction instead ofDictionary+Lock+LinkedList. TheTryGetpath is lock-free.Puttriggers a dictionary swap when the soft entry cap is exceeded. (ADR004)CodecFormatDescriptornow carries aHeaderFormatfield per extension, populated fromCodecFormats, so version checks use the correct codec format rather than a single hardcoded value.- CodecKit extension points previously marked
internalare nowpublicso third-party codec authors can register custom checksums and formats:ChecksumAlgorithmId,ChecksumPlacement,IChecksumProvider,CodecFileHeader, andCodecFormat. - The CodecKit exception hierarchy was reorganised with three purpose-built public base classes.
CodecFormatExceptioncovers structural problems (unknown version, trailing data, insufficient data),CodecIntegrityExceptioncovers checksum and hash failures, andCodecResourceExceptioncovers allocation and overflow errors. The intermediateFormatViolationExceptionwas removed and its subtypes distributed to the new bases.CodecValidationExceptionwas made public. - Norms format bumped to v2.
NormsReaderreads both v1 and v2 on open;NormsWriterproduces v2. A migration path upgrades v1.nrmfiles in place. SearcherManager.AcquireandAcquireLeasespin-waits now throwTimeoutExceptionafter 30 seconds instead of spinning indefinitely, matching the timeout applied toIndexWriter.Dispose.
Fixed
FileOpenRetry.Openno longer retries write/create operations, eliminating the 5s-per-thread stall that causedWriteLock_ConcurrentWriterConstruction_AllowsExactlyOneWriterto time out on Windows (e633ca4b)TestDirectoryFixturecleanup usesFileOpenRetry.DeleteDirectoryso transient AV scan locks on leftover test files do not cascade into CI errors (e633ca4b)- All
Rewrite*methods inIndexCodecMigratornow enumerate source files once into memory instead of openingIndexInputtwice, fixingLLIDX040file-locking failures on Windows CI (69af2fdf7) RewritePostingsnow releases memory-mapped file handles and forces finalizer cleanup before overwriting source files, fixingLLIDX040failures in IndexCodecMigrator tests on Windows CI (5d7e9b58b, 70343f724)SearchWithFacetsnow falls back to a two-pass search for non-TermQueryqueries, fixing facet collection forMatchAllDocsQueryand other complex query types (9d653096b)FileOpenRetry.Opennow catchesIOException(the exception Windows throws for file-locking) in addition toUnauthorizedAccessException, so the retry backoff actually fires instead of propagating immediately to callers (c892a4362)RewriteTermDictionaryno longer holds an MMF-backedIndexInputopen on the source.dicfile after the version probe, preventingIOException("file in use by another process") when the subsequentFile.CopyorFile.Moveruns on Windows (e064ac2f4)QueryParsernow supports backslash escaping (\:,\\,\+, etc.) in term tokens so values containing colons such as URLs, timestamps, and file paths are not prematurely split at:(2f3318d7d)EvaluateMemberExpressionnow rejects non-field member access (properties, static members, chained access) with a clearNotSupportedExceptioninstead of silently compiling and invoking arbitrary code such asDateTime.NoworsomeObj.ExpensivePropertyduring query translation (2961ef826)RewriteTermDictionarynow correctly rewrites.dicfiles from older CodecKit versions by re-encoding the FST at the current envelope version instead of throwingInvalidDataException(904be6020)IndexWriter.Disposeno longer throwsObjectDisposedExceptionfromSemaphoreSlim.Releasewhen the 30-second drain timeout expires while in-flight threads are still flushing segments (81ab65fa5)- Concurrently indexed segments (via
AddDocumentLockFree/AddDocumentsConcurrent) now write.tvd/.tvxterm vectors, apply char filters, and conditionally drop token offsets whenStoreTermVectorsis false, matching the sequential indexing output (bcfd778d6) - Async indexing methods no longer block thread-pool threads on
_writeLockafter await, preventing pool starvation under concurrentasyncwrites (42c2e01fb) AcquireBackpressureSlotAsyncswallowedObjectDisposedExceptionduring shutdown and returned without a backpressure slot; removed and replaced by channel-based serialisation (42c2e01fb)RewriteNormsno longer buffers every field's boost arrays in a dictionary during migration, preventing OOM on indexes with many boosted fields (9f989508a)RewriteNumericDocValuesno longer buffers every field's presence sets in a dictionary during migration, preventing OOM on indexes with many sparse numeric fields (9f989508a)- Background segment merge failures no longer go unobserved; the writer is marked as failed and future operations throw
InvalidOperationExceptionwith a clear message instead of silently accumulating segments (d50b1f881) PublishStagingFilesno longer skips existing files or leaves source files absent from staging, preventing mixed-format indexes after codec migration (ba3fb8dc1)- LZ4, Snappy, and Zstandard compression codecs now survive Native AOT trimming with
DynamicDependencyannotations and AOT smoke coverage for explicitRegister()calls Bumped all three: 1.0.0 to 1.0.1 (6baef8281) - Floating-point inequality comparisons with exact values in boost checks (3d3c1524c)
StoredFieldsReaderno longer allocates unbounded byte arrays from file-declared lengths, enabling compression-bomb denial-of-service (7efc69fc8)SearcherManagerrefresh loop caught and suppressed fatal exceptions, causing thrashing onOutOfMemoryException(d1ebf824b)RrfQuery,MoreLikeThisQuery, andBlockJoinQueryno longer return zero results when searched via theCancellationTokenorSearchOptionsoverloads (2011ed19b)ForceMergeandCompactcould silently drop segments when merging segments containing only dead documents (adfce1628)- Resolved all xUnit2020 and xUnit1051 analyser warnings in the AOT smoke test project (56a1db09a)
SortedDocValuesReadernow validates unpacked ordinals against the ord-table size and rejectsbitsPerOrd > 63,preventing crashes on corrupt or empty sortedDocValuesfields (2ae3dd75b)BKDReadernow validates node markers, leaf counts against remaining file bytes, and caps recursion depth at 64 to prevent crashes from corrupt.bkdfiles (6811f49fe)BlockPostingsEnumnow validatesskipCount,docNumBits,freqNumBits, andtailCountbefore consuming them, preventing crashes from corrupt.posfiles (5b891d42b)- Validate position/payload VarInt reads, payload length advances, and payload span bounds against file length in PostingsEnum to prevent access violations from corrupt postings data (ee12b524d)
- Verify
FstBuildernode content equality on hash hit to prevent silent suffix corruption from 64-bit FNV-1a collisions (25ba8d2fb) HnswReadernow validates header and per-node counts againstnodeCountto prevent OOM/corrupt reads from malformed.hnswfiles (f86b7c37f)FstReaderarc decoder now validates buffer bounds on corrupt FST data, andCount()correctly excludes soft-deleted documents (34e903cd0)MergeThrottleSegmentsnow blocksAddDocumentuntil a background merge completes rather than performing a pointless extra flush (1b7a7b3a8)- Range and Int64 range queries no longer allocate a
HashSet<string>per document when falling back to stored fields (234ab977) CombinedFieldsQuery.FieldWeightsno longer allocates a new dictionary on every access (944b03f4)- Prefix, wildcard, fuzzy, range, regex, and automaton term dictionary lookups no longer allocate UTF-8 byte arrays per call (d5f77b6f)
- Duplicate Meter instances with name
Rowles.LeanCorpusthat could cause telemetry listener collisions (4f23137a) IndexOpenGuardno longer silently skips segments whose codec files cannot be read; IO exceptions and data-corruption errors now propagate so that corrupt or unreadable segment files are detected rather than bypassed as if they were unsupported versions (485fe74a)- HNSW
QuantisedVectorWriterno longer quantises every vector twice; packed bytes (Int8) and bit-packed data (BBQ) are stored during the first quantisation pass and written directly in the second, eliminating the duplicate computation pass (3a0a5ec7)- HNSW graph construction for BBQ-quantised vectors now uses Hamming distance (via PopCount on raw bit-packed data) for stored-vs-stored comparisons, matching the query-time distance metric and eliminating the recall degradation caused by optimising the graph for dot-product on dequantised vectors (c1e9344d)
- HNSW graph construction and search no longer repeatedly dequantises the same stored vectors (c9aeb7ae)
SelectNeighboursHeuristicnow caches dequantised vectors per call, eliminating the inner-loopO(m * k)allocations for quantised formats (BBQ, Int8) (c9aeb7ae)
NumericDocValuesReaderandSortedNumericDocValuesReadernow rejectbitsPerValue > 64and validate packed-bytes length, preventing out-of-bounds reads on malformed doc-value files (7f7525b2)TermVectorHighlighternow validates the full phrase window instead of only checking immediate neighbours, so phrase highlighting no longer triggers on terms that are adjacent but in the wrong order or from different phrases (087e58d6)- Merged segments now inherit the active commit generation instead of being hard-coded to 0, so retention, backup, and migration tooling sees correct metadata (bda24522)
- SegmentMerger.MergeVectors now uses the configured HnswBuildConfig instead of defaults when rebuilding vector graphs during merge (2737b7e9)
- ReverseStringFilter now uses
ArrayPool<char>for tokens longer than 128 characters instead of unbounded stackalloc, preventing stack overflow on pathologically long tokens (14b5406c) - IndexBackup.Restore now verifies restored files against manifest CRC-32 checksums after copy, catching hardware errors during restore (98ded332)
- IndexOutputBuffer.Advance(0) no longer discards unflushed buffered bytes by resetting the write position (b03f761b)
- AddIndexes now correctly reads source segment files from the foreign directory instead of the target, fixing cross-directory index import (c24efd41)
- BlockMaxWandScorer
- now uses per-document norms in block skip entries for tighter upper bounds; deleted documents are correctly excluded from WAND results (52a553c5)
- now uses LM scoring with proper block-max upper bounds and is wired into the disjunctive query path behind EnableBlockMaxWand (6a3aa769)
- now scores with proper BM25 and block-max bounds; stateful filters reset between documents and clone correctly for concurrent use (42862187)
- Analyser.Clone() now deep-clones every filter so LanguageAnalyser is safe for concurrent use; stateful filters reset in Finish() and return fresh instances from Clone() (42862187)
- Stateful analysis filters (SynonymGraphFilter, ShingleFilter, LimitTokenCountFilter, CachingTokenFilter) now reset their state between documents, preventing token leakage across multi-document pipelines (94fec8cf)
- PackDelta now validates monotonic non-negative input, catching corrupt postings data before it gets packed (345854c4)
- Phrase and SpanNear queries now score as a sum of all term weights rather than using only the rarest term (fed34fc8)
StemTokenFilterno longer skips stemming based on an English-centric suffix-letter pre-filter, fixing incomplete stems for non-English languages (ee28d923)WordDelimiterFilterandUniqueTokenFilterare now fully implemented and tested (10fac633)JsonDocumentMapper/JsonMappingOptionsfixes (3dfb10a1)- Depth overflow now throws instead of silently dropping data
JsonMappingOptionsvalidatesMaxDepthandStringFieldMaxLength- JSON strings now default to
StringField
ForceMergenow cleans up segment files for merged segments, matching the behaviour of Compact and preventing unbounded disk growth (643a349f)Compact,ForceMerge, and background merges now refuse to run while a two-phase prepared commit is pending, preventing commit-generation collisions that would throwIOExceptionon publish (ebadf8d1)AddDocumentsConcurrentnow flushes segments underWriteLockso concurrent deletes and commits cannot interleave between segment creation and visibility (90e7a528)ExecuteFilterToBitmapno longer mutates the sharedSegmentReader.DocBase. Now subtracts the captured base from collected global IDs, eliminating a data race on concurrent vector-filter searches (b4488e0e)NumericAggregatorno longer probes only docId 0 to resolve field type; now checks field existence across all three numeric stores, fixing silent zero results when the field was absent from the first document (ef8c9033)- Boolean index scoring fallback no longer inflates legitimate zero scores to 1.0f (ffd46248)
MoreLikeThisnow excludes the source document. (6974ebda)- Properly wired
IndexOfNormalisableDigit/NormaliseDigithelpers intoApply. Add several tests. UpdatedAnalysisSmokeTeststo assert actual normalised values rather than just token count. (1cd3010b, c0f1192d) Compact(),WriteNorms(),PushDepth, andCodecFormatvalidation bugs caught by codec audit.- Double-byte-copy in
AddBinaryDocValue: the string overload encoded to UTF-8 then called the span overload which calledToArray()a second time. Both paths now route through a shared core method, allocating once. - AOT smoke test script now auto-detects the OS when selecting the runtime identifier.
- Highlighter and similarity benchmark comparisons against Lucene.NET corrected.
- Every
awaitin the library now includesConfigureAwait(false), preventing continuations from capturing the caller'sSynchronizationContext. GetVector(int docId)inSegmentReader.DocValuesnow iterates all vector fields instead of returning on the first iteration, fixing a bug where only one field was ever checked.NumericDocValuesbit-packing range calculation uses signed subtraction to keep the compiler happy on unsigned underflow in unchecked arithmetic.IndexOutputBuffernow implementsIDisposable; callers useusingblocks to return rented arrays to the pool.posix_fadviseP/Invoke accepts aSafeFileHandledirectly instead of unsafely extracting the raw fd.BackpressureController.AcquireBackpressureSlotAsyncusesWaitAsyncinstead of a blockingWait(0)on the async path.IndexBackupretry loops converted fromfor(;;)towhile(true)so the stop condition and incrementer stay close to the exit check.- AOT example file-scoped types moved into a named namespace.
- Floating-point equality on
RamBufferSizeMBand scoring boosts replaced with range comparisons. - Generic null checks across CodecKit (
CaseDefinition,ChoiceCodec,OptionalCodec,VersionedCodec,VersionEnvelopeCodec) switched tois nullso the compiler's nullable analysis stays accurate. - Benchmark regex instances include a timeout, silencing ReDoS hotspot noise.
Removed
- Dead second deletion pass in
CommitCorethat flushed and re-checked an already-cleared pending-deletes list (d6bfc72da) - CodecFormats.StoredFields static field — the stored-fields format no longer uses the CodecKit envelope and writes headers directly through StoredFieldsFileHeader (b69a4c0f)
- Dead
NumericFieldsbuffer (List<Dictionary<string, double>>) fromDocumentBufferStateandIndexWriter.FieldProcessing; it allocated an empty dictionary for every document containing a numeric field but was never read, while the actual numeric index lives inNumericIndex(614846ad)