on
Memgraph graph storage
A look at Memgraph graph storage
Storage
Storage
is the main container of a graph. It can store data in memory or on disk.
Unique or shared data access is handled through the Accessor
class, which provides iterators to Vertex
and Edge
.
It also holds name to ID translation information for edges, verteces, labels and properties.
In addtion, it has functions to create or drop indeces.
Delta and Transaction
The Delta
and Transaction
class as used to keep track of modifications to the data.
Small vector
The small_vector
is a replacement for std::vector
and has 16 bytes overhead instead of the 24 required by std::vector
.
NameIdMapper
To facilitate named objects, the NAmeIdMapper
offers a std::string_view
to uint64_t
id translation. The translation data is stored in two SkipList
for accelerated access, one for name -> id and one for id -> name. An atomic counter variable is used to handle concurrent write access.
Vertex
Verteces as referenced by Gid
and hold incoming and outgoing edges in a small_vector
.
Each vertex has a PropertyStore
to store properties and a mutable RWSpinLock
to allow concurrent access.
Edge
Edges as referenced by Gid
and hold almost nothing.
Each edge has a PropertyStore
to store properties and a mutable RWSpinLock
to allow concurrent access.
An Edge
can be connected to a Vertex
by using the EdgeMetadata
struct. This holds a raw pointer to a Vertex
and a Gid
.
EdgeReg
A struct holding a Gid
and a raw pointer to the Edge
.
ModifiedEdgeInfo
Not sure what this does, but it holds Gid
s of a source and destination vertex, an edge type id and an EdgeRef
.
Property store
The property store uses a custom allocator code to store data in the class’ buffer_
variable. Lots of memmoves.
Property value
A property value can store NUll, Bool, Int, Double, TemporalData, ZonedTemporalData, Enum, String, List and Map.
The type of data stored in a value is kept in an enum
rather than a std::variant
or similar C++ standard type.
Each type has a ValueXXX()
getter function that throws an exception if the type held is not convertible.
A boost::flat map
is used to hold maps.
SkipList
Memgraph has its own thread-safe SkipList
implementation to accelerate lookups.
RWSpinLock
A spin lock that waits for all readers to leave before letting a writer access a resource. New readers are held back until a writer gets access to avoid starvation.
SpinLock
Memgraph has its own read-write spinlock implementation based on the pthreads spinlock. The spinlock is a light-weight locking mechanism that doesn’t make any kernel calls.
- https://stackoverflow.com/questions/26583433/c11-implementation-of-spinlock-using-atomic/29195378#29195378
- https://software.intel.com/en-us/node/524249
Other classes
Other interesting classes to look at are:
- utils::ThreadPool
- utils:OnScopeEXit