32
32
import org .apache .lucene .search .ReferenceManager ;
33
33
import org .apache .lucene .search .similarities .Similarity ;
34
34
import org .apache .lucene .store .AlreadyClosedException ;
35
+ import org .apache .lucene .util .Bits ;
35
36
import org .apache .lucene .util .BytesRef ;
37
+ import org .apache .lucene .util .RamUsageEstimator ;
36
38
import org .apache .lucene .util .SetOnce ;
37
39
import org .elasticsearch .ExceptionsHelper ;
38
40
import org .elasticsearch .action .ActionListener ;
@@ -280,6 +282,7 @@ protected static ShardFieldStats shardFieldStats(List<LeafReaderContext> leaves)
280
282
int totalFields = 0 ;
281
283
long usages = 0 ;
282
284
long totalPostingBytes = 0 ;
285
+ long liveDocsBytes = 0 ;
283
286
for (LeafReaderContext leaf : leaves ) {
284
287
numSegments ++;
285
288
var fieldInfos = leaf .reader ().getFieldInfos ();
@@ -291,19 +294,44 @@ protected static ShardFieldStats shardFieldStats(List<LeafReaderContext> leaves)
291
294
} else {
292
295
usages = -1 ;
293
296
}
294
- if (TrackingPostingsInMemoryBytesCodec .TRACK_POSTINGS_IN_MEMORY_BYTES .isEnabled ()) {
297
+ boolean trackPostingsMemoryEnabled = TrackingPostingsInMemoryBytesCodec .TRACK_POSTINGS_IN_MEMORY_BYTES .isEnabled ();
298
+ boolean trackLiveDocsMemoryEnabled = ShardFieldStats .TRACK_LIVE_DOCS_IN_MEMORY_BYTES .isEnabled ();
299
+ if (trackLiveDocsMemoryEnabled || trackPostingsMemoryEnabled ) {
295
300
SegmentReader segmentReader = Lucene .tryUnwrapSegmentReader (leaf .reader ());
296
301
if (segmentReader != null ) {
297
- String postingBytes = segmentReader .getSegmentInfo ().info .getAttribute (
298
- TrackingPostingsInMemoryBytesCodec .IN_MEMORY_POSTINGS_BYTES_KEY
299
- );
300
- if (postingBytes != null ) {
301
- totalPostingBytes += Long .parseLong (postingBytes );
302
+ if (trackPostingsMemoryEnabled ) {
303
+ String postingBytes = segmentReader .getSegmentInfo ().info .getAttribute (
304
+ TrackingPostingsInMemoryBytesCodec .IN_MEMORY_POSTINGS_BYTES_KEY
305
+ );
306
+ if (postingBytes != null ) {
307
+ totalPostingBytes += Long .parseLong (postingBytes );
308
+ }
309
+ }
310
+ if (trackLiveDocsMemoryEnabled ) {
311
+ var liveDocs = segmentReader .getLiveDocs ();
312
+ if (liveDocs != null ) {
313
+ assert validateLiveDocsClass (liveDocs );
314
+ // Would prefer to use FixedBitSet#ramBytesUsed() however FixedBits / Bits interface don't expose that.
315
+ // This almost does what FixedBitSet#ramBytesUsed() does, liveDocs.length() returns the length of the bits long
316
+ // array
317
+ liveDocsBytes += RamUsageEstimator .alignObjectSize (
318
+ (long ) RamUsageEstimator .NUM_BYTES_ARRAY_HEADER + (liveDocs .length () / 8L )
319
+ );
320
+ }
302
321
}
303
322
}
304
323
}
305
324
}
306
- return new ShardFieldStats (numSegments , totalFields , usages , totalPostingBytes );
325
+ return new ShardFieldStats (numSegments , totalFields , usages , totalPostingBytes , liveDocsBytes );
326
+ }
327
+
328
+ private static boolean validateLiveDocsClass (Bits liveDocs ) {
329
+ // These classes are package protected in Lucene and therefor we compare fully qualified classnames as strings here:
330
+ String fullClassName = liveDocs .getClass ().getName ();
331
+ assert fullClassName .equals ("org.apache.lucene.util.FixedBits" )
332
+ || fullClassName .equals ("org.apache.lucene.tests.codecs.asserting.AssertingLiveDocsFormat$AssertingBits" )
333
+ : "unexpected class [" + fullClassName + "]" ;
334
+ return true ;
307
335
}
308
336
309
337
/**
0 commit comments