Is there any speed test between "std :: map with mutexes" and "libcds maps" (Michael Hashmap and Split Order List) "parallel insert, search, erase?

So, I really would like to see parallel parallel speed testing (something like 100 to 10,000 parallel threads), where each thread inserts, finds, deletes at least 3 types of parallel cards - std :: map (with some mutexes) vs libcds (parallel data structures) ...

So, for example, if such a comparison does not yet exist, please help me create it.

Directly linked: LibCds: Michael Hashmap and Split order list

Let's pretend that

#include <iostream> #include <boost/thread.hpp> #include <map> class TestDs { public: virtual bool containsKey(int key)=0; virtual int get(int key)=0; virtual int put(int key, int value)=0; virtual int remove(int key)=0; virtual int size()=0; virtual const char* name()=0; virtual void print()=0; virtual void shutdown()=0; }; class GeneralMap: public TestDs { private: std::map<int,int> _ds; mutable boost::mutex mut_; public: GeneralMap() {} bool containsKey(int key) { boost::mutex::scoped_lock lock(mut_); if ( _ds.find(key) != _ds.end()) { return true; } else { return false; } } int get(int key) { boost::mutex::scoped_lock lock(mut_); return _ds[key]; } int put(int key, int value) { boost::mutex::scoped_lock lock(mut_); _ds.insert(std::pair<int, int>(key,value)); return key; } int remove(int key) { boost::mutex::scoped_lock lock(mut_); return _ds.erase(key); } int size() { boost::mutex::scoped_lock lock(mut_); return _ds.size(); } const char* name() { return "StdMap"; } void print() {} void shutdown() {} }; 

than creating a test that would create N threads, and each thread would call create, find delete ... I started to write something, but now it compiles code with boost 1.47.0 ...

 #include <iostream> #include <boost/thread.hpp> #include <map> #include <boost/thread.hpp> #include <boost/thread/locks.hpp> #include <boost/date_time.hpp> #include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int_distribution.hpp> #include <boost/random.hpp> #include <boost/progress.hpp> class timer { public: timer() : start_time_(boost::posix_time::microsec_clock::local_time()) {} void restart() { start_time_ = boost::posix_time::microsec_clock::local_time(); } boost::posix_time::time_duration elapsed() const { return boost::posix_time::microsec_clock::local_time() - start_time_; } private: boost::posix_time::ptime start_time_; }; class TestDs { public: virtual bool containsKey(int key)=0; virtual int get(int key)=0; virtual int put(int key, int value)=0; virtual int remove(int key)=0; virtual int size()=0; virtual const char* name()=0; virtual void print()=0; virtual void shutdown()=0; }; class GeneralMap: public TestDs { private: std::map<int,int> _ds; mutable boost::mutex mut_; public: GeneralMap() {} bool containsKey(int key) { boost::mutex::scoped_lock lock(mut_); if ( _ds.find(key) != _ds.end()) { return true; } else { return false; } } int get(int key) { boost::mutex::scoped_lock lock(mut_); return _ds[key]; } int put(int key, int value) { boost::mutex::scoped_lock lock(mut_); _ds.insert(std::pair<int, int>(key,value)); return key; } int remove(int key) { boost::mutex::scoped_lock lock(mut_); return _ds.erase(key); } int size() { boost::mutex::scoped_lock lock(mut_); return _ds.size(); } const char* name() { return "StdMap"; } void print() {} void shutdown() {} }; template <class map_wraper_t> class test_map_wraper { public: test_map_wraper(int threads_number) { n = threads_number; } void start_tests() { boost::upgrade_lock<boost::shared_mutex> lock(tests); boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock); boost::shared_lock<boost::shared_mutex> lock_r(results); for(int i=0; i<n; i++) { boost::thread worker(&test_map_wraper::test, this, i); } boost::thread worker_r(&test_map_wraper::result, this); timerForCaptureFame.restart(); } private: int n; boost::shared_mutex tests; boost::shared_mutex results; boost::random::mt19937 rng; timer timerForCaptureFame; map_wraper_t Ds; boost::progress_display *show_progress; void test( int i) { boost::shared_lock<boost::shared_mutex> lock_r(results); boost::shared_lock<boost::shared_mutex> lock(tests); Ds.put(i, 0); if (Ds.containsKey(i)) { Ds.get(i); } Ds.remove(i); } void result() { boost::upgrade_lock<boost::shared_mutex> lock(results); boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock); std::cout << std::endl << "test of " << Ds.name() << " complite;" << std::endl << "test performed on " << n << " items" << std::endl << "test duration: " << timerForCaptureFame.elapsed() << std::endl; } }; int main() { int threads_n = 1000; int tests = 5; std::cout << "Number of required tests: " << tests << std::endl << "Number of threads in each test: " << threads_n << std::endl << "Wait for it..." << std::endl; //for(int i = 0; i < tests; ++i) //{ test_map_wraper<GeneralMap> GeneralMapTest(threads_n); GeneralMapTest.start_tests(); //} std::cin.get(); return 0; } 
+4
source share
1 answer

Yes, this is in unit tests for LibCds

It will run the same test scripts with all kinds of different types of cards, including your blocking implementations, but also std :: map / set with and without blocking.

Of course, no synchronization is clearly a winner, but it will not work when there are writers in the mix. Non-blocking implementations come out much faster than STL containers with synchronized access.

All this should not be a surprise. Why are you asking?

PS. unit test:

  • get tar ball
  • extract
  • build ( cd build && ./build.sh )
  • unit tests in ./bin/*/cds-unit or ./bin/*/cds-unit-debug if they are built using --debug-test
+3
source

Source: https://habr.com/ru/post/1369310/


All Articles