OHC Caching in Java
To minimize lock contention, OHC splits the entire cache into 'segments' so that only if two entries hash to the same segment must one operation wait for the other. This is something like table-level locking in a relational database.
- The meaning of
cpus
is clear enough. - Default
segmentCount
is the smallest power of2
larger than twice the CPU count. For the logic of doubling the CPU count for throughput optimization, see for example https://stackoverflow.com/a/4771384. -
capacity
is the total storable data size in the cache. The default is 16MB per core. This is probably designed to correspond with CPU cache sizes, though presumably a user would have an idea of their application's actual capacity needs and would very likely be configuring this value and not using the default anyway.
The actual roundUpToPowerOf2
can be explained as follows:
Do not go above max
, nor below 1
. (I suppose it's up to the caller to assure that max is itelf a power of two or, it's ok for it not to be in this case.) In betweeen: To get a power of two, we want an int
comprised of a single one bit (or all zeros). Integer#highestOneBit
gives such a number with the turned on bit being the leftmost turned on bit in its argument. So we need to provide it with a number with whose leftmost turned on bit is:
- the same as
number
if it is already a power of two, or - one position to the left of
number
's leftmost one bit.
Calculating number - 1
before left shifting is for the first case. If number
is a power of two, then left shifting as-is would give us the next power of two, which isn't what we want. For the second case, the number
(or it's value subtracted by 1
) left shifted turns on the next larger bit, then Integer#highestOneBit
effectively blanks out all of the bits to the right.