Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use fst for sstable index #2268

Merged
merged 19 commits into from
Dec 4, 2023
Merged

use fst for sstable index #2268

merged 19 commits into from
Dec 4, 2023

Conversation

trinity-1686a
Copy link
Contributor

related to quickwit-oss/quickwit#3964

makes loading an sstable index basically free (previously you'd decode a datastructure, which could take a non-negligible amount of time, in practice ~200ms for a 125m term table, with keys encoding json paths).

sstable/README.md Outdated Show resolved Hide resolved
sstable/README.md Outdated Show resolved Hide resolved
sstable/README.md Outdated Show resolved Hide resolved
// we actually add some correcting factor to have proper rounding, not truncation.

let denominator = (min_slop_idx + max_slop_idx) as u64;
let final_slop = ((min_slop_val + max_slop_val + denominator / 2) / denominator) as u32;
Copy link
Collaborator

@fulmicoton fulmicoton Nov 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let final_slop = ((min_slop_val + max_slop_val + denominator / 2) / denominator) as u32;
let final_slop = ((min_slop_val + max_slop_val + denominator / 2) / denominator) as u32;

would using a decimal slope (not a float but just using a 4 bits as decimal for instance) help here?

let final_slop = ((min_slop_val + max_slop_val + denominator / 2) * 16 / denominator) as u32;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that code is enough to make sure we round in the right direction. I think using fixed point integers wouldn't really help as we would still need to use a similar trick when collapsing the fixed point integers to whole numbers

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant: wouldn't it make the decimal slope make the prediction for high indexes and eventually help with the compression.

as we would still need to use a similar trick when collapsing the fixed point integers to whole numbers

I suspect you forgot there is a multiplication in between.

truncateroundorwhatever(slope*idx)
vs
idx * truncateroundorwhatever(slope)
will actually give you very different precision.

I would not be surprised if you could shave off one or two bits in your encoding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ftr: I tried and on my sample dataset, there was a negligible gain of about 0.1%. Either I did something wrong and I can't figure out what, or the impact is negligible


let cmp = cmp_fn(mid);

if cmp == Less {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: match would be nice here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation was in part copied from libcore. It said the following about that comparison:

// The reason why we use if/else control flow rather than match
// is because match reorders comparison operations, which is perf sensitive.
// This is x86 asm for u8: https://rust.godbolt.org/z/8Y8Pra.

Copy link
Collaborator

@fulmicoton fulmicoton Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am seeing the same assembly code. Maybe the compiler improved?
anyway no need to fix.

}

fn flush_block(&mut self) -> io::Result<()> {
let ref_block_addr = self.block_addrs[0].clone();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it non empty?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caller make sure of that, but I changed it so it's always safe to call

.map(|block| block.byte_range.start as u64)
.chain(std::iter::once(last_block_addr.byte_range.end as u64))
.enumerate()
.skip(1),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how do we know block addrs contains more than one el?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need to, find_best_slope accept empty iterator

sstable/README.md Outdated Show resolved Hide resolved
sstable/README.md Outdated Show resolved Hide resolved
@trinity-1686a trinity-1686a merged commit 9ebc5ed into main Dec 4, 2023
4 checks passed
@trinity-1686a trinity-1686a deleted the trinity--sstable-index-fst branch December 4, 2023 14:13
PSeitz pushed a commit that referenced this pull request Apr 10, 2024
* read path for new fst based index

* implement BlockAddrStoreWriter

* extract slop/derivation computation

* use better linear approximator and allow negative correction to approximator

* document format and reorder some fields

* optimize single block sstable size

* plug backward compat
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants