feat: add roaring bitmaps in posing lists - #446
Conversation
|
@seqbenchbot up 336-compaction mixed |
|
@seqbenchbot down ec638c8c |
|
Nice, @cheb0 The benchmark with identificator Show summary
Have a great time! |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #446 +/- ##
==========================================
+ Coverage 71.33% 71.49% +0.16%
==========================================
Files 233 235 +2
Lines 18999 19328 +329
==========================================
+ Hits 13552 13818 +266
- Misses 4419 4465 +46
- Partials 1028 1045 +17 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
d3f3922 to
4af844b
Compare
🔴 Performance DegradationSome benchmarks have degraded compared to the previous run. Show table
|
🔴 Performance DegradationSome benchmarks have degraded compared to the previous run. Show table
|
There was a problem hiding this comment.
It's gonna be interesting to see how bitmaps will affect sealing latency (and system in overall):
benchstat ~/main.txt ~/bitmaps.txt
goos: linux
goarch: amd64
pkg: github.com/ozontech/seq-db/fracmanager
cpu: 12th Gen Intel(R) Core(TM) i5-12600K
│ /home/dkharms/main.txt │ /home/dkharms/bitmaps.txt │
│ sec/op │ sec/op vs base │
Sealing_NoSort-4 459.1m ± 2% 468.2m ± 2% +1.97% (p=0.005 n=10)
│ /home/dkharms/main.txt │ /home/dkharms/bitmaps.txt │
│ B/op │ B/op vs base │
Sealing_NoSort-4 23.05Mi ± 0% 26.06Mi ± 0% +13.05% (p=0.000 n=10)
│ /home/dkharms/main.txt │ /home/dkharms/bitmaps.txt │
│ allocs/op │ allocs/op vs base │
Sealing_NoSort-4 5.322k ± 0% 8.309k ± 0% +56.11% (p=0.000 n=10)There was a problem hiding this comment.
So far I see they slow down quite literally everything except places where you actually intersect/union them :)
| return b.copyLIDsFromBitmap(t, dst) | ||
| } | ||
|
|
||
| func (b *Block) copyLIDsFromBitmap(ref int32, buf []uint32) []uint32 { |
There was a problem hiding this comment.
| func (b *Block) copyLIDsFromBitmap(ref int32, buf []uint32) []uint32 { | |
| func (b *Block) appendLIDsFromBitmapTo(ref int32, buf []uint32) []uint32 { |
There was a problem hiding this comment.
As I am getting deeper in this pull request I just have several questions about roaring bitmaps in general:
- Are they concurrent-safe for read-only use (getting max/min, cardinality)?
- Are they concurrent-safe for (possibly) mutating operations (like
Or(bm1, bm2)) or there are different APIs for performing such operations in-place or returning a new copy instead?
| type Block struct { | ||
| LIDs []uint32 | ||
| Offsets []uint32 | ||
| types []int32 // determines LID list type: delta-encoded (non-negative value) or bitmap (negative value). nil for delta-encoded blocks |
There was a problem hiding this comment.
Have you measured whether materializing types actually buys anything vs. a binary search over bitmapIndexes? Like it's pretty easy to grasp but the liability of performing checks like b.types == nil is error-prone (IMHO).
And this decision is not scalable since you encode the type of block into signedness of integer (so there could be at most two different types). So if we are going to introduce different format for storing lids we would still have to rewrite this logic.
It could be easily rewritten as something like:
func (b *Block) chunkRef(i int) (ChunkType, int) {
k, found := slices.BinarySearch(b.bitmapIndexes, uint32(i))
if found {
return ChunkTypeBitmap, k
}
return ChunkTypeDelta, i - k
}| // BitmapThreshold specifies minimum number of LIDs in the lid list | ||
| // which are serialized as bitmap. LIDs lists with more elements use bitmap encoding, | ||
| // while smaller lists use delta encoding. | ||
| BitmapThreshold int `config:"bitmap_threshold" default:"65536"` |
There was a problem hiding this comment.
Should we add some kind of validation that BitmapThreshold cannot be larger than BlockSize?
| return size | ||
| } | ||
|
|
||
| func (p *BlockPacker) Pack(b *UnpackedBlock, dst []byte) []byte { |
There was a problem hiding this comment.
Just curious. Have you tried to measure performance metrics when we include whole posting list for token when it exceeds 65k? Of course it heavily depends on density of lids but still it is quite interesting.
However it might break something if we use block capacity as a divider somewhere (I do not remember)...
| NextBatch(need int) LIDBatch | ||
| // NextBatchGeq returns next batch (LIDs >= minLID). Returns nil when exhausted. | ||
| NextBatchGeq(nextLID LID) LIDBatch | ||
| NextBatchGeq(need int, nextLID LID) LIDBatch |
There was a problem hiding this comment.
Seems like need argument is not used anywhere. And in #479 it was deleted again.
There was a problem hiding this comment.
Yes, I deleted it laster. As part of two PRs need will not be added.
Co-authored-by: Daniil <dkharmsd@gmail.com>
Co-authored-by: Daniil <dkharmsd@gmail.com>
🔴 Performance DegradationSome benchmarks have degraded compared to the previous run. Show table
|
Description