@@ -1298,12 +1298,7 @@ public static Status.LiveDocStatus testLiveDocs(
1298
1298
if (liveDocs == null ) {
1299
1299
throw new CheckIndexException ("segment should have deletions, but liveDocs is null" );
1300
1300
} else {
1301
- int numLive = 0 ;
1302
- for (int j = 0 ; j < liveDocs .length (); j ++) {
1303
- if (liveDocs .get (j )) {
1304
- numLive ++;
1305
- }
1306
- }
1301
+ int numLive = bitsCardinality (liveDocs );
1307
1302
if (numLive != numDocs ) {
1308
1303
throw new CheckIndexException (
1309
1304
"liveDocs count mismatch: info=" + numDocs + ", vs bits=" + numLive );
@@ -1349,6 +1344,28 @@ public static Status.LiveDocStatus testLiveDocs(
1349
1344
return status ;
1350
1345
}
1351
1346
1347
+ /**
1348
+ * Returns the cardinality of the given {@code Bits}.
1349
+ *
1350
+ * <p>This method processes bits in batches of 1024 using {@link Bits#applyMask} and {@link
1351
+ * FixedBitSet#cardinality}, which is faster than checking bits one by one.
1352
+ */
1353
+ static int bitsCardinality (Bits bits ) {
1354
+ int cardinality = 0 ;
1355
+ FixedBitSet copy = new FixedBitSet (1024 );
1356
+ for (int offset = 0 ; offset < bits .length (); offset += copy .length ()) {
1357
+ int numBitsToCopy = Math .min (bits .length () - offset , copy .length ());
1358
+ copy .set (0 , copy .length ());
1359
+ if (numBitsToCopy < copy .length ()) {
1360
+ // Clear ghost bits
1361
+ copy .clear (numBitsToCopy , copy .length ());
1362
+ }
1363
+ bits .applyMask (copy , offset );
1364
+ cardinality += copy .cardinality ();
1365
+ }
1366
+ return cardinality ;
1367
+ }
1368
+
1352
1369
/** Test field infos. */
1353
1370
public static Status .FieldInfoStatus testFieldInfos (
1354
1371
CodecReader reader , PrintStream infoStream , boolean failFast ) throws IOException {
0 commit comments