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

feat(page_service): timeout-based batching of requests #9321

Merged
merged 32 commits into from
Nov 18, 2024

Conversation

VladLazar
Copy link
Contributor

@VladLazar VladLazar commented Oct 8, 2024

Problem

We don't take advantage of queue depth generated by the compute
on the pageserver. We can process getpage requests more efficiently
by batching them.

Summary of changes

Batch up incoming getpage requests that arrive within a configurable time window (server_side_batch_timeout).
Then process the entire batch via one get_vectored timeline operation.
By default, no merging takes place.

Testing

@VladLazar VladLazar force-pushed the vlad/pageserver-merge-get-page-requests branch from 2fd0a67 to 14883d2 Compare October 8, 2024 16:52
@VladLazar VladLazar force-pushed the vlad/pageserver-merge-get-page-requests branch from 14883d2 to 96afede Compare October 8, 2024 16:53
Copy link

github-actions bot commented Oct 8, 2024

5490 tests run: 5264 passed, 0 failed, 226 skipped (full report)


Code coverage* (full report)

  • functions: 31.5% (7932 of 25181 functions)
  • lines: 49.6% (62944 of 126880 lines)

* collected from Rust tests only


The comment gets automatically updated with the latest test results
2bea398 at 2024-11-18T20:25:20.479Z :recycle:

Copy link
Contributor

@problame problame left a comment

Choose a reason for hiding this comment

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

The terminology is 50% debounce 50% batching.

I think batching is better, let's adjust the names.

As a person who doesn't mind wordy names, page_service_server_side_batching is how I'd call the functionality / code module.

Maybe server_side_batch_timeout for the config flag?

And BatchedFeMessageS instead of DebouncedFeMessage for the type?


During the hackathon, and now, I wonder(ed) whether we could refactor the batching loop into a Stream / $itertoolsadapter

Like, at the start of handle_pagerequests, split the pgb into reading and writing end (maybe fake that using Arc<Mutex<Pgb>>).
The wrap the reading end into the thing that implements Stream, spitting out DebouncedFeMessage as the strema item.

Orthogonal to that, can we please move the batching into a helper function so the high-level control flow of handle_pagerequests remains clear-ish?


I flagged a couple of places that warn! aggressively.
I actually don't know if we log getpage errors. If we do, then I think it's fine to just leave these warn! messages & dismiss the conversation.

pageserver/src/page_service.rs Outdated Show resolved Hide resolved
pageserver/src/page_service.rs Outdated Show resolved Hide resolved
pageserver/src/page_service.rs Outdated Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Outdated Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Outdated Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Outdated Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Outdated Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Outdated Show resolved Hide resolved
@VladLazar
Copy link
Contributor Author

The terminology is 50% debounce 50% batching.

I think batching is better, let's adjust the names.

As a person who doesn't mind wordy names, page_service_server_side_batching is how I'd call the functionality / code module.

Maybe server_side_batch_timeout for the config flag?

And BatchedFeMessageS instead of DebouncedFeMessage for the type?

You're right. I'll touch up the names.

During the hackathon, and now, I wonder(ed) whether we could refactor the batching loop into a Stream / $itertoolsadapter

Like, at the start of handle_pagerequests, split the pgb into reading and writing end (maybe fake that using Arc<Mutex<Pgb>>). The wrap the reading end into the thing that implements Stream, spitting out DebouncedFeMessage as the strema item.

I also wondered about this while going through the code, but resisted the temptation to rewrite.
Let's create an epic and add a follow-up in there.

Orthogonal to that, can we please move the batching into a helper function so the high-level control flow of handle_pagerequests remains clear-ish?

Sure, I'll give it a go.

The refactor is straightforward, but we also fix a bug.
Previously, a batch could have been empty if handling the first message
resulted in an error (would have panicked). This has been fixed by
including errors in the current batch.
Conflicts: Pageserver config was also updated in main
We already log get page errors the pagestream level
and on the ingest path.
Switch to over to using Vec for the `Vec::spare_capacity_mut`
interface. Fill the `MayebUninit` slots carefully and `Vec::set_len`
at the end.
@VladLazar
Copy link
Contributor Author

  • Switched naming to batching
  • Looked into logging. We already log on both pagestream and ingest flows, so I've removed the redundant logging.
  • Reworked response filling to work around one copy
  • Refactored batching into a separate method.

@VladLazar VladLazar marked this pull request as ready for review October 14, 2024 11:06
@VladLazar VladLazar requested a review from a team as a code owner October 14, 2024 11:06
Copy link
Contributor

@problame problame 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 a lot of plumbing-through of the server_side_batch_timeout variable.
Personally I wouldn't mind just plumbing through the &'static PageServerConf.
Or building a PageServiceConf object out of PageServerConf.
Easily punt-able though.


I think the only two things I'm hard-requesting-changes for is the use of smallvec<1> for the return value of read_batch_from_connection, and the elimination of the panic!(unsupported)

pageserver/src/page_service.rs Outdated Show resolved Hide resolved
pageserver/src/page_service.rs Show resolved Hide resolved
pageserver/src/page_service.rs Outdated Show resolved Hide resolved
pageserver/src/page_service.rs Outdated Show resolved Hide resolved
pageserver/src/page_service.rs Outdated Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Outdated Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Outdated Show resolved Hide resolved
pageserver/src/pgdatadir_mapping.rs Show resolved Hide resolved
@problame problame self-assigned this Nov 12, 2024
problame added a commit that referenced this pull request Nov 17, 2024
Smallvec 1.13.2 contains [an UB fix](servo/rust-smallvec#345).

Upstream opened [a request](rustsec/advisory-db#1960)
for this in the advisory-db but it never got acted upon.

Found while working on #9321.
problame added a commit that referenced this pull request Nov 17, 2024
Smallvec 1.13.2 contains [an UB
fix](servo/rust-smallvec#345).

Upstream opened [a
request](rustsec/advisory-db#1960)
for this in the advisory-db but it never got acted upon.

Found while working on #9321.
…-get-page-requests

Conflicts (all syntactic, not semantic)
	libs/pageserver_api/src/config.rs
	pageserver/Cargo.toml
	pageserver/src/config.rs
	pageserver/src/page_service.rs
	pageserver/src/pgdatadir_mapping.rs
…n of PageReconstructError=>PageStreamError for case of Timeline cancellation
@problame problame changed the title pageserver: merge get page requests pageserver: option to merge getpage requests Nov 17, 2024
@problame problame changed the title pageserver: option to merge getpage requests feat(page_service): timeout-based batching of requests Nov 17, 2024
@problame problame removed their assignment Nov 18, 2024
@problame problame enabled auto-merge (squash) November 18, 2024 19:29
@problame problame merged commit d7662fd into main Nov 18, 2024
76 checks passed
@problame problame deleted the vlad/pageserver-merge-get-page-requests branch November 18, 2024 20:24
problame added a commit that referenced this pull request Nov 20, 2024
This PR adds a benchmark to demonstrate the effect of server-side
getpage request batching added in #9321.

Refs:

- Epic: #9376
- Extracted from #9792
github-merge-queue bot pushed a commit that referenced this pull request Nov 25, 2024
This PR adds two benchmark to demonstrate the effect of server-side
getpage request batching added in
#9321.

For the CPU usage, I found the the `prometheus` crate's built-in CPU
usage accounts the seconds at integer granularity. That's not enough you
reduce the target benchmark runtime for local iteration. So, add a new
`libmetrics` metric and report that.

The benchmarks are disabled because [on our benchmark nodes, timer
resolution isn't high
enough](https://neondb.slack.com/archives/C059ZC138NR/p1732264223207449).
They work (no statement about quality) on my bare-metal devbox.

They will be refined and enabled once we find a fix. Candidates at time
of writing are:
- #9822
- #9851


Refs:

- Epic: #9376
- Extracted from #9792
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.

pageserver: batch get page requests and serve them with one vectored get
2 participants