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

Epic: improved eviction #5331

Open
14 of 18 tasks
jcsp opened this issue Sep 18, 2023 · 17 comments
Open
14 of 18 tasks

Epic: improved eviction #5331

jcsp opened this issue Sep 18, 2023 · 17 comments
Assignees
Labels
c/storage/pageserver Component: storage: pageserver t/feature Issue type: feature, for new features or requests

Comments

@jcsp
Copy link
Collaborator

jcsp commented Sep 18, 2023

This change will improve the pageserver's ability to accomodate larger tenants, especially those with append-heavy work.

Tasks

  1. 11 of 11
    c/storage/pageserver t/bug
    koivunej
  2. c/storage/pageserver
    koivunej
  3. 2 of 2
    c/storage/pageserver
    jcsp
  4. c/storage/pageserver t/bug
    koivunej
@jcsp jcsp added t/feature Issue type: feature, for new features or requests c/storage/pageserver Component: storage: pageserver labels Sep 18, 2023
@koivunej
Copy link
Member

Moved to inprogress as opening PRs this week and testing in staging.

@koivunej
Copy link
Member

koivunej commented Dec 4, 2023

Did not yet get to start, but hopeful of this week.

koivunej added a commit that referenced this issue Dec 14, 2023
this is aimed at replacing the current mtime only based trashing
alerting later.

Cc: #5331
@koivunej
Copy link
Member

koivunej commented Jan 16, 2024

Discussed this just now, trying to summarize.

My open question had been the "advertised resident set size", and what did it mean to not do time threshold based eviction. Latter is easier, and becomes obvious once you look at our redownloaded_at histogram -- we simply would not do it, and we wouldn't have any of those very fast redownloads.

I pointed out that if we would no longer do threshold based eviction, we might not settle on anything resembling "resident set size" as it would be guided by current EvictionOrder and frequency of executing the more tame version or the more critical version. For a better estimate @jcsp had been thinking MAX(timelines.logical_size) with a fudge factor or just the plain synthetic size. This would be used to advertise if we can accept more tenants.

Post-call comparison of synthetic size sums on a single region where there are mostly 12k tenants per pageserver to sum(max(tenant.timelines.logical_size)) with the special pageservers removed gives a range of 1.32 to 3.08, meaning the suggested fudge factor of 2 might work. Removing threshold based eviction does not matter for this rational.

Related to the very fast redownloads, there are two guesses as for the reason which I investigated after the call:

  1. synthetic size calculation where the point in which we calculate the latest logical size moves forward could get unlucky (in relation to imitation not "catching" this)
  2. availability check ends up redownloading those, because we don't directly imitate basebackup -- but we don't imitate basebackup because it is thought to be covered
    • couldn't find any evidence with the really small sample size 130 on-demand downloads

These guesses are sort of related however, a check_availability might produce WAL (at least it did at one point), so it might cause the synthetic size logical size point to move forward.

One action point, soon recorded in the task list: need to make the logging better however for redownloads, as I only added it as a histogram and these searches are really expensive.

@koivunej
Copy link
Member

koivunej commented Jan 22, 2024

Got to testing #5304 today due to unrelated staging problems. I need to go over the actual results on ps-7.us-east-2.aws.neon.build.

Assuming the results are sane, the next steps are:

  • cleanup the summary messages (semi-revert temp: human readable summaries for relative access time compared to absolute #6384, keep select_victims refactoring)
  • introduce a per timeline evictiontask mode which does not evict but only imitiates
  • perhaps introduce a second mode (or don't) for disk usage based eviction
    • staging: we restart quite often, so pageserver inmemory state is reset often
    • production: we restart much more rarely so perhaps there is no real need

Post-discussion afterthought: if we do disk usage based eviction before all imitations are complete, should the eviction be Lsn based or random...?

@koivunej
Copy link
Member

After further discussion with @jcsp and some review of testing results refined the next steps:

  • testing on staging without per timeline eviction task to make sure huge layer counts are not noticeable for disk usage based eviction
  • enable on one production region which has high disk usage right now (50%)

@jcsp
Copy link
Collaborator Author

jcsp commented Jan 29, 2024

Next:

  • Implement the imitate-only task so that we can disable time based eviction.
  • Engage CP team to agree new API for exposing a size heuristic to unblock moving to disk-only (no time based) eviction
  • Enable relative eviction in prod configs

@koivunej
Copy link
Member

koivunej commented Feb 5, 2024

#6491 and #6598 are ready-ish to go but I forgot the config updates from last week.

Discussion about pageserver owning the "is good for next tenant" is barely started.

@jcsp
Copy link
Collaborator Author

jcsp commented Feb 5, 2024

Next step:

  • Define the interface for CP for utilization
  • Avoid taking tenant locks when collecting layers to evict.

koivunej added a commit that referenced this issue Feb 8, 2024
Calculate the `relative_last_activity` using the total evicted and
resident layers similar to what we originally planned.

Cc: #5331
@koivunej
Copy link
Member

koivunej commented Feb 12, 2024

PR list has these open:

  1. enable rel eviction in prod -- we should merge it
  2. imitation only eviction task policy -- reuses the metrics, but we shouldn't have any different configured per tenant
  3. rwlock contention needs refreshing of review

Next steps:

  • write up an issue on the new endpoint (next bullet)
  • impl the endpoint for querying how good the PS thinks it is for the next tenant

koivunej added a commit that referenced this issue Feb 12, 2024
Refactor out layer accesses so that we can have easy access to resident
layers, which are needed for number of cases instead of layers for
eviction. Simplifies the heatmap building by only using Layers, not
RemoteTimelineClient.

Cc: #5331
jcsp pushed a commit that referenced this issue Feb 12, 2024
Refactor out layer accesses so that we can have easy access to resident
layers, which are needed for number of cases instead of layers for
eviction. Simplifies the heatmap building by only using Layers, not
RemoteTimelineClient.

Cc: #5331
koivunej added a commit that referenced this issue Feb 21, 2024
mostly reusing the existing and perhaps controversially sharing the
histogram. in practice we don't configure this per-tenant.

Cc: #5331
koivunej added a commit that referenced this issue Feb 22, 2024
PR adds a simple at most 1Hz refreshed informational API for querying
pageserver utilization. In this first phase, no actual background
calculation is performed. Instead, the worst possible score is always
returned. The returned bytes information is however correct.

Cc: #6835
Cc: #5331
@koivunej
Copy link
Member

koivunej commented Feb 26, 2024

This week testing out the imitation only policy on staging and deciding if we need to complicate eviction candidate discovery #6224. With imitation only, we will finally run with a high amount of layers all of the time, and disk usage based eviction will run often.

Alternatives to #6224:

  • evict earlier non-hit layers after creating image layers

Before testing this week:

  • task list has a logging improvement
  • metric improvement for understanding how bad is the current layer discovery
  • could also do the low hanging fruit optimizations there

@jcsp
Copy link
Collaborator Author

jcsp commented Feb 26, 2024

Extra notes:

  • The try_lock change was reverted for lack of evidence that it was the underlying cause
  • So ~10 minute hang is still probably in there: expect to see reproduction in staging testing

@koivunej
Copy link
Member

koivunej commented Mar 1, 2024

New dashy for the metrics added in #6131: https://neonprod.grafana.net/d/adecaputaszcwd/disk-usage-based-eviction?orgId=1 -- so far there has not been any disk usage based evictions on staging.

@koivunej
Copy link
Member

koivunej commented Mar 4, 2024

Work this week:

  • staging shows an performance issue with struct Layer or disk usage based eviction collection
  • further testing in staging together with OnlyImitiate policy
  • we will likely roll out continious disk usage based eviction to a single pageserver in prod in a region which has great tenant imbalance

@koivunej
Copy link
Member

koivunej commented Mar 11, 2024

Last week:

This week:

@jcsp
Copy link
Collaborator Author

jcsp commented Mar 11, 2024

split the #7030, get reviews through-out the week

Note to self: this about hangs in disk usage based eviction while collecting layers.

@koivunej
Copy link
Member

Latest troubles in staging have provided good ground for disk usage based eviction runs (pageserver-[01].eu-west-1), listing the examined outliers after #6131:

2024-03-14T12:04:55.501895Z  INFO disk_usage_eviction_task:iteration{iteration_no=1093}: collection took longer than threshold tenant_id=9d984098974b482e25f8b85560f9bba3 shard_id=0000 elapsed_ms=15367

Participated in 9 downloads.

2024-03-14T12:15:44.980494Z  INFO disk_usage_eviction_task:iteration{iteration_no=1155}: collection took longer than threshold tenant_id=a992f0c69c3d69b7338586750ba3f9c1 shard_id=0000 elapsed_ms=12523

Participated in 1 download.

2024-03-14T12:18:45.162630Z  INFO disk_usage_eviction_task:iteration{iteration_no=1168}: collection took longer than threshold tenant_id=7affec0a9fdf9da5b3638894a84cb9cc shard_id=0000 elapsed_ms=13364

Participated in 1 download.

2024-03-14T12:18:59.848429Z  INFO disk_usage_eviction_task:iteration{iteration_no=1168}: collection took longer than threshold tenant_id=a776112dba9d2adbb7a7746b6533125d shard_id=0000 elapsed_ms=10176

Participated in 2 downloads.

2024-03-14T12:19:27.135951Z  INFO disk_usage_eviction_task:iteration{iteration_no=1168}: collection took longer than threshold tenant_id=f231e5ac37f956babb1cc98dcfb088ce shard_id=0000 elapsed_ms=17911

Participated in 1 download.

koivunej added a commit that referenced this issue Mar 15, 2024
Split off from #7030:
- each early exit is counted as canceled init, even though it most
likely was just `LayerInner::keep_resident` doing the no-download repair
check
- `downloaded_after` could had been accounted for multiple times, and
also when repairing to match on-disk state

Cc: #5331
koivunej added a commit that referenced this issue Mar 15, 2024
Aiming for the design where `heavier_once_cell::OnceCell` is initialized
by a future factory lead to awkwardness with how
`LayerInner::get_or_maybe_download` looks right now with the `loop`. The
loop helps with two situations:

- an eviction has been scheduled but has not yet happened, and a read
access should cancel the eviction
- a previous `LayerInner::get_or_maybe_download` that canceled a pending
eviction was canceled leaving the `heavier_once_cell::OnceCell`
uninitialized but needing repair by the next
`LayerInner::get_or_maybe_download`

By instead supporting detached initialization in
`heavier_once_cell::OnceCell` via an `OnceCell::get_or_detached_init`,
we can fix what the monolithic #7030 does:
- spawned off download task initializes the
`heavier_once_cell::OnceCell` regardless of the download starter being
canceled
- a canceled `LayerInner::get_or_maybe_download` no longer stops
eviction but can win it if not canceled

Split off from #7030.

Cc: #5331
koivunej added a commit that referenced this issue Mar 20, 2024
The second part of work towards fixing `Layer::keep_resident` so that it
does not need to repair the internal state. #7135 added a nicer API for
initialization. This PR uses it to remove a few indentation levels and
the loop construction. The next PR #7175 will use the refactorings done
in this PR, and always initialize the internal state after a download.

Cc: #5331
koivunej added a commit that referenced this issue Mar 20, 2024
Before this PR, cancellation for `LayerInner::get_or_maybe_download`
could occur so that we have downloaded the layer file in the filesystem,
but because of the cancellation chance, we have not set the internal
`LayerInner::inner` or initialized the state. With the detached init
support introduced in #7135 and in place in #7152, we can now initialize
the internal state after successfully downloading in the spawned task.

The next PR will fix the remaining problems that this PR leaves:
- `Layer::keep_resident` is still used because
- `Layer::get_or_maybe_download` always cancels an eviction, even when
canceled

Split off from #7030. Stacked on top of #7152. Cc: #5331.
koivunej added a commit that referenced this issue Mar 20, 2024
Small fix to remove confusing `mut` bindings.

Builds upon #7175, split off from #7030. Cc: #5331.
koivunej added a commit that referenced this issue Mar 21, 2024
## Problem

The current implementation of struct Layer supports canceled read
requests, but those will leave the internal state such that a following
`Layer::keep_resident` call will need to repair the state. In
pathological cases seen during generation numbers resetting in staging
or with too many in-progress on-demand downloads, this repair activity
will need to wait for the download to complete, which stalls disk
usage-based eviction. Similar stalls have been observed in staging near
disk-full situations, where downloads failed because the disk was full.

Fixes #6028 or the "layer is present on filesystem but not evictable"
problems by:
1. not canceling pending evictions by a canceled
`LayerInner::get_or_maybe_download`
2. completing post-download initialization of the `LayerInner::inner`
from the download task

Not canceling evictions above case (1) and always initializing (2) lead
to plain `LayerInner::inner` always having the up-to-date information,
which leads to the old `Layer::keep_resident` never having to wait for
downloads to complete. Finally, the `Layer::keep_resident` is replaced
with `Layer::is_likely_resident`. These fix #7145.

## Summary of changes

- add a new test showing that a canceled get_or_maybe_download should
not cancel the eviction
- switch to using a `watch` internally rather than a `broadcast` to
avoid hanging eviction while a download is ongoing
- doc changes for new semantics and cleanup
- fix `Layer::keep_resident` to use just `self.0.inner.get()` as truth
as `Layer::is_likely_resident`
- remove `LayerInner::wanted_evicted` boolean as no longer needed

Builds upon: #7185. Cc: #5331.
@koivunej
Copy link
Member

koivunej commented Apr 3, 2024

Before and after #7030:

2024-03-21T02:41:07.618648Z  INFO disk_usage_eviction_task:iteration{iteration_no=1362}: collection completed elapsed_ms=4969 total_layers=83690
2024-03-21T03:53:43.072165Z  INFO disk_usage_eviction_task:iteration{iteration_no=400}: collection completed elapsed_ms=135 total_layers=83695

The set of PRs culminating with #7030 also removed the "10min hang" previously observed. Later more evidence came that it was caused by waiting for a download. For other fixed cases, see: #6028 (comment)


pageserver_layer_downloaded_after metric is still not being used to alert because many cases in staging cause redownloads very soon after evicting. In production, the old mtime-based trashing alert has been downgraded as a warning. It is not known why we get into this situation.

Log analysis is still too time-consuming to spot any patterns. #7030 preliminaries also included fixes for updating this metric. The best guess so far is that we get unlucky with:

  1. evict
  2. initiate layer accesses right after

However, in the short time between (1) to (2), the PITR could have advanced just enough to warrant new synthetic size calculation, for example.


The utilization endpoint work has just not been started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c/storage/pageserver Component: storage: pageserver t/feature Issue type: feature, for new features or requests
Projects
None yet
Development

No branches or pull requests

2 participants