Performance loss from extensive use of shared_ptr as if C++ being garbage-collected? -


i wondering performance issues of reference counted shared_ptrs, , wrote dumb program computes pow(2, n) in inefficient way millions of memory allocations , deallocations, in order test shared_ptrs while not making compiler optimize away, full optimization.

compiled with,

g++ t.cpp -std=c++11 -ot -dv_ -pedantic -ofast -s -fwhole-program 

where -dv_ means use std::vector container.

ran as,

valgrind ./t 10000 

which means compute pow(2, 10000) shows me,

total heap usage: 45,174,051 allocs, 45,174,051 frees, 783,160,061 bytes allocated 

and

time ./t 10000 

outputs

real    0m1.698s user    0m1.693s sys     0m0.004s 

which surprisingly fast, considering amount of heap allocation done. system laptop i5 cpu , ubuntu linux os.

the basic pattern used here defining container classes extending shared_ptr original class.

#if defined(v_)     #define c_ std::vector #elif defined(l_)     #define c_ std::list #elif defined(d_)     #define c_ std::deque #else     #error #endif  template<typename t> class container : public std::shared_ptr<c_<t>> { public:     container():         std::shared_ptr<c_<t>>(new c_<t>)     {     } };  class string : public std::shared_ptr<std::string> { public:     string():         std::shared_ptr<std::string>(new std::string)     {     }     string(const char* s):         std::shared_ptr<std::string>(new std::string(s))     {     }     const char* getcstring()     {         return get()->c_str();     } }; 

this way not have worry @ whether pass value or reference, const reference, rvalue reference et cetera. passing value works fine , cheap. should pointer copy , reference count update. can add few deep copy methods needed, can see deep copy happening in program. letting whole vector being value copied because of missed reference mark not happen. i'd situations deep copies of large objects necessary not common.

well, benefits obvious. in other words, either java or c# offer better productivity c++. there must performance loss. in user applications loss can literally nothing, writing games, must finish computing every frame in 30ms or so. can't write games real garbage collected languages, java example, because see game pausing unexpectedly short noticeable moment , restoring back. feels not right. reference counted (pseudo-)garbage collection, point resources claimed or released quite guaranteed.

so thinking start project use pattern base, don't have experience in using reference counted pointers big-enough projects. in experimenting phase. using shared_ptrs in time critical programs not idea, , no 1 knows impact after project gets big enough, point impossible change deep inside , used everywhere. (i worried part). or overly undervaluing greatness of modern computing machines?

do have or bad experience dealing smart pointers? these work fine multiple threads? how can compiler optimizations on them? modern hardware deal reference counting operations well? other helpful facts reference counted pointers?



below can see whole test program, if you're interested.

#include <cstdlib> #include <cmath> #include <iostream> #include <vector> #include <list> #include <deque> #include <queue> #include <memory>  #if defined(v_)     #define c_ std::vector #elif defined(l_)     #define c_ std::list #elif defined(d_)     #define c_ std::deque #else     #error #endif  void check(bool isokay) {     if (!isokay)     {         std::exit(exit_failure);     } }  template<typename t> class container : public std::shared_ptr<c_<t>> { public:     container():         std::shared_ptr<c_<t>>(new c_<t>)     {     } };  class string : public std::shared_ptr<std::string> { public:     string():         std::shared_ptr<std::string>(new std::string)     {     }     string(const char* s):         std::shared_ptr<std::string>(new std::string(s))     {     }     const char* getcstring() const     {         return get()->c_str();     } };  class slowinteger : public container<int> { public:     slowinteger()     {     }     slowinteger(int n)     {         check(0 <= n && n < 20);         if (n < 10)         {             get()->push_back(n);         }         else         {             get()->push_back(n - 10);             get()->push_back(1);         }     }     int toint() const     {         if (get()->size() == 1)         {             return get()->front();         }         else         {             return get()->front() + 10 * get()->back();         }     } };  class veryslowinteger : public container<slowinteger> { public:     veryslowinteger(string stringnumber)     {         (auto = stringnumber->rbegin(); != stringnumber->rend(); ++it)         {             get()->push_back(slowinteger(*it - '0'));         }     }     void x2()     {         int m = 0;         (auto = get()->begin(); != get()->end(); ++it)         {             int n = it->toint() * 2;             if (n < 10)             {                 *it = slowinteger(m + n);                 m = 0;             }             else             {                 *it = slowinteger(n - 10 + m);                 m = 1;             }         }         if (m == 1)         {             get()->push_back(slowinteger(1));         }     }     void x2n(int n)     {         check(n > 0);         (int = 0; < n; ++i)         {             x2();         }     }     string tostring()     {         string s;         (auto = get()->rbegin(); != get()->rend(); ++it)         {             s->push_back(it->toint() + '0');         }         return s;     } };  int main(int argc, char **argv) {     check(argc == 2);     int n = std::atoi(argv[1]);     check(n > 0);     veryslowinteger nslow("1");     nslow.x2n(n);     string s = nslow.tostring();     std::cout << s.getcstring() << std::endl;     return exit_success; } 


Popular posts from this blog

c# - ODP.NET Oracle.ManagedDataAccess causes ORA-12537 network session end of file -

matlab - Compression and Decompression of ECG Signal using HUFFMAN ALGORITHM -

utf 8 - split utf-8 string into bytes in python -