github.com/vc42/parquet-go@v0.0.0-20240320194221-1a9adb5f23f5/encoding/delta/length_byte_array_amd64.go (about) 1 //go:build !purego 2 3 package delta 4 5 import ( 6 "github.com/vc42/parquet-go/encoding/plain" 7 "golang.org/x/sys/cpu" 8 ) 9 10 //go:noescape 11 func validateLengthValuesAVX2(lengths []int32) (totalLength int, ok bool) 12 13 func validateLengthValues(lengths []int32, maxLength int) (totalLength int, err error) { 14 if cpu.X86.HasAVX2 { 15 totalLength, ok := validateLengthValuesAVX2(lengths) 16 if ok { 17 return totalLength, nil 18 } 19 } 20 21 for i := range lengths { 22 n := int(lengths[i]) 23 if n < 0 { 24 return 0, errInvalidNegativeValueLength(n) 25 } 26 if n > maxLength { 27 return 0, errValueLengthOutOfBounds(n, maxLength) 28 } 29 totalLength += n 30 } 31 32 if totalLength > maxLength { 33 err = errValueLengthOutOfBounds(totalLength, maxLength) 34 } 35 return totalLength, err 36 } 37 38 //go:noescape 39 func decodeLengthByteArrayAVX2(dst, src []byte, lengths []int32) int 40 41 func decodeLengthByteArray(dst, src []byte, lengths []int32) ([]byte, error) { 42 totalLength, err := validateLengthValues(lengths, len(src)) 43 if err != nil { 44 return dst, err 45 } 46 47 size := plain.ByteArrayLengthSize * len(lengths) 48 size += totalLength 49 src = src[:totalLength] 50 dst = resizeNoMemclr(dst, size+padding) 51 52 i := 0 53 j := 0 54 k := 0 55 n := 0 56 57 // To leverage the SEE optimized implementation of the function we must 58 // create enough padding at the end to prevent the opportunistic reads 59 // and writes from overflowing past the buffer's limits. 60 if cpu.X86.HasAVX2 && len(src) > padding { 61 k = len(lengths) 62 63 for k > 0 && n < padding { 64 k-- 65 n += int(lengths[k]) 66 } 67 68 if k > 0 && n >= padding { 69 i = decodeLengthByteArrayAVX2(dst, src, lengths[:k]) 70 j = len(src) - n 71 } else { 72 k = 0 73 } 74 } 75 76 for _, n := range lengths[k:] { 77 plain.PutByteArrayLength(dst[i:], int(n)) 78 i += plain.ByteArrayLengthSize 79 i += copy(dst[i:], src[j:j+int(n)]) 80 j += int(n) 81 } 82 83 return dst[:size], nil 84 }