197
snapshotted. To avoid snapshotting unnecessary data, for example,
if the key is immutable, we split keys and values into separate
vectors. This also helps in the case of updating several values in
one transaction. Recall the discussion in the “Copy-on-Write and
Versioning” section. The result could turn out to be next to each other
in a vector, and there could be fewer bigger regions to snapshot.
• Line 74: Calculate hash in a table using standard library feature.
• Lines 76-79: Search for entry with specified key by iterating over
all buckets stored in the table under index. Note that e is a const
reference to the key-value pair. Because of the way libpmemobj-cpp
containers work, this has a positive impact on performance when
compared to non-const reference; obtaining non-const reference
requires a snapshot, while a const reference does not.
• Line 90: Get the instance of the pmemobj pool object, which is used to
manage the persistent memory pool where our data structure resides.
• Lines 94-95: Find the position of a value in the values vector by
iterating over all the entries in the designated bucket.
• Lines 96-98: If an element with the specified key is found, update its
value using a transaction.
• Lines 106-109: If there is no element with the specified key, insert a
value into the values vector, and put a reference to this value in the
proper bucket; that is, create key, index pair. Those two operations
must be completed in a single atomic transaction because we want
them both to either succeed or fail.
Hash Table with Transactions and Selective Persistence
This example shows how to modify a persistent data structure (hash table) by moving
some data out of persistent memory. The data structure presented in Listing 11-5 is
a modified version of the hash table in Listing 11-4 and contains the implementation
of this hash table design. Here we store only the vector of keys and vector of values in
persistent memory. On application startup, we build the buckets and store them in
volatile memory for faster processing during runtime. The most noticeable performance
gain would be in the get() method.
Chapter 11 Designing Data struCtures for persistent MeMory
snapshotted. To avoid snapshotting unnecessary data, for example,
if the key is immutable, we split keys and values into separate
vectors. This also helps in the case of updating several values in
one transaction. Recall the discussion in the “Copy-on-Write and
Versioning” section. The result could turn out to be next to each other
in a vector, and there could be fewer bigger regions to snapshot.
• Line 74: Calculate hash in a table using standard library feature.
• Lines 76-79: Search for entry with specified key by iterating over
all buckets stored in the table under index. Note that e is a const
reference to the key-value pair. Because of the way libpmemobj-cpp
containers work, this has a positive impact on performance when
compared to non-const reference; obtaining non-const reference
requires a snapshot, while a const reference does not.
• Line 90: Get the instance of the pmemobj pool object, which is used to
manage the persistent memory pool where our data structure resides.
• Lines 94-95: Find the position of a value in the values vector by
iterating over all the entries in the designated bucket.
• Lines 96-98: If an element with the specified key is found, update its
value using a transaction.
• Lines 106-109: If there is no element with the specified key, insert a
value into the values vector, and put a reference to this value in the
proper bucket; that is, create key, index pair. Those two operations
must be completed in a single atomic transaction because we want
them both to either succeed or fail.
Hash Table with Transactions and Selective Persistence
This example shows how to modify a persistent data structure (hash table) by moving
some data out of persistent memory. The data structure presented in Listing 11-5 is
a modified version of the hash table in Listing 11-4 and contains the implementation
of this hash table design. Here we store only the vector of keys and vector of values in
persistent memory. On application startup, we build the buckets and store them in
volatile memory for faster processing during runtime. The most noticeable performance
gain would be in the get() method.
Chapter 11 Designing Data struCtures for persistent MeMory
