github.com/apache/arrow/go/v14@v14.0.2/parquet/internal/utils/rle.go (about) 1 // Licensed to the Apache Software Foundation (ASF) under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 // Package utils contains various internal utilities for the parquet library 18 // that aren't intended to be exposed to external consumers such as interfaces 19 // and bitmap readers/writers including the RLE encoder/decoder and so on. 20 package utils 21 22 import ( 23 "bytes" 24 "encoding/binary" 25 "math" 26 27 "github.com/apache/arrow/go/v14/arrow/bitutil" 28 "github.com/apache/arrow/go/v14/internal/bitutils" 29 "github.com/apache/arrow/go/v14/internal/utils" 30 "github.com/apache/arrow/go/v14/parquet" 31 "golang.org/x/xerrors" 32 ) 33 34 //go:generate go run ../../../arrow/_tools/tmpl/main.go -i -data=physical_types.tmpldata typed_rle_dict.gen.go.tmpl 35 36 const ( 37 MaxValuesPerLiteralRun = (1 << 6) * 8 38 ) 39 40 func MinBufferSize(bitWidth int) int { 41 maxLiteralRunSize := 1 + bitutil.BytesForBits(int64(MaxValuesPerLiteralRun*bitWidth)) 42 maxRepeatedRunSize := binary.MaxVarintLen32 + bitutil.BytesForBits(int64(bitWidth)) 43 return int(utils.Max(maxLiteralRunSize, maxRepeatedRunSize)) 44 } 45 46 func MaxBufferSize(width, numValues int) int { 47 bytesPerRun := width 48 numRuns := int(bitutil.BytesForBits(int64(numValues))) 49 literalMaxSize := numRuns + (numRuns * bytesPerRun) 50 51 minRepeatedRunSize := 1 + int(bitutil.BytesForBits(int64(width))) 52 repeatedMaxSize := int(bitutil.BytesForBits(int64(numValues))) * minRepeatedRunSize 53 54 return utils.MaxInt(literalMaxSize, repeatedMaxSize) 55 } 56 57 // Utility classes to do run length encoding (RLE) for fixed bit width values. If runs 58 // are sufficiently long, RLE is used, otherwise, the values are just bit-packed 59 // (literal encoding). 60 // For both types of runs, there is a byte-aligned indicator which encodes the length 61 // of the run and the type of the run. 62 // This encoding has the benefit that when there aren't any long enough runs, values 63 // are always decoded at fixed (can be precomputed) bit offsets OR both the value and 64 // the run length are byte aligned. This allows for very efficient decoding 65 // implementations. 66 // The encoding is: 67 // encoded-block := run* 68 // run := literal-run | repeated-run 69 // literal-run := literal-indicator < literal bytes > 70 // repeated-run := repeated-indicator < repeated value. padded to byte boundary > 71 // literal-indicator := varint_encode( number_of_groups << 1 | 1) 72 // repeated-indicator := varint_encode( number_of_repetitions << 1 ) 73 // 74 // Each run is preceded by a varint. The varint's least significant bit is 75 // used to indicate whether the run is a literal run or a repeated run. The rest 76 // of the varint is used to determine the length of the run (eg how many times the 77 // value repeats). 78 // 79 // In the case of literal runs, the run length is always a multiple of 8 (i.e. encode 80 // in groups of 8), so that no matter the bit-width of the value, the sequence will end 81 // on a byte boundary without padding. 82 // Given that we know it is a multiple of 8, we store the number of 8-groups rather than 83 // the actual number of encoded ints. (This means that the total number of encoded values 84 // can not be determined from the encoded data, since the number of values in the last 85 // group may not be a multiple of 8). For the last group of literal runs, we pad 86 // the group to 8 with zeros. This allows for 8 at a time decoding on the read side 87 // without the need for additional checks. 88 // 89 // There is a break-even point when it is more storage efficient to do run length 90 // encoding. For 1 bit-width values, that point is 8 values. They require 2 bytes 91 // for both the repeated encoding or the literal encoding. This value can always 92 // be computed based on the bit-width. 93 // 94 // Examples with bit-width 1 (eg encoding booleans): 95 // ---------------------------------------- 96 // 100 1s followed by 100 0s: 97 // <varint(100 << 1)> <1, padded to 1 byte> <varint(100 << 1)> <0, padded to 1 byte> 98 // - (total 4 bytes) 99 // 100 // alternating 1s and 0s (200 total): 101 // 200 ints = 25 groups of 8 102 // <varint((25 << 1) | 1)> <25 bytes of values, bitpacked> 103 // (total 26 bytes, 1 byte overhead) 104 // 105 106 type RleDecoder struct { 107 r *BitReader 108 109 bitWidth int 110 curVal uint64 111 repCount int32 112 litCount int32 113 } 114 115 func NewRleDecoder(data *bytes.Reader, width int) *RleDecoder { 116 return &RleDecoder{r: NewBitReader(data), bitWidth: width} 117 } 118 119 func (r *RleDecoder) Reset(data *bytes.Reader, width int) { 120 r.bitWidth = width 121 r.curVal = 0 122 r.repCount = 0 123 r.litCount = 0 124 r.r.Reset(data) 125 } 126 127 func (r *RleDecoder) Next() bool { 128 indicator, ok := r.r.GetVlqInt() 129 if !ok { 130 return false 131 } 132 133 literal := (indicator & 1) != 0 134 count := uint32(indicator >> 1) 135 if literal { 136 if count == 0 || count > uint32(math.MaxInt32/8) { 137 return false 138 } 139 r.litCount = int32(count) * 8 140 } else { 141 if count == 0 || count > uint32(math.MaxInt32) { 142 return false 143 } 144 r.repCount = int32(count) 145 146 nbytes := int(bitutil.BytesForBits(int64(r.bitWidth))) 147 switch { 148 case nbytes > 4: 149 if !r.r.GetAligned(nbytes, &r.curVal) { 150 return false 151 } 152 case nbytes > 2: 153 var val uint32 154 if !r.r.GetAligned(nbytes, &val) { 155 return false 156 } 157 r.curVal = uint64(val) 158 case nbytes > 1: 159 var val uint16 160 if !r.r.GetAligned(nbytes, &val) { 161 return false 162 } 163 r.curVal = uint64(val) 164 default: 165 var val uint8 166 if !r.r.GetAligned(nbytes, &val) { 167 return false 168 } 169 r.curVal = uint64(val) 170 } 171 } 172 return true 173 } 174 175 func (r *RleDecoder) GetValue() (uint64, bool) { 176 vals := make([]uint64, 1) 177 n := r.GetBatch(vals) 178 return vals[0], n == 1 179 } 180 181 func (r *RleDecoder) GetBatch(values []uint64) int { 182 read := 0 183 size := len(values) 184 185 out := values 186 for read < size { 187 remain := size - read 188 189 if r.repCount > 0 { 190 repbatch := int(math.Min(float64(remain), float64(r.repCount))) 191 for i := 0; i < repbatch; i++ { 192 out[i] = r.curVal 193 } 194 195 r.repCount -= int32(repbatch) 196 read += repbatch 197 out = out[repbatch:] 198 } else if r.litCount > 0 { 199 litbatch := int(math.Min(float64(remain), float64(r.litCount))) 200 n, _ := r.r.GetBatch(uint(r.bitWidth), out[:litbatch]) 201 if n != litbatch { 202 return read 203 } 204 205 r.litCount -= int32(litbatch) 206 read += litbatch 207 out = out[litbatch:] 208 } else { 209 if !r.Next() { 210 return read 211 } 212 } 213 } 214 return read 215 } 216 217 func (r *RleDecoder) GetBatchSpaced(vals []uint64, nullcount int, validBits []byte, validBitsOffset int64) (int, error) { 218 if nullcount == 0 { 219 return r.GetBatch(vals), nil 220 } 221 222 converter := plainConverter{} 223 blockCounter := bitutils.NewBitBlockCounter(validBits, validBitsOffset, int64(len(vals))) 224 225 var ( 226 totalProcessed int 227 processed int 228 block bitutils.BitBlockCount 229 err error 230 ) 231 232 for { 233 block = blockCounter.NextFourWords() 234 if block.Len == 0 { 235 break 236 } 237 238 if block.AllSet() { 239 processed = r.GetBatch(vals[:block.Len]) 240 } else if block.NoneSet() { 241 converter.FillZero(vals[:block.Len]) 242 processed = int(block.Len) 243 } else { 244 processed, err = r.getspaced(converter, vals, int(block.Len), int(block.Len-block.Popcnt), validBits, validBitsOffset) 245 if err != nil { 246 return totalProcessed, err 247 } 248 } 249 250 totalProcessed += processed 251 vals = vals[int(block.Len):] 252 validBitsOffset += int64(block.Len) 253 254 if processed != int(block.Len) { 255 break 256 } 257 } 258 return totalProcessed, nil 259 } 260 261 func (r *RleDecoder) getspaced(dc DictionaryConverter, vals interface{}, batchSize, nullCount int, validBits []byte, validBitsOffset int64) (int, error) { 262 switch vals := vals.(type) { 263 case []int32: 264 return r.getspacedInt32(dc, vals, batchSize, nullCount, validBits, validBitsOffset) 265 case []int64: 266 return r.getspacedInt64(dc, vals, batchSize, nullCount, validBits, validBitsOffset) 267 case []float32: 268 return r.getspacedFloat32(dc, vals, batchSize, nullCount, validBits, validBitsOffset) 269 case []float64: 270 return r.getspacedFloat64(dc, vals, batchSize, nullCount, validBits, validBitsOffset) 271 case []parquet.ByteArray: 272 return r.getspacedByteArray(dc, vals, batchSize, nullCount, validBits, validBitsOffset) 273 case []parquet.FixedLenByteArray: 274 return r.getspacedFixedLenByteArray(dc, vals, batchSize, nullCount, validBits, validBitsOffset) 275 case []parquet.Int96: 276 return r.getspacedInt96(dc, vals, batchSize, nullCount, validBits, validBitsOffset) 277 case []uint64: 278 return r.getspacedUint64(dc, vals, batchSize, nullCount, validBits, validBitsOffset) 279 default: 280 return 0, xerrors.New("parquet/rle: getspaced invalid type") 281 } 282 } 283 284 func (r *RleDecoder) getspacedUint64(dc DictionaryConverter, vals []uint64, batchSize, nullCount int, validBits []byte, validBitsOffset int64) (int, error) { 285 if nullCount == batchSize { 286 dc.FillZero(vals[:batchSize]) 287 return batchSize, nil 288 } 289 290 read := 0 291 remain := batchSize - nullCount 292 293 const bufferSize = 1024 294 var indexbuffer [bufferSize]IndexType 295 296 // assume no bits to start 297 bitReader := bitutils.NewBitRunReader(validBits, validBitsOffset, int64(batchSize)) 298 validRun := bitReader.NextRun() 299 for read < batchSize { 300 if validRun.Len == 0 { 301 validRun = bitReader.NextRun() 302 } 303 304 if !validRun.Set { 305 dc.FillZero(vals[:int(validRun.Len)]) 306 vals = vals[int(validRun.Len):] 307 read += int(validRun.Len) 308 validRun.Len = 0 309 continue 310 } 311 312 if r.repCount == 0 && r.litCount == 0 { 313 if !r.Next() { 314 return read, nil 315 } 316 } 317 318 var batch int 319 switch { 320 case r.repCount > 0: 321 batch, remain, validRun = r.consumeRepeatCounts(read, batchSize, remain, validRun, bitReader) 322 current := IndexType(r.curVal) 323 if !dc.IsValid(current) { 324 return read, nil 325 } 326 dc.Fill(vals[:batch], current) 327 case r.litCount > 0: 328 var ( 329 litread int 330 skipped int 331 err error 332 ) 333 litread, skipped, validRun, err = r.consumeLiteralsUint64(dc, vals, remain, indexbuffer[:], validRun, bitReader) 334 if err != nil { 335 return read, err 336 } 337 batch = litread + skipped 338 remain -= litread 339 } 340 341 vals = vals[batch:] 342 read += batch 343 } 344 return read, nil 345 } 346 347 func (r *RleDecoder) consumeRepeatCounts(read, batchSize, remain int, run bitutils.BitRun, bitRdr bitutils.BitRunReader) (int, int, bitutils.BitRun) { 348 // Consume the entire repeat counts incrementing repeat_batch to 349 // be the total of nulls + values consumed, we only need to 350 // get the total count because we can fill in the same value for 351 // nulls and non-nulls. This proves to be a big efficiency win. 352 repeatBatch := 0 353 for r.repCount > 0 && (read+repeatBatch) < batchSize { 354 if run.Set { 355 updateSize := int(utils.Min(run.Len, int64(r.repCount))) 356 r.repCount -= int32(updateSize) 357 repeatBatch += updateSize 358 run.Len -= int64(updateSize) 359 remain -= updateSize 360 } else { 361 repeatBatch += int(run.Len) 362 run.Len = 0 363 } 364 365 if run.Len == 0 { 366 run = bitRdr.NextRun() 367 } 368 } 369 return repeatBatch, remain, run 370 } 371 372 func (r *RleDecoder) consumeLiteralsUint64(dc DictionaryConverter, vals []uint64, remain int, buf []IndexType, run bitutils.BitRun, bitRdr bitutils.BitRunReader) (int, int, bitutils.BitRun, error) { 373 batch := utils.MinInt(utils.MinInt(remain, int(r.litCount)), len(buf)) 374 buf = buf[:batch] 375 376 n, _ := r.r.GetBatchIndex(uint(r.bitWidth), buf) 377 if n != batch { 378 return 0, 0, run, xerrors.New("was not able to retrieve correct number of indexes") 379 } 380 381 if !dc.IsValid(buf...) { 382 return 0, 0, run, xerrors.New("invalid index values found for dictionary converter") 383 } 384 385 var ( 386 read int 387 skipped int 388 ) 389 for read < batch { 390 if run.Set { 391 updateSize := utils.MinInt(batch-read, int(run.Len)) 392 if err := dc.Copy(vals, buf[read:read+updateSize]); err != nil { 393 return 0, 0, run, err 394 } 395 read += updateSize 396 vals = vals[updateSize:] 397 run.Len -= int64(updateSize) 398 } else { 399 dc.FillZero(vals[:int(run.Len)]) 400 vals = vals[int(run.Len):] 401 skipped += int(run.Len) 402 run.Len = 0 403 } 404 if run.Len == 0 { 405 run = bitRdr.NextRun() 406 } 407 } 408 r.litCount -= int32(batch) 409 return read, skipped, run, nil 410 } 411 412 func (r *RleDecoder) GetBatchWithDict(dc DictionaryConverter, vals interface{}) (int, error) { 413 switch vals := vals.(type) { 414 case []int32: 415 return r.GetBatchWithDictInt32(dc, vals) 416 case []int64: 417 return r.GetBatchWithDictInt64(dc, vals) 418 case []float32: 419 return r.GetBatchWithDictFloat32(dc, vals) 420 case []float64: 421 return r.GetBatchWithDictFloat64(dc, vals) 422 case []parquet.ByteArray: 423 return r.GetBatchWithDictByteArray(dc, vals) 424 case []parquet.FixedLenByteArray: 425 return r.GetBatchWithDictFixedLenByteArray(dc, vals) 426 case []parquet.Int96: 427 return r.GetBatchWithDictInt96(dc, vals) 428 default: 429 return 0, xerrors.New("parquet/rle: GetBatchWithDict invalid type") 430 } 431 } 432 433 func (r *RleDecoder) GetBatchWithDictSpaced(dc DictionaryConverter, vals interface{}, nullCount int, validBits []byte, validBitsOffset int64) (int, error) { 434 switch vals := vals.(type) { 435 case []int32: 436 return r.GetBatchWithDictSpacedInt32(dc, vals, nullCount, validBits, validBitsOffset) 437 case []int64: 438 return r.GetBatchWithDictSpacedInt64(dc, vals, nullCount, validBits, validBitsOffset) 439 case []float32: 440 return r.GetBatchWithDictSpacedFloat32(dc, vals, nullCount, validBits, validBitsOffset) 441 case []float64: 442 return r.GetBatchWithDictSpacedFloat64(dc, vals, nullCount, validBits, validBitsOffset) 443 case []parquet.ByteArray: 444 return r.GetBatchWithDictSpacedByteArray(dc, vals, nullCount, validBits, validBitsOffset) 445 case []parquet.FixedLenByteArray: 446 return r.GetBatchWithDictSpacedFixedLenByteArray(dc, vals, nullCount, validBits, validBitsOffset) 447 case []parquet.Int96: 448 return r.GetBatchWithDictSpacedInt96(dc, vals, nullCount, validBits, validBitsOffset) 449 default: 450 return 0, xerrors.New("parquet/rle: GetBatchWithDictSpaced invalid type") 451 } 452 } 453 454 type RleEncoder struct { 455 w *BitWriter 456 457 buffer []uint64 458 BitWidth int 459 curVal uint64 460 repCount int32 461 litCount int32 462 literalIndicatorOffset int 463 464 indicatorBuffer [1]byte 465 } 466 467 func NewRleEncoder(w WriterAtWithLen, width int) *RleEncoder { 468 return &RleEncoder{ 469 w: NewBitWriter(w), 470 buffer: make([]uint64, 0, 8), 471 BitWidth: width, 472 literalIndicatorOffset: -1, 473 } 474 } 475 476 func (r *RleEncoder) Flush() int { 477 if r.litCount > 0 || r.repCount > 0 || len(r.buffer) > 0 { 478 allRep := r.litCount == 0 && (r.repCount == int32(len(r.buffer)) || len(r.buffer) == 0) 479 if r.repCount > 0 && allRep { 480 r.flushRepeated() 481 } else { 482 // buffer the last grou pof literals to 8 by padding with 0s 483 for len(r.buffer) != 0 && len(r.buffer) < 8 { 484 r.buffer = append(r.buffer, 0) 485 } 486 487 r.litCount += int32(len(r.buffer)) 488 r.flushLiteral(true) 489 r.repCount = 0 490 } 491 } 492 r.w.Flush(false) 493 return r.w.Written() 494 } 495 496 func (r *RleEncoder) flushBuffered(done bool) (err error) { 497 if r.repCount >= 8 { 498 // clear buffered values. they are part of the repeated run now and we 499 // don't want to flush them as literals 500 r.buffer = r.buffer[:0] 501 if r.litCount != 0 { 502 // there was current literal run. all values flushed but need to update the indicator 503 err = r.flushLiteral(true) 504 } 505 return 506 } 507 508 r.litCount += int32(len(r.buffer)) 509 ngroups := r.litCount / 8 510 if ngroups+1 >= (1 << 6) { 511 // we need to start a new literal run because the indicator byte we've reserved 512 // cannot store any more values 513 err = r.flushLiteral(true) 514 } else { 515 err = r.flushLiteral(done) 516 } 517 r.repCount = 0 518 return 519 } 520 521 func (r *RleEncoder) flushLiteral(updateIndicator bool) (err error) { 522 if r.literalIndicatorOffset == -1 { 523 r.literalIndicatorOffset, err = r.w.SkipBytes(1) 524 if err != nil { 525 return 526 } 527 } 528 529 for _, val := range r.buffer { 530 if err = r.w.WriteValue(val, uint(r.BitWidth)); err != nil { 531 return 532 } 533 } 534 r.buffer = r.buffer[:0] 535 536 if updateIndicator { 537 // at this point we need to write the indicator byte for the literal run. 538 // we only reserve one byte, to allow for streaming writes of literal values. 539 // the logic makes sure we flush literal runs often enough to not overrun the 1 byte. 540 ngroups := r.litCount / 8 541 r.indicatorBuffer[0] = byte((ngroups << 1) | 1) 542 _, err = r.w.WriteAt(r.indicatorBuffer[:], int64(r.literalIndicatorOffset)) 543 r.literalIndicatorOffset = -1 544 r.litCount = 0 545 } 546 return 547 } 548 549 func (r *RleEncoder) flushRepeated() (ret bool) { 550 indicator := r.repCount << 1 551 552 ret = r.w.WriteVlqInt(uint64(indicator)) 553 ret = ret && r.w.WriteAligned(r.curVal, int(bitutil.BytesForBits(int64(r.BitWidth)))) 554 555 r.repCount = 0 556 r.buffer = r.buffer[:0] 557 return 558 } 559 560 // Put buffers input values 8 at a time. after seeing all 8 values, 561 // it decides whether they should be encoded as a literal or repeated run. 562 func (r *RleEncoder) Put(value uint64) error { 563 if r.curVal == value { 564 r.repCount++ 565 if r.repCount > 8 { 566 // this is just a continuation of the current run, no need to buffer the values 567 // NOTE this is the fast path for long repeated runs 568 return nil 569 } 570 } else { 571 if r.repCount >= 8 { 572 if !r.flushRepeated() { 573 return xerrors.New("failed to flush repeated value") 574 } 575 } 576 r.repCount = 1 577 r.curVal = value 578 } 579 580 r.buffer = append(r.buffer, value) 581 if len(r.buffer) == 8 { 582 return r.flushBuffered(false) 583 } 584 return nil 585 } 586 587 func (r *RleEncoder) Clear() { 588 r.curVal = 0 589 r.repCount = 0 590 r.buffer = r.buffer[:0] 591 r.litCount = 0 592 r.literalIndicatorOffset = -1 593 r.w.Clear() 594 }