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

pageserver: Reduce tracing overhead in timeline::get #6115

Merged

Conversation

ivaxer
Copy link
Contributor

@ivaxer ivaxer commented Dec 12, 2023

Problem

Compaction process (specifically the image layer reconstructions part) is lagging behind wal ingest (at speed ~10-15MB/s) for medium-sized tenants (30-50GB). CPU profile shows that significant amount of time (see flamegraph) is being spent in tracing::span::Span::new.

mainline (commit: 0ba4cae):
reconstruct-mainline-0ba4cae491c2

Summary of changes

By lowering the tracing level in get_value_reconstruct_data and get_or_maybe_download from info to debug, we can reduce the overhead of span creation in prod environments. On my system, this sped up the image reconstruction process by 60% (from 14500 to 23160 page reconstruction per sec)

pr:
reconstruct-opt-2

create_image_layers() (it's 1 CPU bound here) mainline vs pr:
image

Checklist before requesting a review

  • I have performed a self-review of my code.
  • If it is a core feature, I have added thorough tests.
  • Do we need to implement analytics? if so did you add the relevant metrics to the dashboard?
  • If this PR requires public announcement, mark it with /release-notes label and add several sentences in this section.

Checklist before merging

  • Do not forget to reformat commit message to not include the above checklist

@ivaxer ivaxer marked this pull request as ready for review December 12, 2023 15:48
@ivaxer ivaxer requested a review from a team as a code owner December 12, 2023 15:48
@ivaxer ivaxer requested review from problame and removed request for a team December 12, 2023 15:48
@bayandin bayandin added the approved-for-ci-run Changes are safe to trigger CI for the PR label Dec 12, 2023
@github-actions github-actions bot removed the approved-for-ci-run Changes are safe to trigger CI for the PR label Dec 12, 2023
@vipvap vipvap mentioned this pull request Dec 12, 2023
Copy link

github-actions bot commented Dec 12, 2023

2190 tests run: 2105 passed, 0 failed, 85 skipped (full report)


Flaky tests (1)

Postgres 15

Code coverage (full report)

  • functions: 55.1% (9680 of 17563 functions)
  • lines: 82.4% (55639 of 67543 lines)

The comment gets automatically updated with the latest test results
ce692a6 at 2023-12-18T13:07:46.072Z :recycle:

Copy link
Contributor

@koivunej koivunej left a comment

Choose a reason for hiding this comment

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

I think it would be great to comment on why those are debug spans, also I did not work plain "debug" would work, but this is a good find anyways.

I will add the comment when I reshuffle the spans to be on the public api of the layer in a follow-up PR later this week.

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 main concern I have is with losing context in case we log an error inside the code whose level you demote to debug in this PR.
Take for example

tracing::error!("layer file download failed, and additionally failed to communicate this to caller: {e:?}");

Currently if we log something there it contains the layer= field.

My understanding is that we'll lose that layer field with this PR.

Of course this can be fixed by rigoruously including layer= field in all the tracing::{info,warn,error}! usage in the call graph of get_or_maybe_download.

So I guess it's a trade-off between performance and convenience.

That being said, the performance gains are impressive.

I assume your workload didn't actually do any ondemand downloads.

Wondering if we can delay the creation of the span (remaining at info level) until we know we're off the hot path.

At least for get_or_maybe_download, it seems straight forward.
@koivunej , thoughts?

@koivunej
Copy link
Contributor

koivunej commented Dec 13, 2023

Good point. The delayed span creation can be implemented by creating the span only at this line:

so the span is created only when the factory is called to actually download and initialize, not before.

Span needed there is:

#[tracing::instrument(skip_all, fields(layer=%self))]

so:

-}
+}.instrument(tracing::info_span!("get_or_maybe_download", layer=%self))

@ivaxer
Copy link
Contributor Author

ivaxer commented Dec 13, 2023

I assume your workload didn't actually do any ondemand downloads.

Yes, I hope this is typical when generating images in the timeline::compact().

I'll try @koivunej suggestion, thanks.

@problame
Copy link
Contributor

Can we do something similar for get_value_reconstruct_data?

@ivaxer ivaxer force-pushed the feature-reconstruction-tracing-perf branch from 312210b to 22cb367 Compare December 13, 2023 16:35
Lowering the tracing level in get_value_reconstruct_data and
get_or_maybe_download from info to debug reduces the overhead
of span creation in non-debug environments.
@ivaxer ivaxer force-pushed the feature-reconstruction-tracing-perf branch from 22cb367 to 239d6b7 Compare December 15, 2023 07:36
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.

IIUC the contribution of get_value_reconstruct_data and get_or_maybe_download is roughly 50:50 in your benchmarks?

If so, let's get the get_or_maybe_download part merged as part of this PR and create a follow-up to improve the get_value_reconstruct_data.

pageserver/src/tenant/storage_layer/layer.rs Outdated Show resolved Hide resolved
pageserver/src/tenant/storage_layer/layer.rs Outdated Show resolved Hide resolved
@ivaxer
Copy link
Contributor Author

ivaxer commented Dec 15, 2023

IIUC the contribution of get_value_reconstruct_data and get_or_maybe_download is roughly 50:50 in your benchmarks?

Yes.

If so, let's get the get_or_maybe_download part merged as part of this PR

Ok.

and create a follow-up to improve the get_value_reconstruct_data.

Ok. Span::new will take >20% CPU time of Timeline::get_reconstruct_data. Any ideas on how to do this other than not creating new span?

flamegraph:
compaction-revert-get-value

@problame problame added the approved-for-ci-run Changes are safe to trigger CI for the PR label Dec 18, 2023
@github-actions github-actions bot removed the approved-for-ci-run Changes are safe to trigger CI for the PR label Dec 18, 2023
@problame problame added the approved-for-ci-run Changes are safe to trigger CI for the PR label Dec 18, 2023
@github-actions github-actions bot removed the approved-for-ci-run Changes are safe to trigger CI for the PR label Dec 18, 2023
problame added a commit that referenced this pull request Dec 18, 2023
Pre-merge `git merge --squash` of
#6115

Lowering the tracing level in get_value_reconstruct_data and
get_or_maybe_download from info to debug reduces the overhead
of span creation in non-debug environments.
@problame problame enabled auto-merge (squash) December 18, 2023 12:41
@problame problame merged commit 33cb9a6 into neondatabase:main Dec 18, 2023
68 of 70 checks passed
@shanyp
Copy link
Contributor

shanyp commented Dec 18, 2023

@ivaxer thanks for your contribution

koivunej added a commit that referenced this pull request Mar 20, 2024
Since #6115 with more often used get_value_reconstruct_data and friends,
we should not have needless INFO level span creation near hot paths. In
our prod configuration, INFO spans are always created, but in practice,
very rarely anything at INFO level is logged underneath.
`ResidentLayer::load_keys` is only used during compaction so it is not
that hot, but this aligns the access paths and their span usage.

PR changes the span level to debug to align with others, and adds the
layer name to the error which was missing.

Split off from #7030.
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

5 participants