diff --git a/CHANGELOG.md b/CHANGELOG.md index 61ba1f8..baf5bd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ diskcache-community forked from DiskCache at upstream commit ebfa37c (3 March 20 ### Fixes +- `Cache.get` is as fast on a hit as in 5.6.3 again; since 5.7.0 it was about 5% slower (PR #35). - A float NaN stored as a value is kept, on every disk. It was written to SQLite, which stores NaN as NULL, so it read back as `None`. It is now stored as a pickle, which 5.6.3 reads too (PR #34). - `memoize_stampede` works with `SafeDisk`: the key of its early recomputation marker held the internal `ENOVAL` constant, which `SafeDisk` refuses, so a call raised `TypeError` once a cached value neared expiry (PR #32). diff --git a/diskcache_community/core.py b/diskcache_community/core.py index e1b7944..6887497 100644 --- a/diskcache_community/core.py +++ b/diskcache_community/core.py @@ -2617,6 +2617,9 @@ def get( :raises Timeout: if database timeout occurs """ + # Kept in one function: a helper call costs a measurable share of a + # cache hit. + # pylint: disable=too-many-branches,too-many-statements db_key, raw = self._disk.put(key) update_column = EVICTION_POLICY[self.eviction_policy]['get'] statistics = self.statistics @@ -2626,13 +2629,24 @@ def get( # the path that does not write. update_column = None statistics = False - select = ( - 'SELECT rowid, expire_time, tag, mode, filename, value, store_time' - ' FROM Cache WHERE key = ? AND raw = ?' - ' AND (expire_time IS NULL OR expire_time > ?)' - ) + # Select store_time only when asked: each extra column costs a + # measurable share of a cache hit. + if store_time: + select = ( + 'SELECT rowid, expire_time, tag, mode, filename, value,' + ' store_time FROM Cache WHERE key = ? AND raw = ?' + ' AND (expire_time IS NULL OR expire_time > ?)' + ) + else: + select = ( + 'SELECT rowid, expire_time, tag, mode, filename, value' + ' FROM Cache WHERE key = ? AND raw = ?' + ' AND (expire_time IS NULL OR expire_time > ?)' + ) - default = _meta_result(default, expire_time, tag, store_time) + meta_wanted = expire_time or tag or store_time + if meta_wanted: + default = _meta_result(default, expire_time, tag, store_time) if not statistics and update_column is None: # Fast path, no transaction necessary. @@ -2642,17 +2656,23 @@ def get( if not rows: return default - ( + if store_time: ( - rowid, - db_expire_time, - db_tag, - mode, - filename, - db_value, - db_store_time, - ), - ) = rows + ( + rowid, + db_expire_time, + db_tag, + mode, + filename, + db_value, + db_store_time, + ), + ) = rows + else: + ( + (rowid, db_expire_time, db_tag, mode, filename, db_value), + ) = rows + db_store_time = None try: value = self._disk.fetch(mode, filename, db_value, read) @@ -2681,17 +2701,30 @@ def get( sql(cache_miss) return default - ( + if store_time: ( - rowid, - db_expire_time, - db_tag, - mode, - filename, - db_value, - db_store_time, - ), - ) = rows + ( + rowid, + db_expire_time, + db_tag, + mode, + filename, + db_value, + db_store_time, + ), + ) = rows + else: + ( + ( + rowid, + db_expire_time, + db_tag, + mode, + filename, + db_value, + ), + ) = rows + db_store_time = None try: value = self._disk.fetch(mode, filename, db_value, read) @@ -2719,6 +2752,8 @@ def get( if update_column is not None: sql(update % update_column.format(now=now), (rowid,)) + if not meta_wanted: + return value meta = (db_expire_time, db_tag, db_store_time) return _meta_result(value, expire_time, tag, store_time, meta)