Skip to content

Commit 05a3f34

Browse files
authored
Merge pull request #5 from parquet-go/optimize-pack-purego
optimize purego bit packing
2 parents b424617 + d2e796c commit 05a3f34

7 files changed

Lines changed: 1227 additions & 63 deletions

File tree

pack.go

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package bitpack
22

3-
import (
4-
"encoding/binary"
5-
)
6-
73
// PackInt32 packs values from src to dst, each value is packed into the given
84
// bit width regardless of how many bits are needed to represent it.
95
//
@@ -13,34 +9,6 @@ func PackInt32(dst []byte, src []int32, bitWidth uint) {
139
packInt32(dst, src, bitWidth)
1410
}
1511

16-
func packInt32(dst []byte, src []int32, bitWidth uint) {
17-
n := ByteCount(uint(len(src)) * bitWidth)
18-
b := dst[:n]
19-
20-
for i := range b {
21-
b[i] = 0
22-
}
23-
24-
bitMask := uint32(1<<bitWidth) - 1
25-
bitOffset := uint(0)
26-
27-
for _, value := range src {
28-
i := bitOffset / 32
29-
j := bitOffset % 32
30-
31-
lo := binary.LittleEndian.Uint32(dst[(i+0)*4:])
32-
hi := binary.LittleEndian.Uint32(dst[(i+1)*4:])
33-
34-
lo |= (uint32(value) & bitMask) << j
35-
hi |= (uint32(value) >> (32 - j))
36-
37-
binary.LittleEndian.PutUint32(dst[(i+0)*4:], lo)
38-
binary.LittleEndian.PutUint32(dst[(i+1)*4:], hi)
39-
40-
bitOffset += bitWidth
41-
}
42-
}
43-
4412
// PackInt64 packs values from src to dst, each value is packed into the given
4513
// bit width regardless of how many bits are needed to represent it.
4614
//
@@ -50,34 +18,6 @@ func PackInt64(dst []byte, src []int64, bitWidth uint) {
5018
packInt64(dst, src, bitWidth)
5119
}
5220

53-
func packInt64(dst []byte, src []int64, bitWidth uint) {
54-
n := ByteCount(uint(len(src)) * bitWidth)
55-
b := dst[:n]
56-
57-
for i := range b {
58-
b[i] = 0
59-
}
60-
61-
bitMask := uint64(1<<bitWidth) - 1
62-
bitOffset := uint(0)
63-
64-
for _, value := range src {
65-
i := bitOffset / 64
66-
j := bitOffset % 64
67-
68-
lo := binary.LittleEndian.Uint64(dst[(i+0)*8:])
69-
hi := binary.LittleEndian.Uint64(dst[(i+1)*8:])
70-
71-
lo |= (uint64(value) & bitMask) << j
72-
hi |= (uint64(value) >> (64 - j))
73-
74-
binary.LittleEndian.PutUint64(dst[(i+0)*8:], lo)
75-
binary.LittleEndian.PutUint64(dst[(i+1)*8:], hi)
76-
77-
bitOffset += bitWidth
78-
}
79-
}
80-
8121
func assertPack(dst []byte, count int, bitWidth uint) {
8222
_ = dst[:ByteCount(bitWidth*uint(count))]
8323
}

pack_arm64.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//go:build !purego
2+
3+
package bitpack
4+
5+
//go:noescape
6+
func packInt32ARM64(dst []byte, src []int32, bitWidth uint)
7+
8+
//go:noescape
9+
func packInt32NEON(dst []byte, src []int32, bitWidth uint)
10+
11+
//go:noescape
12+
func packInt64ARM64(dst []byte, src []int64, bitWidth uint)
13+
14+
//go:noescape
15+
func packInt64NEON(dst []byte, src []int64, bitWidth uint)
16+
17+
func packInt32(dst []byte, src []int32, bitWidth uint) {
18+
if bitWidth <= 8 {
19+
packInt32NEON(dst, src, bitWidth)
20+
} else {
21+
packInt32ARM64(dst, src, bitWidth)
22+
}
23+
}
24+
25+
func packInt64(dst []byte, src []int64, bitWidth uint) {
26+
if bitWidth <= 8 {
27+
packInt64NEON(dst, src, bitWidth)
28+
} else {
29+
packInt64ARM64(dst, src, bitWidth)
30+
}
31+
}

0 commit comments

Comments
 (0)