Postpone call to get() when loading from the in-memory cache

Caffeine's get() method relies on the `ConcurrentHashMap.compute()`
java11 implementation, which locks concurrent access in [1].

The effect of this on cache-chroniclemap is that when multiple threads
try to access the in-memory cache concurrently, they result in being
BLOCKED, as documented by the `ConcurrentHashMap.compute()` method:

Some attempted update operations on this map by other threads
may be blocked while computation is in progress, so the
computation should be short and simple, and must not attempt to
update any other mappings of this Map.

This, in turn, causes high consumption of Gerrit threads, which might
eventually, make it unresponsive.

Workaround this problem by first trying to get the key _if present_ and
only calling get() in case no value could be loaded.

This works because getIfPresent(), as opposed to, get(), does not try to
`compute` entries in the cache and thus decreases the chances of threads
blocking in case of cache hits.


Bug: Issue 15645
Change-Id: I7021d93d4011e252c5c022ffcd3eecee22820ff5
1 file changed
tree: 12167625a01aa15062b991c503eff4a15502591a
  1. src/
  2. .gitignore
  3. BUILD
  4. external_plugin_deps.bzl
  5. Jenkinsfile

Persistent cache for Gerrit, based on ChronicleMap

Non-blocking and super-fast on-disk cache libModule for Gerrit Code Review based on ChronicleMap on-disk implementation.

How to build

This libModule is built like a Gerrit in-tree plugin, using Bazelisk. See the build instructions for more details.


  • Install cache-chronicalmap module

Install the chronicle-map module into the $GERRIT_SITE/lib directory.

Add the cache-chroniclemap module to $GERRIT_SITE/etc/gerrit.config as follows:

  installModule = com.googlesource.gerrit.modules.cache.chroniclemap.ChronicleMapCacheModule

For further information and supported options, refer to config documentation.

Migration from H2 caches

You can check how to migrate from H2 to chronicle-map here.