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

Mitigate LFU struct tearing using SeqLock #621

Merged
merged 4 commits into from
Sep 15, 2024
Merged

Conversation

bitfaster
Copy link
Owner

@bitfaster bitfaster commented Aug 31, 2024

Repeat of #593, but for LFU. The lock counter fits inside node padding when the position enum is reduced from a 32 to 16 bit integer (see #590).

This is preferred to the approach outlined in #596, since we avoid allocating a new node and complicating time-based expiry logic. Nodes now contain a 32bit counter which fits inside the padding for the common case (64bit platform, key and value are 64bit objects).

Revisit:

  • slight throughput penalty, assuming this is from the enum change. It is possible to eliminate the enum and instead compare to each list ptr.
  • code is duplicated for the seq lock itself - see if this can be de-duped.

@coveralls
Copy link

coveralls commented Aug 31, 2024

Coverage Status

coverage: 99.217% (+0.06%) from 99.159%
when pulling 9e85652 on users/alexpeck/tornwrite4
into ab5878b on main.

@bitfaster
Copy link
Owner Author

Get bench difference is noise:

Before

Method Runtime Mean StdDev Ratio
ConcurrentDictionary .NET 6.0 8.411 ns 0.2609 ns 1.00
ConcurrentLfuBackground .NET 6.0 29.658 ns 1.3391 ns 3.53
ConcurrentLfuForeround .NET 6.0 64.598 ns 1.2908 ns 7.69
ConcurrentLfuThreadPool .NET 6.0 48.558 ns 3.3162 ns 5.78
ConcurrentLfuNull .NET 6.0 24.832 ns 0.5998 ns 2.96
ConcurrentDictionary .NET Framework 4.8 15.384 ns 0.5245 ns 1.00
ConcurrentLfuBackground .NET Framework 4.8 59.298 ns 1.0931 ns 3.86
ConcurrentLfuForeround .NET Framework 4.8 99.336 ns 2.2780 ns 6.46
ConcurrentLfuThreadPool .NET Framework 4.8 62.865 ns 0.7662 ns 4.09
ConcurrentLfuNull .NET Framework 4.8 38.489 ns 0.8632 ns 2.50

After

Method Runtime Mean StdDev Ratio
ConcurrentDictionary .NET 6.0 8.307 ns 0.1237 ns 1.00
ConcurrentLfuBackground .NET 6.0 29.964 ns 1.8776 ns 3.61
ConcurrentLfuForeround .NET 6.0 64.969 ns 1.1785 ns 7.82
ConcurrentLfuThreadPool .NET 6.0 47.788 ns 1.7784 ns 5.75
ConcurrentLfuNull .NET 6.0 26.173 ns 0.9501 ns 3.15
ConcurrentDictionary .NET Framework 4.8 15.353 ns 0.4578 ns 1.00
ConcurrentLfuBackground .NET Framework 4.8 55.862 ns 1.2768 ns 3.64
ConcurrentLfuForeround .NET Framework 4.8 100.165 ns 1.7840 ns 6.53
ConcurrentLfuThreadPool .NET Framework 4.8 75.223 ns 1.7748 ns 4.90
ConcurrentLfuNull .NET Framework 4.8 38.881 ns 0.6930 ns 2.53

@bitfaster
Copy link
Owner Author

bitfaster commented Sep 14, 2024

Read+write throughput is regressed slightly, but eviction is not:

image

image

@bitfaster bitfaster merged commit 43dcc90 into main Sep 15, 2024
13 checks passed
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