Top Description Inners Fields Constructors Methods
org.eclipse.jgit.internal.storage.file

public Class WindowCache

extends Object
Class Inheritance
Imports
java.io.IOException, java.lang.ref.ReferenceQueue, .SoftReference, java.util.Collections, .HashSet, .Map, .Random, .Set, java.util.concurrent.ConcurrentHashMap, .ConcurrentLinkedQueue, java.util.concurrent.atomic.AtomicBoolean, .AtomicLong, .AtomicReferenceArray, .LongAdder, java.util.concurrent.locks.ReentrantLock, java.util.stream.Collectors, org.eclipse.jgit.annotations.NonNull, org.eclipse.jgit.internal.JGitText, org.eclipse.jgit.storage.file.WindowCacheConfig, .WindowCacheStats, org.eclipse.jgit.util.Monitoring

Caches slices of a 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:

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.eclipse.jgit.internal.storage.file.WindowCache.PageRef 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.

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static interface
private static class
private static class
private static interface
private static class
private static class
WindowCache.SoftRef

A soft reference wrapped around a cached object.

pack-priv static interface
WindowCache.StatsRecorder

Record statistics for a cache

pack-priv static class
private static class
private static class
WindowCache.StrongRef

A strong reference wrapped around a cached object.

Field Summary

Modifier and TypeField and Description
private int
private static volatile WindowCache
private final AtomicLong
clock

Access clock for loose LRU.

private final int
evictBatch

Number of table buckets to scan for an eviction window.

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.Lock[]
locks

Locks to prevent concurrent loads for same (PackFile,position).

private final long
private final int
private final WindowCache.StatsRecorderImpl
private final boolean
private final int
numRemovalBlocks

Number of blocks to split the Pack removal into.

private int
private Set<Pack>
private Set<Pack>
private final AtomicBoolean
private final WindowCache.CleanupQueue
queue

cleanup released and/or garbage collected windows.

private final int
private static final Random
private final WindowCache.StatsRecorder
private static volatile int
private final AtomicReferenceArray<WindowCache.Entry>
table

Hash bucket directory; entries are chained below.

private final int
tableSize

Number of entries in table.

private final boolean
private final boolean
private final int
private final int

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
private static final int
bits(int newSize)

private static WindowCache.Entry
private void
private void
close(Pack pack)

private WindowCache.PageRef<ByteWindow>
createRef(Pack p, long o, ByteWindow v)

private void
private void
gc()

pack-priv static final ByteWindow
get(Pack pack, long offset)

public static WindowCache

Returns:

the cached instance.
getInstance
()

Get singleton instance

private ByteWindow

Returns:

the object reference.
getOrLoad
(Pack
the pack that "contains" the cached object.
pack
,
long
offset within pack of the object.
position
)

Lookup a cached object, creating and loading it if it doesn't exist.

public WindowCacheStats

Returns:

cache statistics for the WindowCache
getStats
()

Get cache statistics

pack-priv static int
private int
hash(int packHash, long off)

private void
private boolean
pack-priv boolean
private ByteWindow
load(Pack pack, long offset)

private WindowCache.Lock
lock(Pack pack, long position)

private static int
private WindowCache
pack-priv static final void
purge(Pack pack)

pack-priv static final void
purge(Set<Pack> packs)

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
removeAll()

Clear every entry from the cache.

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 thread
removeNextBlock
(int
the number of already processed block removals by the current thread
numRemoved
)

Determine which block to remove next, if any, and do so.

public void
resetStats()

Reset stats.

private ByteWindow
scan(WindowCache.Entry n, Pack pack, long position)

private int
slot(Pack pack, long position)

private static int
private long
toStart(long offset)

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait