Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updates with memory segment structure

...

Page content is stored in RAM in segments. Actually memory region allocated in RAM is not continious sequence of pages. 

 Ignite uses a special component that manages information about pages currently available in memory segment (LoadedPagesTable, ex FullPageIdTable) and ID mapping to region address. There is one page ID table per memory segment chunk (UnsafeChunk, DirectMemoryRegion). For unsafe segment chunk sun.misc.Unsafe is used internally, which provides memory for off-heap data storage.

LoadedPagesTable (PageIdTable) manages mapping from Page ID to relative pointer map (rowAddr) within unsafe segment chunk.

Each segment manages it's own lock. Lock protects segment content (page table) from concurrent modification.  By default segment count is determined by available CPUs, but may be configured by DataStorageConfiguration.setConcurrencyLevel().

Splitting each data region (DataRegionConfiguration) to a number of segments allows to minimise contention on one lock for region (striping technique is used). By default segment count is determined by available CPUs, but may be configured by DataStorageConfiguration.setConcurrencyLevel().

  • Read lock is held to segment to resolve real unmanaged memory address from page ID (page pin, acquire).
  • Read lock is held to release previously acquired page.
  • Write lock is held if segment pages are being modified (e.g. page is rotated from RAM to disk, or new page is allocated).

Structure of segments and Loaded Pages Map is shown at fugure:

Gliffy Diagram
size600
namesegmentsAndPageTable

Since Ignite version 2.5 Loaded Pages Id Table uses Robin Hood hashing: backward shift deletion algorithm for maintatining HashMap of FullPageId (CacheId, PageId)->(Address, PartGeneration).

To select approrpiate segment Ignite hashes Full Page Id, and (hash % segmentNo) gives the number.

In segment in LoadedPagesTable Ignite also hashes FullPageId to select approptiate bucket in the table.

In case of hash collision inside LoadedPagesTable lineral probe is used to find page by ID. If empty bucket is found, search is finished: page is not present in RAM.


Page itself also has its own lock. This lock may be acquired only for page available in RAM and only for pinned (acquired) page.

Since Ignite version 2.5 there are two optimizations introduced. Segment write lock

  1. is not held during initial page loading from disk
  2. and it is not held during actual page write to disk.

For read case segment lock is relased, but page write lock is acquired instead, so user thread will wait on page lock instead of segment lock during page is loaded. This decreases contention on segment lock during long running IO operation. Segment lock is hold for short time to acquire page and insert it into table, but released before IO.

In case of flusing dirty page (see section page replacement below) there is additional synchronized map of pages being written to disk, so page read can't be started for such pages until removal from this map. This map is usually not big and most likely page is not there.

Eviction, rotation and expiration

...