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

kafka replay speed: don't trim fetchWants #9919

Merged
merged 3 commits into from
Nov 17, 2024

Conversation

dimitarvdimitrov
Copy link
Contributor

@dimitarvdimitrov dimitarvdimitrov commented Nov 15, 2024

What this PR does

I realized that trimming fetchWants can end up discarding offsets in extreme circumstances.

How it works

If the fetchWant is so big that its size would exceed 2GiB, then we trim it. We trim it by reducing the end offset. The idea is that the next fetchWant will pick up from where this one left off.

How it can break

We trim the fetchWant in UpdateBytesPerRecord too. UpdateBytesPerRecord can be invoked in concurrentFEtchers.run after the fetchWant is dispatched. In that case the next fetchWant would have already been calculated. And we would end up with a gap.

Did it break?

It's hard to tell, but it's very unlikely. To reach 2GiB we would have needed to have the estimation for bytes per record be 2 MiB (with 1000 records per fetch). While these large records are possible, they should be rare and our rolling average estimation for records size shouldn't reach it.

Why we can do without trimIfTooBig()?

MaxBytes() already caps the value to MaxInt32, so we're compliant with the Kafka Protocol.

fetchBytes := w.expectedBytes()
if fetchBytes > math.MaxInt32 {
// This shouldn't happen because w should have been trimmed before sending the request.
// But we definitely don't want to request negative bytes by casting to int32, so add this safeguard.
return math.MaxInt32
}

Which issue(s) this PR fixes or relates to

Fixes #

Checklist

  • Tests updated.
  • Documentation added.
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX].
  • about-versioning.md updated with experimental features.

I realized that trimming `fetchWant`s can end up discarding offsets in extreme circumstances.

### How it works

If the fetchWant is so big that its size would exceed 2GiB, then we trim it. We trim it by reducing the end offset. The idea is that the next fetchWant will pick up from where this one left off.

### How it can break

We trim the `fetchWant` in `UpdateBytesPerRecord` too. `UpdateBytesPerRecord` can be invoked in `concurrentFEtchers.run` after the `fetchWant` is dispatched. In that case the next `fetchWant` would have already been calculated. And we would end up with a gap.

### Did it break?

It's hard to tell, but it's very unlikely. To reach 2GiB we would have needed to have the estimation for bytes per record be 2 MiB. While these large records are possible, they should be rare and our rolling average estimation for records size shouldn't reach it.

Signed-off-by: Dimitar Dimitrov <[email protected]>
@dimitarvdimitrov dimitarvdimitrov requested a review from a team as a code owner November 15, 2024 15:31
Copy link
Collaborator

@pracucci pracucci left a comment

Choose a reason for hiding this comment

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

I see the problem. Good job spotting it!

Do you think we can unit test fetchWatch.MaxBytes() and UpdateBytesPerRecord() for this specific case the fetch would be greater than int32 bytes? I know we removed the trim code, but could help us not reintroduce something similar in the future.

pkg/storage/ingest/fetcher.go Outdated Show resolved Hide resolved
@dimitarvdimitrov
Copy link
Contributor Author

Do you think we can unit test fetchWatch.MaxBytes() and UpdateBytesPerRecord() for this specific case the fetch would be greater than int32 bytes? I know we removed the trim code, but could help us not reintroduce something similar in the future.

added some tests here and had to adjust MaxBytes slightly because it could overflow sometimes dcc1397

@dimitarvdimitrov dimitarvdimitrov merged commit c3b4ada into main Nov 17, 2024
29 checks passed
@dimitarvdimitrov dimitarvdimitrov deleted the dimitar/ingest/remove-fetchWant-trimming branch November 17, 2024 18:14
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.

2 participants