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

PS/Prefetch: Use a timeout for reading data from TCP #10834

Merged
merged 4 commits into from
Feb 27, 2025

Conversation

MMeent
Copy link
Contributor

@MMeent MMeent commented Feb 14, 2025

This reduces pressure on OS TCP buffers, reducing flush times in other systems like PageServer.

Problem

Summary of changes

Copy link

github-actions bot commented Feb 14, 2025

7744 tests run: 7366 passed, 0 failed, 378 skipped (full report)


Code coverage* (full report)

  • functions: 32.8% (8642 of 26359 functions)
  • lines: 48.7% (73209 of 150476 lines)

* collected from Rust tests only


The comment gets automatically updated with the latest test results
e456cc9 at 2025-02-27T13:31:47.712Z :recycle:

@MMeent MMeent force-pushed the MMeent/timeout-based-prefetch-queue-draining branch from 65b6124 to cce5d5d Compare February 17, 2025 16:31
Copy link

If this PR added a GUC in the Postgres fork or neon extension,
please regenerate the Postgres settings in the cloud repo:

make NEON_WORKDIR=path/to/neon/checkout \
  -C goapp/internal/shareddomain/postgres generate

If you're an external contributor, a Neon employee will assist in
making sure this step is done.

@MMeent MMeent marked this pull request as ready for review February 20, 2025 15:22
@MMeent MMeent requested review from a team as code owners February 20, 2025 15:22
@MMeent MMeent force-pushed the MMeent/timeout-based-prefetch-queue-draining branch from f94533c to f24e99e Compare February 20, 2025 15:26
@MMeent MMeent enabled auto-merge February 20, 2025 23:19
@MMeent MMeent force-pushed the MMeent/timeout-based-prefetch-queue-draining branch 2 times, most recently from 6db9ede to 93ab153 Compare February 21, 2025 16:38
Copy link
Member

@skyzh skyzh left a comment

Choose a reason for hiding this comment

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

LGTM from the storage side

@MMeent MMeent force-pushed the MMeent/timeout-based-prefetch-queue-draining branch 2 times, most recently from 0caec61 to b86b759 Compare February 21, 2025 17:07
@MMeent MMeent requested a review from hlinnaka February 21, 2025 17:09
@MMeent MMeent force-pushed the MMeent/timeout-based-prefetch-queue-draining branch from b86b759 to 7214004 Compare February 25, 2025 15:30
@hlinnaka
Copy link
Contributor

This still makes me pretty squirmish. Are you sure you might not "re-enter" some parts of the prefetching code? The readpage_reentrant_guard is supposed to prevent that, but I can't convince myself that it's enough and that it's used in the right places. I don't see any direct bug or issue either though.

For example, can an interrupt happen while we're in a prefetch_register_bufferv() call? Is it OK? I don't see any CHECK_FOR_INTERRUPTS() calls there, but it's a long function, it's hard to tell at a quick glance.

Does the guard protect some specific fields of MyPState?

@hlinnaka
Copy link
Contributor

prefetch_pump_state has this comment:

 * Note that this works because we don't pipeline non-getPage requests.

Took me a while to understand, but I got it now:

smgrnblocks()
 -> neon_nblocks()
   -> page_server_request()
     -> page_server->receive()
       -> pageserver_receive()
         -> call_PQgetCopyData()
           -> CHECK_FOR_INTERRUPTS()
             -> pagestore_smgr_processinterrupts()
               -> prefetch_pump_state()
                 -> page_server->try_receive()
                   -> PQgetCopyData()

The above cannot happen, because prefetch_pump_state() would find that there are no in-flight requests in the ring.

So that's OK, although feels a bit fragile.

Copy link
Contributor

@hlinnaka hlinnaka left a comment

Choose a reason for hiding this comment

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

I don't see a concrete problem with this even though I'm a bit squirmish.

Let's add a GUC for this though. I'd love to have this in staging and pre-prod for a while, and perhaps do a slow roll out to production too, starting with the endpoints that have experienced problems with the socket buffers filling up.

I think a simple check in reconfigure_timeout_if_needed to do nothing if the GUC is not set would do the trick. Or since we're adding a GUC, perhaps make it an integer GUC to replace the PS_BACKGROUND_DELAY constant. Then we can also experiment making it more or less aggressive.

This reduces pressure on OS TCP buffers, reducing TCP backpressure and
therefore flush times in upstream systems like PageServer.

The timeout triggers every 100 ms (compile-time constant) if there are
any outstanding getpage requests.
That's better than a builtin constant, as it allows us to better control the behaviour of this feature.
@MMeent MMeent force-pushed the MMeent/timeout-based-prefetch-queue-draining branch from 7214004 to db031d7 Compare February 26, 2025 14:55
@MMeent
Copy link
Contributor Author

MMeent commented Feb 26, 2025

@hlinnaka Did you mean something like this latest? (i.e. commit 2 of 3)

- Adjust comment on readahead_getpage_pull_timeout_ms
- Use 0 for disabling the timeout, not both 0 and -1
- Limit the timeout to 5 minutes
@MMeent MMeent added this pull request to the merge queue Feb 27, 2025
Merged via the queue into main with commit a283eda Feb 27, 2025
91 checks passed
@MMeent MMeent deleted the MMeent/timeout-based-prefetch-queue-draining branch February 27, 2025 14:01
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.

3 participants