You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@geode.apache.org by GitBox <gi...@apache.org> on 2020/06/09 16:25:12 UTC

[GitHub] [geode-native] albertogpz commented on a change in pull request #611: GEODE-8213: lock-free SerializationRegistry

albertogpz commented on a change in pull request #611:
URL: https://github.com/apache/geode-native/pull/611#discussion_r436629331



##########
File path: cppcache/src/SerializationRegistry.cpp
##########
@@ -355,45 +363,39 @@ std::shared_ptr<Serializable> SerializationRegistry::GetEnum(
 }
 
 void TheTypeMap::clear() {
-  std::lock_guard<util::concurrent::spinlock_mutex> guard(
-      m_dataSerializableMapLock);
-  m_dataSerializableMap.clear();
+  auto tempDataSerializableMap =
+      std::make_shared<std::unordered_map<int32_t, TypeFactoryMethod>>();
+  std::atomic_store(&m_dataSerializableMap, tempDataSerializableMap);
 
-  std::lock_guard<util::concurrent::spinlock_mutex> guard2(
-      m_dataSerializableFixedIdMapLock);
-  m_dataSerializableFixedIdMap.clear();
+  auto tempDataSerializableFixedId = std::make_shared<
+      std::unordered_map<internal::DSFid, TypeFactoryMethod>>();
+  std::atomic_store(&m_dataSerializableFixedIdMap, tempDataSerializableFixedId);
 
-  std::lock_guard<util::concurrent::spinlock_mutex> guard3(
-      m_pdxSerializableMapLock);
-  m_pdxSerializableMap.clear();
+  auto tempPdxSerializableMap =
+      std::make_shared<std::unordered_map<std::string, TypeFactoryMethodPdx>>();
+  std::atomic_store(&m_pdxSerializableMap, tempPdxSerializableMap);
 }
 
 void TheTypeMap::findDataSerializable(int32_t id,
                                       TypeFactoryMethod& func) const {
-  std::lock_guard<util::concurrent::spinlock_mutex> guard(
-      m_dataSerializableMapLock);
-  const auto& found = m_dataSerializableMap.find(id);
-  if (found != m_dataSerializableMap.end()) {
+  const auto& found = m_dataSerializableMap->find(id);
+  if (found != m_dataSerializableMap->end()) {

Review comment:
       You are right

##########
File path: cppcache/src/SerializationRegistry.cpp
##########
@@ -409,44 +411,56 @@ void TheTypeMap::bindDataSerializable(TypeFactoryMethod func, int32_t id) {
         "TheTypeMap::bind: Serialization type not implemented.");
   }
 
-  std::lock_guard<util::concurrent::spinlock_mutex> guard(
-      m_dataSerializableMapLock);
-  const auto& result = m_dataSerializableMap.emplace(id, func);
+  auto tempDataSerializableMap =
+      std::make_shared<std::unordered_map<int32_t, TypeFactoryMethod>>(
+          *m_dataSerializableMap);
+  const auto& result = tempDataSerializableMap->emplace(id, func);
   if (!result.second) {
     LOGERROR("A class with ID %d is already registered.", id);
     throw IllegalStateException("A class with given ID is already registered.");
   }
+  std::atomic_store(&m_dataSerializableMap, tempDataSerializableMap);

Review comment:
       I was assuming that the map would only be updated from one thread. Is it reasonable?
   If several threads could update the map then I do not see how we could make this work consistently and being thread safe.
   In your draft code using compare_and_exchange you need to clone the map and I think that should be done atomically. Otherwise, the data could be modified by another thread in the mean time. To do it atomically we would need blocking
   Besides, to use compare_and_exchange on the map we would need it to be atomic. We could change the type from shared_ptr to a raw pointer but in that case the memory management would not be obvious at all. How could we know when you could free the memory map after exchanging the pointer? It might be that some other thread is using that memory at the same time and we would get a segmentation violation.
   Please, let me know if I am missing anything.
   Otherwise, I think it would be better to go for a solution based on shared locks.

##########
File path: cppcache/src/SerializationRegistry.cpp
##########
@@ -409,44 +411,56 @@ void TheTypeMap::bindDataSerializable(TypeFactoryMethod func, int32_t id) {
         "TheTypeMap::bind: Serialization type not implemented.");
   }
 
-  std::lock_guard<util::concurrent::spinlock_mutex> guard(
-      m_dataSerializableMapLock);
-  const auto& result = m_dataSerializableMap.emplace(id, func);
+  auto tempDataSerializableMap =
+      std::make_shared<std::unordered_map<int32_t, TypeFactoryMethod>>(
+          *m_dataSerializableMap);
+  const auto& result = tempDataSerializableMap->emplace(id, func);
   if (!result.second) {
     LOGERROR("A class with ID %d is already registered.", id);
     throw IllegalStateException("A class with given ID is already registered.");
   }
+  std::atomic_store(&m_dataSerializableMap, tempDataSerializableMap);

Review comment:
       I changed the implementation to boost::shared_mutex and the performance measured by the benchmark introduced was way worse than with the spinlock. I had read that the implementation of the boost::shared_lock was suboptimal on Linux.
   These are the figures:
   
   Benchmark                                                                                    Time             CPU      Time Old      Time New       CPU Old       CPU New
   -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:1                 +1.0440         +1.0438           213           435           213           434
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:2                 +0.9090         +0.9091           156           297           312           595
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:4                 +1.0325         +1.0136            65           132           254           512
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:8                 +0.7878         +0.7826            43            78           348           620
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:16                +0.9026         +1.0066            31            59           357           717
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:32                +0.9935         +0.9967            28            57           365           729
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:64                +1.0535         +1.0519            26            54           358           735
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:96                +1.1182         +1.0243            25            52           360           729
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:1                   +0.7410         +0.7410           231           403           231           403
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:2                   +1.4190         +1.3271           114           276           228           531
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:4                   +0.9838         +0.9709            59           116           234           462
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:8                   +0.9452         +0.9369            42            82           335           649
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:16                  +1.0843         +0.9737            30            62           368           725
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:32                  +1.0204         +1.0018            28            57           367           735
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:64                  +0.9670         +0.9939            28            55           368           734
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:96                  +0.8644         +1.0207            29            54           362           732
   SerializationRegistryBM_findDataSerializable/real_time/threads:1                          +0.9817         +0.9817           211           418           211           418
   SerializationRegistryBM_findDataSerializable/real_time/threads:2                          +0.3399         +0.3401           157           211           314           421
   SerializationRegistryBM_findDataSerializable/real_time/threads:4                          +1.2335         +1.2339            59           133           237           530
   SerializationRegistryBM_findDataSerializable/real_time/threads:8                          +0.9273         +0.9344            42            81           335           648
   SerializationRegistryBM_findDataSerializable/real_time/threads:16                         +1.1570         +1.0856            29            63           360           750
   SerializationRegistryBM_findDataSerializable/real_time/threads:32                         +1.2448         +1.0935            28            62           364           762
   SerializationRegistryBM_findDataSerializable/real_time/threads:64                         +1.0317         +1.0715            27            56           363           752
   SerializationRegistryBM_findDataSerializable/real_time/threads:96                         +1.0391         +1.0796            26            54           361           751
   SerializationRegistryBM_findPdxSerializable/real_time/threads:1                           +0.8144         +0.8144           234           425           234           425
   SerializationRegistryBM_findPdxSerializable/real_time/threads:2                           +0.4180         +0.4181           154           218           308           436
   SerializationRegistryBM_findPdxSerializable/real_time/threads:4                           +0.6402         +0.6284            73           120           293           476
   SerializationRegistryBM_findPdxSerializable/real_time/threads:8                           +1.3334         +1.3390            39            90           307           717
   SerializationRegistryBM_findPdxSerializable/real_time/threads:16                          +0.9053         +0.9381            34            65           407           789
   SerializationRegistryBM_findPdxSerializable/real_time/threads:32                          +1.0597         +0.9980            31            64           414           828
   SerializationRegistryBM_findPdxSerializable/real_time/threads:64                          +0.9588         +0.9441            32            63           413           803
   SerializationRegistryBM_findPdxSerializable/real_time/threads:96                          +0.7951         +0.9451            32            57           411           800
   
   I tried with C++14 std::shared_timed_mutex and the performance was better in most cases although the improvement was not spectacular:
   Benchmark                                                                                    Time             CPU      Time Old      Time New       CPU Old       CPU New
   -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:1                 -0.0320         -0.0320           213           206           213           206
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:2                 -0.2957         -0.2957           156           110           312           219
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:4                 -0.1130         -0.0923            65            58           254           231
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:8                 -0.0796         -0.0811            43            40           348           319
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:16                -0.0082         +0.0533            31            31           357           376
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:32                +0.0372         +0.0424            28            30           365           381
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:64                +0.0669         +0.0692            26            28           358           383
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:96                +0.1285         +0.0457            25            28           360           377
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:1                   -0.0929         -0.0929           231           210           231           210
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:2                   -0.0190         -0.0191           114           112           228           224
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:4                   -0.0091         -0.0092            59            58           234           232
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:8                   -0.1483         -0.1501            42            36           335           285
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:16                  +0.0480         +0.0159            30            31           368           373
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:32                  +0.0776         +0.0321            28            30           367           379
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:64                  +0.0035         +0.0254            28            28           368           378
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:96                  +0.0029         +0.0447            29            29           362           378
   SerializationRegistryBM_findDataSerializable/real_time/threads:1                          +0.0412         +0.0412           211           219           211           219
   SerializationRegistryBM_findDataSerializable/real_time/threads:2                          -0.3122         -0.3121           157           108           314           216
   SerializationRegistryBM_findDataSerializable/real_time/threads:4                          -0.0301         -0.0299            59            58           237           230
   SerializationRegistryBM_findDataSerializable/real_time/threads:8                          -0.0128         -0.0112            42            42           335           331
   SerializationRegistryBM_findDataSerializable/real_time/threads:16                         +0.0404         +0.0318            29            30           360           371
   SerializationRegistryBM_findDataSerializable/real_time/threads:32                         -0.0093         +0.0292            28            27           364           374
   SerializationRegistryBM_findDataSerializable/real_time/threads:64                         -0.0119         +0.0465            27            27           363           380
   SerializationRegistryBM_findDataSerializable/real_time/threads:96                         -0.0511         +0.0467            26            25           361           378
   SerializationRegistryBM_findPdxSerializable/real_time/threads:1                           -0.0410         -0.0410           234           225           234           225
   SerializationRegistryBM_findPdxSerializable/real_time/threads:2                           -0.2185         -0.2185           154           120           308           240
   SerializationRegistryBM_findPdxSerializable/real_time/threads:4                           -0.1662         -0.1662            73            61           293           244
   SerializationRegistryBM_findPdxSerializable/real_time/threads:8                           +0.0004         -0.0001            39            39           307           306
   SerializationRegistryBM_findPdxSerializable/real_time/threads:16                          -0.0075         +0.0106            34            34           407           412
   SerializationRegistryBM_findPdxSerializable/real_time/threads:32                          +0.0701         +0.0034            31            33           414           416
   SerializationRegistryBM_findPdxSerializable/real_time/threads:64                          -0.0072         +0.0068            32            32           413           416
   SerializationRegistryBM_findPdxSerializable/real_time/threads:96                          -0.0614         +0.0182            32            30           411           419
   
   As a result, I do not see the point in changing the implementation until Geode is upgraded to a later C++ version. Do you know if there are plans for it?
   
   I think at least we should leave the benchmark tests for future improvements.

##########
File path: cppcache/src/SerializationRegistry.cpp
##########
@@ -409,44 +411,56 @@ void TheTypeMap::bindDataSerializable(TypeFactoryMethod func, int32_t id) {
         "TheTypeMap::bind: Serialization type not implemented.");
   }
 
-  std::lock_guard<util::concurrent::spinlock_mutex> guard(
-      m_dataSerializableMapLock);
-  const auto& result = m_dataSerializableMap.emplace(id, func);
+  auto tempDataSerializableMap =
+      std::make_shared<std::unordered_map<int32_t, TypeFactoryMethod>>(
+          *m_dataSerializableMap);
+  const auto& result = tempDataSerializableMap->emplace(id, func);
   if (!result.second) {
     LOGERROR("A class with ID %d is already registered.", id);
     throw IllegalStateException("A class with given ID is already registered.");
   }
+  std::atomic_store(&m_dataSerializableMap, tempDataSerializableMap);

Review comment:
       I changed the implementation to boost::shared_mutex and the performance measured by the benchmark introduced was way worse than with the spinlock. I had read that the implementation of the boost::shared_lock was suboptimal on Linux.
   These are the figures:
   
   Benchmark                                                                                    Time             CPU      Time Old      Time New       CPU Old       CPU New
   -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:1                 +1.0440         +1.0438           213           435           213           434
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:2                 +0.9090         +0.9091           156           297           312           595
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:4                 +1.0325         +1.0136            65           132           254           512
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:8                 +0.7878         +0.7826            43            78           348           620
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:16                +0.9026         +1.0066            31            59           357           717
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:32                +0.9935         +0.9967            28            57           365           729
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:64                +1.0535         +1.0519            26            54           358           735
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:96                +1.1182         +1.0243            25            52           360           729
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:1                   +0.7410         +0.7410           231           403           231           403
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:2                   +1.4190         +1.3271           114           276           228           531
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:4                   +0.9838         +0.9709            59           116           234           462
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:8                   +0.9452         +0.9369            42            82           335           649
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:16                  +1.0843         +0.9737            30            62           368           725
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:32                  +1.0204         +1.0018            28            57           367           735
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:64                  +0.9670         +0.9939            28            55           368           734
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:96                  +0.8644         +1.0207            29            54           362           732
   SerializationRegistryBM_findDataSerializable/real_time/threads:1                          +0.9817         +0.9817           211           418           211           418
   SerializationRegistryBM_findDataSerializable/real_time/threads:2                          +0.3399         +0.3401           157           211           314           421
   SerializationRegistryBM_findDataSerializable/real_time/threads:4                          +1.2335         +1.2339            59           133           237           530
   SerializationRegistryBM_findDataSerializable/real_time/threads:8                          +0.9273         +0.9344            42            81           335           648
   SerializationRegistryBM_findDataSerializable/real_time/threads:16                         +1.1570         +1.0856            29            63           360           750
   SerializationRegistryBM_findDataSerializable/real_time/threads:32                         +1.2448         +1.0935            28            62           364           762
   SerializationRegistryBM_findDataSerializable/real_time/threads:64                         +1.0317         +1.0715            27            56           363           752
   SerializationRegistryBM_findDataSerializable/real_time/threads:96                         +1.0391         +1.0796            26            54           361           751
   SerializationRegistryBM_findPdxSerializable/real_time/threads:1                           +0.8144         +0.8144           234           425           234           425
   SerializationRegistryBM_findPdxSerializable/real_time/threads:2                           +0.4180         +0.4181           154           218           308           436
   SerializationRegistryBM_findPdxSerializable/real_time/threads:4                           +0.6402         +0.6284            73           120           293           476
   SerializationRegistryBM_findPdxSerializable/real_time/threads:8                           +1.3334         +1.3390            39            90           307           717
   SerializationRegistryBM_findPdxSerializable/real_time/threads:16                          +0.9053         +0.9381            34            65           407           789
   SerializationRegistryBM_findPdxSerializable/real_time/threads:32                          +1.0597         +0.9980            31            64           414           828
   SerializationRegistryBM_findPdxSerializable/real_time/threads:64                          +0.9588         +0.9441            32            63           413           803
   SerializationRegistryBM_findPdxSerializable/real_time/threads:96                          +0.7951         +0.9451            32            57           411           800
   
   I tried with C++14 std::shared_timed_mutex and the performance was better in most cases although the improvement was not spectacular:
   
   Benchmark                                                                                    Time             CPU      Time Old      Time New       CPU Old       CPU New
   -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:1                 -0.0320         -0.0320           213           206           213           206
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:2                 -0.2957         -0.2957           156           110           312           219
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:4                 -0.1130         -0.0923            65            58           254           231
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:8                 -0.0796         -0.0811            43            40           348           319
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:16                -0.0082         +0.0533            31            31           357           376
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:32                +0.0372         +0.0424            28            30           365           381
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:64                +0.0669         +0.0692            26            28           358           383
   SerializationRegistryBM_findDataSerializablePrimitive/real_time/threads:96                +0.1285         +0.0457            25            28           360           377
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:1                   -0.0929         -0.0929           231           210           231           210
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:2                   -0.0190         -0.0191           114           112           228           224
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:4                   -0.0091         -0.0092            59            58           234           232
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:8                   -0.1483         -0.1501            42            36           335           285
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:16                  +0.0480         +0.0159            30            31           368           373
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:32                  +0.0776         +0.0321            28            30           367           379
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:64                  +0.0035         +0.0254            28            28           368           378
   SerializationRegistryBM_findDataSerializableFixedId/real_time/threads:96                  +0.0029         +0.0447            29            29           362           378
   SerializationRegistryBM_findDataSerializable/real_time/threads:1                          +0.0412         +0.0412           211           219           211           219
   SerializationRegistryBM_findDataSerializable/real_time/threads:2                          -0.3122         -0.3121           157           108           314           216
   SerializationRegistryBM_findDataSerializable/real_time/threads:4                          -0.0301         -0.0299            59            58           237           230
   SerializationRegistryBM_findDataSerializable/real_time/threads:8                          -0.0128         -0.0112            42            42           335           331
   SerializationRegistryBM_findDataSerializable/real_time/threads:16                         +0.0404         +0.0318            29            30           360           371
   SerializationRegistryBM_findDataSerializable/real_time/threads:32                         -0.0093         +0.0292            28            27           364           374
   SerializationRegistryBM_findDataSerializable/real_time/threads:64                         -0.0119         +0.0465            27            27           363           380
   SerializationRegistryBM_findDataSerializable/real_time/threads:96                         -0.0511         +0.0467            26            25           361           378
   SerializationRegistryBM_findPdxSerializable/real_time/threads:1                           -0.0410         -0.0410           234           225           234           225
   SerializationRegistryBM_findPdxSerializable/real_time/threads:2                           -0.2185         -0.2185           154           120           308           240
   SerializationRegistryBM_findPdxSerializable/real_time/threads:4                           -0.1662         -0.1662            73            61           293           244
   SerializationRegistryBM_findPdxSerializable/real_time/threads:8                           +0.0004         -0.0001            39            39           307           306
   SerializationRegistryBM_findPdxSerializable/real_time/threads:16                          -0.0075         +0.0106            34            34           407           412
   SerializationRegistryBM_findPdxSerializable/real_time/threads:32                          +0.0701         +0.0034            31            33           414           416
   SerializationRegistryBM_findPdxSerializable/real_time/threads:64                          -0.0072         +0.0068            32            32           413           416
   SerializationRegistryBM_findPdxSerializable/real_time/threads:96                          -0.0614         +0.0182            32            30           411           419
   
   As a result, I do not see the point in changing the implementation until Geode is upgraded to a later C++ version. Do you know if there are plans for it?
   
   I think at least we should leave the benchmark tests for future improvements.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org