org.eclipse.jgit.internal.storage.file.Pack in
memory for faster read access.
The WindowCache serves as a Java based "buffer cache", loading segments of a PackFile into the JVM heap prior to use. As JGit often wants to do reads of only tiny slices of a file, the WindowCache tries to smooth out these tiny reads into larger block-sized IO operations.
Whenever a cache miss occurs, load(Pack, long) is invoked by
exactly one thread for the given (PackFile,position) key tuple.
This is ensured by an array of locks, with the tuple hashed to a lock
instance.
During a miss, older entries are evicted from the cache so long as
isFull() returns true.
Its too expensive during object access to be 100% accurate with a least recently used (LRU) algorithm. Strictly ordering every read is a lot of overhead that typically doesn't yield a corresponding benefit to the application.
This cache implements a loose LRU policy by randomly picking a window comprised of roughly 10% of the cache, and evicting the oldest accessed entry within that window.
Entities created by the cache are held under SoftReferences if option
core.packedGitUseStrongRefs is set to false in the git config
(this is the default) or by calling
WindowCacheConfig#setPackedGitUseStrongRefs(boolean), permitting the
Java runtime's garbage collector to evict entries when heap memory gets low.
Most JREs implement a loose least recently used algorithm for this eviction.
When this option is set to true strong references are used which
means that Java gc cannot evict the WindowCache to reclaim memory. On the
other hand this provides more predictable performance since the cache isn't
flushed when used heap comes close to the maximum heap size.
The internal hash table does not expand at runtime, instead it is fixed in size at cache creation time. The internal lock table used to gate load invocations is also fixed in size.
The key tuple is passed through to methods as a pair of parameters rather than as a single Object, thus reducing the transient memory allocations of callers. It is more efficient to avoid the allocation, as we can't be 100% sure that a JIT would be able to stack-allocate a key tuple.
This cache has an implementation rule such that:
load(Pack, long) is invoked by at most one thread at a time
for a given (PackFile,position) tuple.load() invocation there is exactly one
createRef(Pack, long, ByteWindow) invocation to wrap a
SoftReference or a StrongReference around the cached entity.createRef() there will be
exactly one call to clear(PageRef) to cleanup any resources associated
with the (now expired) cached entity.
Therefore, it is safe to perform resource accounting increments during the
load(Pack, long) or
createRef(Pack, long, ByteWindow) methods, and matching
decrements during clear(PageRef). Implementors may need to override
createRef(Pack, long, ByteWindow) in order to embed additional
accounting information into an implementation specific
org. subclass, as
the cached entity may have already been evicted by the JRE's garbage
collector.
To maintain higher concurrency workloads, during eviction only one thread performs the eviction work, while other threads can continue to insert new objects in parallel. This means that the cache can be temporarily over limit, especially if the nominated eviction thread is being starved relative to the other threads.
| Modifier and Type | Class and Description |
|---|---|
| private static interface | |
| private static class | |
| private static class | |
| private static interface | |
| private static class | |
| private static class | WindowCache.
A soft reference wrapped around a cached object. |
| pack-priv static interface | WindowCache.
Record statistics for a cache |
| pack-priv static class | |
| private static class | |
| private static class | WindowCache.
A strong reference wrapped around a cached object. |
| Modifier and Type | Field and Description |
|---|---|
| private int | |
| private static volatile WindowCache | |
| private final AtomicLong | clock
Access clock for loose LRU. |
| private final int | evictBatch
Number of |
| private final ReentrantLock | evictLock
Lock to elect the eviction thread after a load occurs. |
| private final int | idealNumRemovers
Removers are purely CPU/mem bound (no I/O), so likely should not go above # CPUs |
| private final WindowCache. | locks
Locks to prevent concurrent loads for same (PackFile,position). |
| private final long | |
| private final int | |
| private final WindowCache. | |
| private final boolean | |
| private final int | numRemovalBlocks
Number of blocks to split the Pack removal into. |
| private int | |
| private Set | |
| private Set | |
| private final AtomicBoolean | |
| private final WindowCache. | queue
cleanup released and/or garbage collected windows. |
| private final int | |
| private static final Random | |
| private final WindowCache. | |
| private static volatile int | |
| private final AtomicReferenceArray | table
Hash bucket directory; entries are chained below. |
| private final int | |
| private final boolean | |
| private final boolean | |
| private final int | |
| private final int |
| Access | Constructor and Description |
|---|---|
| private |
| Modifier and Type | Method and Description |
|---|---|
| private static final int | |
| private static WindowCache. | |
| private void | |
| private void | |
| private WindowCache. | |
| private void | |
| private void | |
| pack-priv static final ByteWindow | |
| public static WindowCache | |
| private ByteWindow | |
| public WindowCacheStats | |
| pack-priv static int | |
| private int | |
| private void | |
| private boolean | |
| pack-priv boolean | |
| private ByteWindow | |
| private WindowCache. | |
| private static int | |
| private WindowCache | |
| pack-priv static final void | |
| pack-priv static final void | |
| private void | queueRemoveAll(Set<Pack>
the files to purge all entries of packs)Asynchronously clear all entries related to files. |
| public static void | reconfigure(WindowCacheConfig
the new window cache configuration. cfg)
Deprecated
use
cfg.install() to avoid internal reference.
Modify the configuration of the window cache. |
| private void | |
| private void | removeBlock(Set<Pack>
the files to purge all entries of packs, int the specific block to process removals for block)Remove a block of entries for a Set of files |
| private boolean | Returns: whether more processing should be done by the current threadthe number of already processed block removals by the current thread numRemoved)Determine which block to remove next, if any, and do so. |
| public void | |
| private ByteWindow | |
| private int | |
| private static int | |
| private long |