Repository navigation
Make a plain Cache.get read less and reuse a cursor per thread - #38
Merged
Merged
Conversation
…ta or bookkeeping is needed.
…ge so lint passes.
This was referenced Nov 2, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A plain
Cache.getdoes less work per call. That's a get with statistics off, an eviction policy that doesn't write on reads, and noexpire_time,tagorstore_timeasked for. Hits are about 17% faster than master and 5.6.3, misses about 12%, andDjangoCache.getabout 16%.mode,filenameandvalue, withfetchone(). The key and raw columns are unique, so there is at most one row. Requests for metadata, and caches that record statistics or access times, keep the existing queries._connectand dropped with the connection byclose()and after a fork. Only statements whose result is fetched right away use it.on_error='miss', an unreadable entry found on this path is deleted by its key and raw columns, with the same check that the row hasn't changed. Other paths still delete byrowid.getgets two more pylint size disables, for the same reason as before: a helper call would cost a share of every hit.max-module-linesgoes from 4100 to 4200, and a long line on the benchmarks page is wrapped. Both are identical to PR Make Cache.set faster by running fewer statements and less Python per write #37.CHANGELOG.mdentry underUnreleased.Measured with interleaved runs: each build in its own venv on the Python 3.14.6 GIL build, SQLite 3.53.1, Apple M5 Pro, 20 rounds in random order. Medians are against PyPI diskcache 5.6.3; 5.6.3 and master were each run twice to show the noise.
get(tag=True)getwith metadata flags is unchanged by this PR. It is still about 5% slower than 5.6.3 because of the metadata tuple helper, andmemoize_stampedecallsget(expire_time=True). That could be a follow-up.The code merges cleanly with PR #37. Both PRs add a
### Performancesection toCHANGELOG.md, so whichever merges second needs a one-line rebase.Checked:
close()getandsetclose(), never taking the new path, or deleting unreadable entries by a key that matches nothing each makes tests fail.bluecheck,doc8,flake8,isortcheck,mypyandpylintpass.