Original article: http://www.darkbull.net/
In recent projects, a large number of Boost: shared_ptr has been used. On the game server, sometimes the same data block is sent to different connections (for example, a walking message package of Player A is sent to all nearby players ), if you copy a copy of data for each connection, the cost is relatively high and it is difficult to maintain, think about the data block to be released after sending the data, it is easy to error, and the performance is not good. With smart pointers, you only need to copy one data block and do not need to manage the memory release. But over the past few days, I have been thinking that boost: shared_ptr claims to be thread-safe, so when maintaining the reference count of objects at the lower layer, it must be cumbersome. If you frequently copy smart pointers, performance overhead cannot be ignored. I am not very familiar with the boost thread library. I checked it online and it seems that shared_ptr is through boost. the mutex object of thread is used to protect the reference count. If so, I infer that shared_ptr is used in windows, and the performance is certainly not high. Based on this speculation, I wrote some simple smart pointers and maintained the intelligent pointer reference count through the windows API interlocked series functions. The Code is as follows:
# Ifndef autoptr_h_0000ded # define autoptr_h_0000ded # include <windows. h> template <typename T> class autoptr {public: autoptr (void): _ PTR (0), _ refcount (0) {} explicit autoptr (T * PTR ): _ PTR (PTR) {_ refcount = new long (1);} autoptr (const autoptr & RHs): _ PTR (RHS. _ PTR), _ refcount (RHS. _ refcount) {If (_ PTR & _ refcount): interlockedincrement (_ refcount); // Add 1 to reference count }~ Autoptr (void) {If (! _ PTR) return; long refcount =: interlockedexchangeadd (_ refcount,-1); If (refcount = 1) {Delete _ refcount; Delete _ PTR ;}} T & operator * (void) {return * _ PTR;} const T & operator * (void) const {return * _ PTR;} t * operator-> (void) {return _ PTR;} const T * operator-> (void) const {return _ PTR;} const autoptr & operator = (const autoptr & RHs ); // T * Get (void) // {// return _ PTR; //} // const T * Get (void) const // {// return _ PTR; //} // T * release (void) // {//} // void reset (T * PTR) // {//} PRIVATE: T * _ PTR; long * _ refcount;}; Template <typename T> const autoptr <t> & autoptr <t>: Operator = (const autoptr & RHs) {If (_ PTR) {long refcount =: interlockedexchangeadd (_ refcount,-1); If (refcount = 1) {Delete _ refcount; Delete _ PTR; }}_ PTR = RHS. _ PTR; _ refcount = RHS. _ refcount; If (_ refcount): interlockedincrement (_ refcount); return * This ;}# endif // autoptr_h_included
A simple test program is written to compare the self-written autoptr, boost: shared_ptr, STD: tr1: shared_ptr. The test code is as follows:
int main(int argc, char *argv[]){AutoPtr<int> intPtr1(new int(0)); time_t beg1 = clock(); for (int i = 0; i < 10000000; ++i) { AutoPtr<int> tmp = intPtr1; ++(*tmp); } time_t end1 = clock();std::cout << "AutoPtr cost: " << end1 - beg1 << ", Result: " << *intPtr1 << std::endl;boost::shared_ptr<int> intPtr2(new int(0));time_t beg2 = clock();for (int i = 0; i < 10000000; ++i){ boost::shared_ptr<int> tmp = intPtr2; ++(*tmp);}time_t end2 = clock();std::cout << "boost::shared_ptr cost:" << end2 - beg2 << ", Result: " << *intPtr2 << std::endl;std::tr1::shared_ptr<int> intPtr3(new int(0));time_t beg3 = clock();for (int i = 0; i < 10000000; ++i){std::tr1::shared_ptr<int> tmp = intPtr3; ++(*tmp);}time_t end3 = clock();std::cout << "std::tr1::shared_ptr cost:" << end3 - beg3 << ", Result: " << *intPtr3 << std::endl;return 0;}
The results are beyond my expectation:
The result in vc9 is:
Result In gcc4.4.2:
The results show that the performance of Boost:; shared_ptr is not as bad as I think. In vc9, the performance of the three smart pointers is at the same level. In gcc4.4.2, boost :: shared_ptr has similar performance with autoptr, but it is an order of magnitude different from shared_ptr of tr1.