Added HP/DHP internal stats to test
authorkhizmax <libcds.dev@gmail.com>
Sat, 21 Jan 2017 08:19:41 +0000 (11:19 +0300)
committerkhizmax <libcds.dev@gmail.com>
Sat, 21 Jan 2017 08:19:41 +0000 (11:19 +0300)
cds/gc/dhp.h
cds/gc/hp.h
projects/Win/vc14/cds.sln
src/hp.cpp
test/include/cds_test/stat_dhp_out.h [new file with mode: 0644]
test/include/cds_test/stat_hp_out.h [new file with mode: 0644]
test/include/cds_test/stress_test.h
test/stress/framework/stress_test.cpp
test/stress/main.cpp

index d06bbed..7651179 100644 (file)
@@ -470,16 +470,16 @@ namespace cds { namespace gc {
             thread_hp_storage   hazards_;   ///< Hazard pointers private to the thread
             retired_array       retired_;   ///< Retired data private to the thread
 
+            char pad1_[cds::c_nCacheLineSize];
+            atomics::atomic<unsigned int> sync_; ///< dummy var to introduce synchronizes-with relationship between threads
+            char pad2_[cds::c_nCacheLineSize];
+
 #       ifdef CDS_ENABLE_HPSTAT
             size_t              free_call_count_;
             size_t              scan_call_count_;
             size_t              help_scan_call_count_;
 #       endif
 
-            char pad1_[cds::c_nCacheLineSize];
-            atomics::atomic<unsigned int> sync_; ///< dummy var to introduce synchronizes-with relationship between threads
-            char pad2_[cds::c_nCacheLineSize];
-
             // CppCheck warn: pad1_ and pad2_ is uninitialized in ctor
             // cppcheck-suppress uninitMemberVar
             thread_data( guard* guards, size_t guard_count )
@@ -504,7 +504,7 @@ namespace cds { namespace gc {
         //@endcond
 
         //@cond
-        // Dynmic (adaptive) Hazard Pointer SMR (Safe Memory Reclamation)
+        // Dynamic (adaptive) Hazard Pointer SMR (Safe Memory Reclamation)
         class smr
         {
             struct thread_record;
index 42c64f0..76df614 100644 (file)
@@ -349,18 +349,28 @@ namespace cds { namespace gc {
             thread_hp_storage   hazards_;   ///< Hazard pointers private to the thread
             retired_array       retired_;   ///< Retired data private to the thread
 
-            stat                stat_;      ///< Internal statistics for the thread
-
             char pad1_[cds::c_nCacheLineSize];
             atomics::atomic<unsigned int> sync_; ///< dummy var to introduce synchronizes-with relationship between threads
             char pad2_[cds::c_nCacheLineSize];
 
+#       ifdef CDS_ENABLE_HPSTAT
+            // Internal statistics:
+            size_t              free_count_;
+            size_t              scan_count_;
+            size_t              help_scan_count_;
+#       endif
+
             // CppCheck warn: pad1_ and pad2_ is uninitialized in ctor
             // cppcheck-suppress uninitMemberVar
             thread_data( guard* guards, size_t guard_count, retired_ptr* retired_arr, size_t retired_capacity )
                 : hazards_( guards, guard_count )
                 , retired_( retired_arr, retired_capacity )
                 , sync_(0)
+#       ifdef CDS_ENABLE_HPSTAT
+                , free_count_(0)
+                , scan_count_(0)
+                , help_scan_count_(0)
+#       endif
             {}
 
             thread_data() = delete;
index d18e78f..d420364 100644 (file)
@@ -22,9 +22,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cds_test", "cds_test", "{3A
                ..\..\..\test\include\cds_test\hash_func.h = ..\..\..\test\include\cds_test\hash_func.h\r
                ..\..\..\test\include\cds_test\stat_bronson_avltree_out.h = ..\..\..\test\include\cds_test\stat_bronson_avltree_out.h\r
                ..\..\..\test\include\cds_test\stat_cuckoo_out.h = ..\..\..\test\include\cds_test\stat_cuckoo_out.h\r
+               ..\..\..\test\include\cds_test\stat_dhp_out.h = ..\..\..\test\include\cds_test\stat_dhp_out.h\r
                ..\..\..\test\include\cds_test\stat_ellenbintree_out.h = ..\..\..\test\include\cds_test\stat_ellenbintree_out.h\r
                ..\..\..\test\include\cds_test\stat_feldman_hashset_out.h = ..\..\..\test\include\cds_test\stat_feldman_hashset_out.h\r
                ..\..\..\test\include\cds_test\stat_flat_combining_out.h = ..\..\..\test\include\cds_test\stat_flat_combining_out.h\r
+               ..\..\..\test\include\cds_test\stat_hp_out.h = ..\..\..\test\include\cds_test\stat_hp_out.h\r
                ..\..\..\test\include\cds_test\stat_iterable_list_out.h = ..\..\..\test\include\cds_test\stat_iterable_list_out.h\r
                ..\..\..\test\include\cds_test\stat_lazy_list_out.h = ..\..\..\test\include\cds_test\stat_lazy_list_out.h\r
                ..\..\..\test\include\cds_test\stat_michael_list_out.h = ..\..\..\test\include\cds_test\stat_michael_list_out.h\r
index 8da02d1..50dd605 100644 (file)
@@ -318,7 +318,7 @@ namespace cds { namespace gc { namespace hp {
             }
         }
 
-        CDS_HPSTAT( ++pRec->stat_.scan_count );
+        CDS_HPSTAT( ++pRec->scan_count_ );
 
         // Sort retired pointer array
         std::sort( first_retired, last_retired, retired_ptr::less );
@@ -373,7 +373,7 @@ namespace cds { namespace gc { namespace hp {
                 else {
                     // Retired pointer may be freed
                     it->free();
-                    CDS_HPSTAT( ++pRec->stat_.free_count );
+                    CDS_HPSTAT( ++pRec->free_count_ );
                 }
             }
             const size_t nDeferred = insert_pos - first_retired;
@@ -386,7 +386,7 @@ namespace cds { namespace gc { namespace hp {
     {
         thread_record* pRec = static_cast<thread_record*>( pThreadRec );
 
-        CDS_HPSTAT( ++pRec->stat_.scan_count );
+        CDS_HPSTAT( ++pRec->scan_count_ );
 
         std::vector< void*, allocator<void*>>   plist;
         plist.reserve( get_max_thread_count() * get_hazard_ptr_count());
@@ -429,7 +429,7 @@ namespace cds { namespace gc { namespace hp {
                 }
                 else {
                     it->free();
-                    CDS_HPSTAT( ++pRec->stat_.free_count );
+                    CDS_HPSTAT( ++pRec->free_count_ );
                 }
             }
 
@@ -441,7 +441,7 @@ namespace cds { namespace gc { namespace hp {
     {
         assert( static_cast<thread_record*>( pThis )->m_idOwner.load( atomics::memory_order_relaxed ) == cds::OS::get_current_thread_id() );
 
-        CDS_HPSTAT( ++pThis->stat_.help_scan_count );
+        CDS_HPSTAT( ++pThis->help_scan_count_ );
 
         const cds::OS::ThreadId nullThreadId = cds::OS::c_NullThreadId;
         const cds::OS::ThreadId curThreadId = cds::OS::get_current_thread_id();
@@ -496,9 +496,9 @@ namespace cds { namespace gc { namespace hp {
             st.guard_allocated += hprec->hazards_.alloc_guard_count_;
             st.guard_freed     += hprec->hazards_.free_guard_count_;
             st.retired_count   += hprec->retired_.retire_call_count_;
-            st.free_count      += hprec->stat_.free_count;
-            st.scan_count      += hprec->stat_.scan_count;
-            st.help_scan_count += hprec->stat_.help_scan_count;
+            st.free_count      += hprec->free_count_;
+            st.scan_count      += hprec->scan_count_;
+            st.help_scan_count += hprec->help_scan_count_;
         }
 #   endif
     }
diff --git a/test/include/cds_test/stat_dhp_out.h b/test/include/cds_test/stat_dhp_out.h
new file mode 100644 (file)
index 0000000..ea4bd53
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+    Source code repo: http://github.com/khizmax/libcds/
+    Download: http://sourceforge.net/projects/libcds/files/
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSTEST_STAT_DHP_OUT_H
+#define CDSTEST_STAT_DHP_OUT_H
+
+#include <cds/gc/dhp.h>
+#include <ostream>
+
+namespace cds_test {
+
+    static inline property_stream& operator <<( property_stream& o, cds::gc::DHP::stat const& s )
+    {
+#ifdef CDS_ENABLE_HPSTAT
+#   define CDS_HPSTAT_OUT( stat, fld ) std::make_pair( "dhp_" + property_stream::stat_prefix() + "." #fld, stat.fld )
+        return o
+            << CDS_HPSTAT_OUT( s, guard_allocated )
+            << CDS_HPSTAT_OUT( s, guard_freed )
+            << CDS_HPSTAT_OUT( s, retired_count )
+            << CDS_HPSTAT_OUT( s, free_count )
+            << CDS_HPSTAT_OUT( s, scan_count )
+            << CDS_HPSTAT_OUT( s, help_scan_count )
+            << CDS_HPSTAT_OUT( s, thread_rec_count )
+            << CDS_HPSTAT_OUT( s, hp_block_count )
+            << CDS_HPSTAT_OUT( s, retired_block_count )
+            << CDS_HPSTAT_OUT( s, hp_extend_count )
+            << CDS_HPSTAT_OUT( s, retired_extend_count );
+#   undef CDS_HPSTAT_OUT
+#else
+        return o;
+#endif
+    }
+
+} // namespace cds_test
+
+static inline std::ostream& operator <<( std::ostream& o, cds::gc::DHP::stat const& s )
+{
+#ifdef CDS_ENABLE_HPSTAT
+#   define CDS_HPSTAT_OUT( stat, fld ) "\t" << #fld << "=" << stat.fld << "\n"
+    return o
+        << "DHP post-mortem statistics:\n"
+        << CDS_HPSTAT_OUT( s, guard_allocated )
+        << CDS_HPSTAT_OUT( s, guard_freed )
+        << CDS_HPSTAT_OUT( s, retired_count )
+        << CDS_HPSTAT_OUT( s, free_count )
+        << CDS_HPSTAT_OUT( s, scan_count )
+        << CDS_HPSTAT_OUT( s, help_scan_count )
+        << CDS_HPSTAT_OUT( s, thread_rec_count )
+        << CDS_HPSTAT_OUT( s, hp_block_count )
+        << CDS_HPSTAT_OUT( s, retired_block_count )
+        << CDS_HPSTAT_OUT( s, hp_extend_count )
+        << CDS_HPSTAT_OUT( s, retired_extend_count );
+#   undef CDS_HPSTAT_OUT
+#else
+    return o;
+#endif
+}
+
+
+#endif // #ifndef CDSTEST_STAT_DHP_OUT_H
diff --git a/test/include/cds_test/stat_hp_out.h b/test/include/cds_test/stat_hp_out.h
new file mode 100644 (file)
index 0000000..3a5d239
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+    Source code repo: http://github.com/khizmax/libcds/
+    Download: http://sourceforge.net/projects/libcds/files/
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSTEST_STAT_HP_OUT_H
+#define CDSTEST_STAT_HP_OUT_H
+
+#include <cds/gc/hp.h>
+#include <ostream>
+
+namespace cds_test {
+
+    static inline property_stream& operator <<( property_stream& o, cds::gc::HP::stat const& s )
+    {
+#ifdef CDS_ENABLE_HPSTAT
+#   define CDS_HPSTAT_OUT( stat, fld ) std::make_pair( "hp_" + property_stream::stat_prefix() + "." #fld, stat.fld )
+        return o
+            << CDS_HPSTAT_OUT( s, guard_allocated )
+            << CDS_HPSTAT_OUT( s, guard_freed )
+            << CDS_HPSTAT_OUT( s, retired_count )
+            << CDS_HPSTAT_OUT( s, free_count )
+            << CDS_HPSTAT_OUT( s, scan_count )
+            << CDS_HPSTAT_OUT( s, help_scan_count )
+            << CDS_HPSTAT_OUT( s, thread_rec_count );
+#   undef CDS_HPSTAT_OUT
+#else
+        return o;
+#endif
+    }
+
+} // namespace cds_test
+
+static inline std::ostream& operator <<( std::ostream& o, cds::gc::HP::stat const& s )
+{
+#ifdef CDS_ENABLE_HPSTAT
+#   define CDS_HPSTAT_OUT( stat, fld ) "\t" << #fld << "=" << stat.fld << "\n"
+    return o
+        << "HP post-mortem statistics:\n"
+        << CDS_HPSTAT_OUT( s, guard_allocated )
+        << CDS_HPSTAT_OUT( s, guard_freed )
+        << CDS_HPSTAT_OUT( s, retired_count )
+        << CDS_HPSTAT_OUT( s, free_count )
+        << CDS_HPSTAT_OUT( s, scan_count )
+        << CDS_HPSTAT_OUT( s, help_scan_count )
+        << CDS_HPSTAT_OUT( s, thread_rec_count );
+#   undef CDS_HPSTAT_OUT
+#else
+    return o;
+#endif
+}
+
+#endif // #ifndef CDSTEST_STAT_HP_OUT_H
index a739a4b..9e3053f 100644 (file)
@@ -172,6 +172,8 @@ namespace cds_test {
 
     class stress_fixture : public fixture
     {
+        typedef fixture base_class;
+
     protected:
         stress_fixture()
             : m_thread_pool( *this )
@@ -179,13 +181,18 @@ namespace cds_test {
 
         //static void SetUpTestCase();
         //static void TearDownTestCase();
+        void TearDown()
+        {
+            print_hp_stat();
+            base_class::TearDown();
+        }
 
         thread_pool& get_pool()
         {
             return m_thread_pool;
         }
 
-        static property_stream& propout();
+        static void print_hp_stat();
 
     public:
         static config const& get_config( char const * slot );
@@ -196,6 +203,8 @@ namespace cds_test {
         static void init_detail_level( int argc, char **argv );
         static bool check_detail_level( int nLevel );
 
+        static property_stream& propout();
+
     private:
         thread_pool     m_thread_pool;
     };
index 1497cc7..2cd19db 100644 (file)
 #include <iostream>\r
 #include <cds_test/stress_test.h>\r
 \r
+#ifdef CDS_ENABLE_HPSTAT\r
+#   include <cds_test/stat_hp_out.h>\r
+#   include <cds_test/stat_dhp_out.h>\r
+#endif\r
+\r
 namespace cds_test {\r
 \r
     static std::string s_stat_prefix( "stat" );\r
@@ -55,6 +60,23 @@ namespace cds_test {
         return s_prop_stream;\r
     }\r
 \r
+    /*static*/ void stress_fixture::print_hp_stat()\r
+    {\r
+#ifdef CDS_ENABLE_HPSTAT\r
+        {\r
+            cds::gc::HP::stat st;\r
+            cds::gc::HP::statistics( st );\r
+            propout() << st;\r
+        }\r
+        {\r
+            cds::gc::DHP::stat st;\r
+            cds::gc::DHP::statistics( st );\r
+            propout() << st;\r
+        }\r
+#endif\r
+    }\r
+\r
+\r
     /*static*/ std::vector<std::string> stress_fixture::load_dictionary()\r
     {\r
         std::vector<std::string> arrString;\r
index 0c7acd8..14eb93e 100644 (file)
 #   include <cds/urcu/signal_threaded.h>\r
 #endif\r
 \r
+#ifdef CDS_ENABLE_HPSTAT\r
+#   include <cds_test/stat_hp_out.h>\r
+#   include <cds_test/stat_dhp_out.h>\r
+#   include <iostream>\r
+#endif\r
+\r
 int main( int argc, char **argv )\r
 {\r
     int result;\r
@@ -97,6 +103,13 @@ int main( int argc, char **argv )
 \r
         cds::threading::Manager::detachThread();\r
     }\r
+\r
+#ifdef CDS_ENABLE_HPSTAT\r
+    std::cout << cds::gc::HP::postmortem_statistics();\r
+    std::cout << cds::gc::DHP::postmortem_statistics();\r
+#endif\r
+\r
     cds::Terminate();\r
+\r
     return result;\r
 }\r