@@ -141,51 +141,53 @@ public AtomicNumericFieldData loadDirect(AtomicReaderContext context) throws Exc
141
141
maxValue = values .get (values .size () - 1 );
142
142
}
143
143
144
- // Encode document without a value with a special value
145
- long missingValue = 0 ;
146
- if (docsWithValues != null ) {
147
- if ((maxValue - minValue + 1 ) == values .size ()) {
148
- // values are dense
149
- if (minValue > Long .MIN_VALUE ) {
150
- missingValue = --minValue ;
151
- } else {
152
- assert maxValue != Long .MAX_VALUE ;
153
- missingValue = ++maxValue ;
154
- }
155
- } else {
156
- for (long i = 1 ; i < values .size (); ++i ) {
157
- if (values .get (i ) > values .get (i - 1 ) + 1 ) {
158
- missingValue = values .get (i - 1 ) + 1 ;
159
- break ;
160
- }
161
- }
162
- }
163
- }
164
144
165
- final long valuesDelta = maxValue - minValue ;
166
145
final float acceptableOverheadRatio = fieldDataType .getSettings ().getAsFloat ("acceptable_overhead_ratio" , PackedInts .DEFAULT );
167
146
final int pageSize = fieldDataType .getSettings ().getAsInt ("single_value_page_size" , 1024 );
168
147
169
148
if (formatHint == null ) {
170
- formatHint = chooseStorageFormat (reader , values , build , ordinals , missingValue , valuesDelta , acceptableOverheadRatio , pageSize );
149
+ formatHint = chooseStorageFormat (reader , values , build , ordinals , minValue , maxValue , acceptableOverheadRatio , pageSize );
171
150
}
172
151
173
152
logger .trace ("single value format for field [{}] set to [{}]" , getFieldNames ().fullName (), formatHint );
174
153
175
154
switch (formatHint ) {
176
155
case PACKED :
177
- int bitsRequired = valuesDelta < 0 ? 64 : PackedInts .bitsRequired (valuesDelta );
156
+ // Encode document without a value with a special value
157
+ long missingValue = 0 ;
158
+ if (docsWithValues != null ) {
159
+ if ((maxValue - minValue + 1 ) == values .size ()) {
160
+ // values are dense
161
+ if (minValue > Long .MIN_VALUE ) {
162
+ missingValue = --minValue ;
163
+ } else {
164
+ assert maxValue != Long .MAX_VALUE ;
165
+ missingValue = ++maxValue ;
166
+ }
167
+ } else {
168
+ for (long i = 1 ; i < values .size (); ++i ) {
169
+ if (values .get (i ) > values .get (i - 1 ) + 1 ) {
170
+ missingValue = values .get (i - 1 ) + 1 ;
171
+ break ;
172
+ }
173
+ }
174
+ }
175
+ missingValue -= minValue ;
176
+ }
178
177
178
+ final long valuesDelta = maxValue - minValue ;
179
+ int bitsRequired = valuesDelta < 0 ? 64 : PackedInts .bitsRequired (valuesDelta );
179
180
final PackedInts .Mutable sValues = PackedInts .getMutable (reader .maxDoc (), bitsRequired , acceptableOverheadRatio );
180
181
181
- if (missingValue != 0 ) {
182
- missingValue -= minValue ;
182
+ if (docsWithValues != null ) {
183
183
sValues .fill (0 , sValues .size (), missingValue );
184
184
}
185
+
185
186
for (int i = 0 ; i < reader .maxDoc (); i ++) {
186
187
final long ord = ordinals .getOrd (i );
187
188
if (ord != Ordinals .MISSING_ORDINAL ) {
188
- sValues .set (i , values .get (ord - 1 ) - minValue );
189
+ long value = values .get (ord - 1 );
190
+ sValues .set (i , value - minValue );
189
191
}
190
192
}
191
193
if (docsWithValues == null ) {
@@ -238,14 +240,18 @@ public AtomicNumericFieldData loadDirect(AtomicReaderContext context) throws Exc
238
240
}
239
241
240
242
protected CommonSettings .MemoryStorageFormat chooseStorageFormat (AtomicReader reader , MonotonicAppendingLongBuffer values , Ordinals build , Docs ordinals ,
241
- long missingValue , long valuesDelta , float acceptableOverheadRatio , int pageSize ) {
242
- CommonSettings .MemoryStorageFormat format ;// estimate format
243
+ long minValue , long maxValue , float acceptableOverheadRatio , int pageSize ) {
244
+
245
+ CommonSettings .MemoryStorageFormat format ;
246
+
247
+ // estimate memory usage for a single packed array
248
+ long packedDelta = maxValue - minValue + 1 ; // allow for a missing value
243
249
// valuesDelta can be negative if the difference between max and min values overflows the positive side of longs.
244
- int bitsRequired = valuesDelta < 0 ? 64 : PackedInts .bitsRequired (valuesDelta );
250
+ int bitsRequired = packedDelta < 0 ? 64 : PackedInts .bitsRequired (packedDelta );
245
251
PackedInts .FormatAndBits formatAndBits = PackedInts .fastestFormatAndBits (reader .maxDoc (), bitsRequired , acceptableOverheadRatio );
246
-
247
- // there's sweet spot where due to low unique value count, using ordinals will consume less memory
248
252
final long singleValuesSize = formatAndBits .format .longCount (PackedInts .VERSION_CURRENT , reader .maxDoc (), formatAndBits .bitsPerValue ) * 8L ;
253
+
254
+ // ordinal memory usage
249
255
final long ordinalsSize = build .getMemorySizeInBytes () + values .ramBytesUsed ();
250
256
251
257
// estimate the memory signature of paged packing
@@ -261,24 +267,7 @@ protected CommonSettings.MemoryStorageFormat chooseStorageFormat(AtomicReader re
261
267
}
262
268
if (pageIndex == pageSize - 1 ) {
263
269
// end of page, we now know enough to estimate memory usage
264
- if (pageMaxOrdinal == Long .MIN_VALUE ) {
265
- // empty page - will use the null reader which just stores size
266
- pagedSingleValuesSize += RamUsageEstimator .alignObjectSize (RamUsageEstimator .NUM_BYTES_OBJECT_HEADER + RamUsageEstimator .NUM_BYTES_INT );
267
-
268
- } else {
269
- long pageMinValue = values .get (pageMinOrdinal - 1 );
270
- long pageMaxValue = values .get (pageMaxOrdinal - 1 );
271
- long pageDelta = pageMaxValue - pageMinValue ;
272
- if (pageDelta != 0 ) {
273
- bitsRequired = valuesDelta < 0 ? 64 : PackedInts .bitsRequired (pageDelta );
274
- formatAndBits = PackedInts .fastestFormatAndBits (pageSize , bitsRequired , acceptableOverheadRatio );
275
- pagedSingleValuesSize += formatAndBits .format .longCount (PackedInts .VERSION_CURRENT , pageSize , formatAndBits .bitsPerValue ) * RamUsageEstimator .NUM_BYTES_LONG ;
276
- pagedSingleValuesSize += RamUsageEstimator .NUM_BYTES_LONG ; // min value per page storage
277
- } else {
278
- // empty page
279
- pagedSingleValuesSize += RamUsageEstimator .alignObjectSize (RamUsageEstimator .NUM_BYTES_OBJECT_HEADER + RamUsageEstimator .NUM_BYTES_INT );
280
- }
281
- }
270
+ pagedSingleValuesSize += getPageMemoryUsage (values , acceptableOverheadRatio , pageSize , pageMinOrdinal , pageMaxOrdinal );
282
271
283
272
pageMinOrdinal = Long .MAX_VALUE ;
284
273
pageMaxOrdinal = Long .MIN_VALUE ;
@@ -288,24 +277,7 @@ protected CommonSettings.MemoryStorageFormat chooseStorageFormat(AtomicReader re
288
277
if (pageIndex > 0 ) {
289
278
// last page estimation
290
279
pageIndex ++;
291
- if (pageMaxOrdinal == Long .MIN_VALUE ) {
292
- // empty page - will use the null reader which just stores size
293
- pagedSingleValuesSize += RamUsageEstimator .alignObjectSize (RamUsageEstimator .NUM_BYTES_OBJECT_HEADER + RamUsageEstimator .NUM_BYTES_INT );
294
-
295
- } else {
296
- long pageMinValue = values .get (pageMinOrdinal - 1 );
297
- long pageMaxValue = values .get (pageMaxOrdinal - 1 );
298
- long pageDelta = pageMaxValue - pageMinValue ;
299
- if (pageDelta != 0 ) {
300
- bitsRequired = valuesDelta < 0 ? 64 : PackedInts .bitsRequired (pageDelta );
301
- formatAndBits = PackedInts .fastestFormatAndBits (pageSize , bitsRequired , acceptableOverheadRatio );
302
- pagedSingleValuesSize += formatAndBits .format .longCount (PackedInts .VERSION_CURRENT , pageSize , formatAndBits .bitsPerValue ) * RamUsageEstimator .NUM_BYTES_LONG ;
303
- pagedSingleValuesSize += RamUsageEstimator .NUM_BYTES_LONG ; // min value per page storage
304
- } else {
305
- // empty page
306
- pagedSingleValuesSize += RamUsageEstimator .alignObjectSize (RamUsageEstimator .NUM_BYTES_OBJECT_HEADER + RamUsageEstimator .NUM_BYTES_INT );
307
- }
308
- }
280
+ pagedSingleValuesSize += getPageMemoryUsage (values , acceptableOverheadRatio , pageSize , pageMinOrdinal , pageMaxOrdinal );
309
281
}
310
282
311
283
if (ordinalsSize < singleValuesSize ) {
@@ -324,6 +296,31 @@ protected CommonSettings.MemoryStorageFormat chooseStorageFormat(AtomicReader re
324
296
return format ;
325
297
}
326
298
299
+ private long getPageMemoryUsage (MonotonicAppendingLongBuffer values , float acceptableOverheadRatio , int pageSize , long pageMinOrdinal , long pageMaxOrdinal ) {
300
+ int bitsRequired ;
301
+ long pageMemorySize = 0 ;
302
+ PackedInts .FormatAndBits formatAndBits ;
303
+ if (pageMaxOrdinal == Long .MIN_VALUE ) {
304
+ // empty page - will use the null reader which just stores size
305
+ pageMemorySize += RamUsageEstimator .alignObjectSize (RamUsageEstimator .NUM_BYTES_OBJECT_HEADER + RamUsageEstimator .NUM_BYTES_INT );
306
+
307
+ } else {
308
+ long pageMinValue = values .get (pageMinOrdinal - 1 );
309
+ long pageMaxValue = values .get (pageMaxOrdinal - 1 );
310
+ long pageDelta = pageMaxValue - pageMinValue ;
311
+ if (pageDelta != 0 ) {
312
+ bitsRequired = pageDelta < 0 ? 64 : PackedInts .bitsRequired (pageDelta );
313
+ formatAndBits = PackedInts .fastestFormatAndBits (pageSize , bitsRequired , acceptableOverheadRatio );
314
+ pageMemorySize += formatAndBits .format .longCount (PackedInts .VERSION_CURRENT , pageSize , formatAndBits .bitsPerValue ) * RamUsageEstimator .NUM_BYTES_LONG ;
315
+ pageMemorySize += RamUsageEstimator .NUM_BYTES_LONG ; // min value per page storage
316
+ } else {
317
+ // empty page
318
+ pageMemorySize += RamUsageEstimator .alignObjectSize (RamUsageEstimator .NUM_BYTES_OBJECT_HEADER + RamUsageEstimator .NUM_BYTES_INT );
319
+ }
320
+ }
321
+ return pageMemorySize ;
322
+ }
323
+
327
324
@ Override
328
325
public XFieldComparatorSource comparatorSource (@ Nullable Object missingValue , SortMode sortMode ) {
329
326
return new LongValuesComparatorSource (this , missingValue , sortMode );
0 commit comments