Header of a persisted Chronicle Map store is written once, when the instance and the file are
created, and never changed after that. It is stored in Text Wire Format
).
The top-level structure name is !net.openhft.chronicle.map.VanillaChronicleMap. It contains the
following fields:
A String containing the version of the reference Java implementation, e. g. "3.5.0-beta".
The Class of the Chronicle Map's keys, e. g. !type int32 (corresponds to java.lang.Integer).
The marshaller for the Chronicle Map's key sizes, an instance of
net.openhft.chronicle.hash.serialization.SizeMarshaller, e. g.
!net.openhft.chronicle.hash.serialization.impl.ConstantSizeMarshaller {
constantSize: 4
}The reference Java implementation itself defines and uses only two types of size marshallers:
ConstantSizeMarshaller(see above), that consumes 0 bytes to "read" and "write" some constant size, andStopBitSizeMarshaller, that uses stop bit encoding to read and write sizes.
The reader for the Chronicle Map's keys, an instance of
net.openhft.chronicle.hash.serialization.SizedReader, e. g.
!net.openhft.chronicle.hash.serialization.impl.IntegerMarshaller {
}The data access strategy for the Chronicle Map's keys, an instance of
net.openhft.chronicle.hash.serialization.DataAccess, e. g.
!net.openhft.chronicle.hash.serialization.impl.NotReusingSizedMarshallableDataAccess {
tClass: !type int32,
sizedReader: !net.openhft.chronicle.hash.serialization.impl.IntegerMarshaller {
},
sizedWriter: !net.openhft.chronicle.hash.serialization.impl.IntegerMarshaller {
}
}A flag denoting if checksums are computed and stored for the Chronicle Map's entries along with
them. A boolean value, true or false.
In the reference Java implementation, the default value is
truefor persisted Chronicle Maps, checksums are computed and stored.
The number of segments in this Chronicle Map. A positive signed
32-bit value, e. g. 16.
The algorithm for choosing both the segment for a key based on it's 64-bit hash code, and
the data to play the role of key in the segment tier's hash lookups. An instance of net.openhft.chronicle.hash.impl.HashSplitting,
e. g.
!net.openhft.chronicle.hash.impl.HashSplitting$ForPowerOf2Segments {
bits: 4
}The reference Java implementation defines and uses three types of hash splitting algorithms:
net.openhft.chronicle.hash.impl.HashSplitting$ForPowerOf2Segments, used when theactualSegmentsvalue is a power of 2 (except 1). Lowest bits of keys' hash codes (specified by thebitsfield) are used to choose the segment, highest 64 −bitsare used as keys in segment tier's hash lookups.net.openhft.chronicle.hash.impl.HashSplitting$ForSingleSegmentis an optimized version ofHashSplitting$ForPowerOf2Segments, for the case of the single segment in the Chronicle Map (actualSegmentsequals to 1). The "chosen" segment index is 0, and entire key's hash codes are used as key in segment tier's hash lookups.net.openhft.chronicle.hash.impl.HashSplitting$ForNonPowerOf2Segments, used when theactualSegmentsis not a power of 2. It has a fieldsegments, that has the same value, asactualSegmentsin the higher-level Chronicle Map configuration. The segment index is determined assegmentIndex = (keyHashCode & 0x7FFFFFFF) % segments, and the highest 33 bits of keys' hash codes are used as keys in segment tier's hash lookups.
The size in bytes of the allocation unit (chunk) of the segment tier's entry space. A positive 64-bit value, e. g. 4.
Unless both keys and values are constant sized, the reference Java implementation by default chooses a chunk size which is a power of 2, so that an average-sized entry spans from 4 to 8 chunks.
The maximum number of chunks a single entry could span. A positive signed 32-bit value, with upper
bound of the actualChunksPerSegmentTier value, e. g. 3303.
#####actualChunksPerSegmentTier
The size of the segment tier's entry space area, in chunks. A positive 64-bit value, e. g. 3303.
The number of bytes between starts of the segment headers. A 32-bit value, greater or equal to 32,
e. g. 192.
Segment headers take only 32 bytes, the rest space between segment headers is alignment aimed to reduce false sharing. The maximum reasonable
segmentHeaderSizevalue for modern Intel CPUs is 192, 3 cache lines. CPUs prefetch cache lines in both directions from the accessed one, containing the segment header.
The number of bits of the tier hash lookup's slots, used to store the index of the first chunk
allocated for the Chronicle Map's entry. A 32-bit value in [1, 63] range, e. g. 12.
In the reference Java implementation the number of value bits is as little as enough to encode any chunk index, i. e. log(2, nextPowerOf2(
actualChunksPerSegmentTier))
The number of bits of the tier hash lookup's slots, used to store parts of the Chronicle Map key's
hash codes, playing the role of key in hash lookup tables. The part of hash codes is extracted by
the hashSplitting algorithm. A 32-bit value is [1, 63] range, e. g. 20.
The size of the tier hash lookup's slots, in bytes. A 32-bit value, 4 or 8. Invariant:
tierHashLookupKeyBits + tierHashLookupValueBits = tierHashLookupSlotSize * 8.
The number of slots in the hash lookups. A positive 64-bit value, a power of 2, e. g. 2048.
The maximum number of entries, allowed to be stored in a segment tier, i. e. number of slots taken
in a hash lookup. A positive 64-bit value, e. g. 1638.
In the reference Java implementation,
maxEntriesPerHashLookupis chosen astierHashLookupCapacity* 0.8. When linear-probing hash table's load factor exceeds 0.8, chain lengths become unreasonably long.
The size of hash lookups in bytes. A positive 64-bit value, equals to tierHashLookupInnerSize
* tierHashLookupSlotSize. A positive
64-bit value, e. g. 8192.
The size of hash lookups + alignment, in bytes. A positive 64-bit value, e. g. 8192.
In the reference Java implementation,
tierHashLookupOuterSizeequals to thetierHashLookupInnerSizevalue, rounded up to the next multiple of 64 (i. e. a cache line boundary).
The size segment tiers' free lists (indexes of free chunks in entry spaces), in bytes. A positive
64-bit value, e. g. 416.
In the reference Java implementation,
tierFreeListInnerSizeequals to theactualChunksPerSegmentTiervalue, rounded up to the next multiple of 64, then divided by 8, i. e. the dimension of this value is bytes, and it is a multiple of 8.
The size of free lists + alignment, in bytes. A positive 64-bit value, e. g. 448.
In the reference Java implementation,
tierFreeListOuterSizeequals to thetierFreeListInnerSizevalue, rounded up to the next multiple of 64 (i. e. a cache line boundary).
The size of segment tiers' entry spaces, in bytes. A positive 64-bit value, e. g. 13212.
The offset in entry spaces from the start to the offset of the first chunk. A non-negative 32-bit
value, e. g. 0.
This offset is non-zero, when both keys and values are constant sized, and the value size is not a multiple of the
alignment, then the first chunk of the entry space is misaligned in order to make all entries take the same number of bytes.
The size of segment tiers' entry spaces + alignment, in bytes. A positive 64-bit value, e. g.
13248.
In the reference Java implementation,
tierEntrySpaceOuterSizeequals to thetierEntrySpaceInnerSizevalue, rounded up to the next multiple of 64 (i. e. a cache line boundary).
The size of segment tiers in this Chronicle Map, in bytes. A positive 64-bit value, e. g. 21952.
In the reference Java implementation,
tierSizeequals totierHashLookupOuterSize+ 64 (tier counters area size) +tierFreeListOuterSize+tierEntrySpaceOuterSize+ (optionally) 64. ThetierSizeis a multiple of 64 (i. e. it spans integral number of cache lines). The optional extra cache line is added, when thetierSizeis too round, and there are too many segments, in order to break collisions of tiers' start addresses by L1 cache banks. See e. g. this post for more information on this effect.
The maximum number of extra tiers could be allocated, before the Chronicle Map is full and rejects
new insertion requests. A non-negative 64-bit value, e. g. 16.
In the reference Java implementation,
maxExtraTiersdefaults to theactualSegments. I. e. the Chronicle Map could nearly double the expected size, before it throwsIllegalStateExceptionsupon new insertion requests.
The size in bytes of a tier bulk, a unit of memory allocation, when extra tiers are needed. A
positive 64-bit value, e. g. 43904.
In the reference Java implementation,
tierBulkSizeInBytesequals totierBulkInnerOffsetToTiers+tiersInBulk*tierSize.
The offset from tier bulks' starts to the address of the first tier within a bulk, in bytes. This
space is used as metadata of a tier bulk. A non-negative 64-bit value, e. g. 0.
The number of tiers in the tier bulks. A positive 64-bit value, e. g. 2.
The value of this field equals to log(2, tiersInBulk).
The Class of the Chronicle Map's values, e. g. !type CharSequence.
The marshaller for the Chronicle Map's value sizes, an instance of
net.openhft.chronicle.hash.serialization.SizeMarshaller, e. g.
!net.openhft.chronicle.hash.serialization.impl.StopBitSizeMarshaller {
}See the comments on
keySizeMarshallerfor information about this field.
The reader for the Chronicle Map's values, an instance of
net.openhft.chronicle.hash.serialization.SizedReader, e. g.
!net.openhft.chronicle.hash.serialization.impl.CharSequenceSizedReader {
}The data access strategy for the Chronicle Map's values, an instance of
net.openhft.chronicle.hash.serialization.DataAccess, e. g.
!net.openhft.chronicle.hash.serialization.impl.SizedMarshallableDataAccess {
tClass: !type CharSequence,
sizedReader: !net.openhft.chronicle.hash.serialization.impl.CharSequenceSizedReader {
},
sizedWriter: !net.openhft.chronicle.hash.serialization.impl.CharSequenceSizedWriter {
}
}A flag denoting if both keys and values of the Chronicle Map are constant sized. A boolean value,
true or false.
The alignment (in bytes) of the values of this Chronicle Maps, by addresses, when residing the entry
spaces. A positive, 32-bit, power of 2 value, e. g. 1.
The most bytes could theoretically be wasted on the value alignment. The value
alignment waste might vary, if the chunkSize is not a multiple of
alignment, and/or due to amount of memory before value in the stored entry
structure might vary.
A non-negative 32-bit value, e. g. 0.
The described fields are defined in
VanillaChronicleHashandVanillaChronicleMap.