From e488a0bc1b9062d95542589dccdee0d0e1e20e0a Mon Sep 17 00:00:00 2001 From: Maciej Bilas Date: Tue, 16 Jan 2018 15:12:03 +0100 Subject: [PATCH 1/3] fromBuffer: don't append to roaringArray slices when not necessary --- roaringarray.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/roaringarray.go b/roaringarray.go index fbee02d7..89da6bbb 100644 --- a/roaringarray.go +++ b/roaringarray.go @@ -580,13 +580,16 @@ func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) { } // Allocate slices upfront as number of containers is known - ra.containers = make([]container, 0, size) - ra.keys = make([]uint16, 0, size) - ra.needCopyOnWrite = make([]bool, 0, size) + ra.containers = make([]container, size) + ra.keys = make([]uint16, size) + ra.needCopyOnWrite = make([]bool, size) for i := uint32(0); i < size; i++ { key := uint16(keycard[2*i]) card := int(keycard[2*i+1]) + 1 + ra.keys[i] = key + ra.needCopyOnWrite[i] = true + if haveRunContainers && isRun.contains(uint16(i)) { // run container nr := binary.LittleEndian.Uint16(buf[pos:]) @@ -596,7 +599,7 @@ func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) { card: int64(card), } pos += int(nr) * 4 - ra.appendContainer(key, &nb, true) + ra.containers[i] = &nb } else if card > arrayDefaultMaxSize { // bitmap container nb := bitmapContainer{ @@ -604,14 +607,14 @@ func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) { bitmap: byteSliceAsUint64Slice(buf[pos : pos+arrayDefaultMaxSize*2]), } pos += arrayDefaultMaxSize * 2 - ra.appendContainer(key, &nb, true) + ra.containers[i] = &nb } else { // array container nb := arrayContainer{ byteSliceAsUint16Slice(buf[pos : pos+card*2]), } pos += card * 2 - ra.appendContainer(key, &nb, true) + ra.containers[i] = &nb } } From d3a8c122b6c1a783e024b19a1aca8c5c6d7830b2 Mon Sep 17 00:00:00 2001 From: Maciej Bilas Date: Tue, 16 Jan 2018 15:56:32 +0100 Subject: [PATCH 2/3] Add generic uint64SliceAsByteSlice --- serialization_generic.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/serialization_generic.go b/serialization_generic.go index da852338..7fcef769 100644 --- a/serialization_generic.go +++ b/serialization_generic.go @@ -59,6 +59,16 @@ func (bc *bitmapContainer) asLittleEndianByteSlice() []byte { return by } +func uint64SliceAsByteSlice(slice []uint64) []byte { + by := make([]byte, len(slice)*8) + + for i, v := range slice { + binary.LittleEndian.PutUint64(by[i*8:], v) + } + + return by +} + func byteSliceAsUint16Slice(slice []byte) []uint16 { if len(slice)%2 != 0 { panic("Slice size should be divisible by 2") From 61fc009801ec0a4210ab58f795902260f35b02b8 Mon Sep 17 00:00:00 2001 From: Maciej Bilas Date: Wed, 31 Jan 2018 14:41:22 +0100 Subject: [PATCH 3/3] FromBuffer: no-copy _isRunBitmap_ --- roaringarray.go | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/roaringarray.go b/roaringarray.go index 89da6bbb..ee2db7c0 100644 --- a/roaringarray.go +++ b/roaringarray.go @@ -541,7 +541,7 @@ func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) { pos += 4 var size uint32 // number of containers haveRunContainers := false - var isRun *bitmapContainer + var isRunBitmap []byte // cookie header if cookie&0x0000FFFF == serialCookie { @@ -549,20 +549,9 @@ func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) { size = uint32(uint16(cookie>>16) + 1) // number of containers // create is-run-container bitmap - bytesToRead := (int(size) + 7) / 8 - by := buf[pos : pos+bytesToRead] - pos += bytesToRead - isRun = newBitmapContainer() - i := 0 - for ; len(by) >= 8; i++ { - isRun.bitmap[i] = binary.LittleEndian.Uint64(by) - by = by[8:] - } - if len(by) > 0 { - bx := make([]byte, 8) - copy(bx, by) - isRun.bitmap[i] = binary.LittleEndian.Uint64(bx) - } + isRunBitmapSize := (int(size) + 7) / 8 + isRunBitmap = buf[pos : pos+isRunBitmapSize] + pos += isRunBitmapSize } else if cookie == serialCookieNoRunContainer { size = binary.LittleEndian.Uint32(buf[pos:]) pos += 4 @@ -590,7 +579,7 @@ func (ra *roaringArray) fromBuffer(buf []byte) (int64, error) { ra.keys[i] = key ra.needCopyOnWrite[i] = true - if haveRunContainers && isRun.contains(uint16(i)) { + if haveRunContainers && isRunBitmap[i/8]&(1<<(i%8)) != 0 { // run container nr := binary.LittleEndian.Uint16(buf[pos:]) pos += 2