Why std::make_shared<>() has much better perfor

2019-06-23 18:52发布

I have been doing some field performance test on

1>std::shared_ptr, std::make_shared based on 'gcc 4.7.2' & 'VC10 implementation' 
2>boost::shared_ptr, boost::make_shared based on boost 1.47

The test result is somewhat interesting.

1>In general std version performs better but especially std::make_shared. Why? Can I increase the boost version performance since C++ 11 is not available for some old project yet as they are using old version of Visual studio?

Below is my code snippet used to test those. NB. you need to manually switch between boost & std. NB. "SimpleMSTimer.hpp" is my timer wrapper for boost ptime, a bit too long to post here. But feel free to use your own timer.Any portable time would do.

#include "stdafx.h"
#include <vector>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost\make_shared.hpp>

#include "SimpleMSTimer.hpp"//my timer wrapper for boost ptime

using namespace std;
using namespace boost;

class Thing
{
public:
    Thing()
    {
    }

    void method (void)
    {
        int i = 5;
    }
};

typedef boost::shared_ptr<Thing> ThingPtr;

void processThing(Thing* thing)
{
    thing->method();
}

//loop1 and loop2 test shared_ptr in the vector container
void loop1(long long num)
{
    cout << "native raw pointer: ";
    vector<Thing> thingPtrs;
    YiUtil::MSSegmentTimer segTimer(YiUtil::MSSegmentTimer::MLSEC, std::cout);
    for(int i=0; i< num; i++) {
        Thing thing;
        thingPtrs.push_back(thing);
    }
    thingPtrs.clear();
}

void loop2(long long num)
{
    cout << "native boost::shared_ptr: ";
    vector<ThingPtr> thingPtrs;
    YiUtil::MSSegmentTimer segTimer(YiUtil::MSSegmentTimer::MLSEC, std::cout);
    for(int i=0; i< num; i++) {
        ThingPtr p1(new Thing);
        thingPtrs.push_back(p1);
    }
}

void loop3(long long num)
{
    cout << "optimized boost::shared_ptr: ";
    vector<ThingPtr> thingPtrs;

    YiUtil::MSSegmentTimer segTimer(YiUtil::MSSegmentTimer::MLSEC, std::cout);
    for(int i=0; i< num; i++) {
        ThingPtr p1 = boost::make_shared<Thing>();
        thingPtrs.push_back(p1);
    }
}


//loop3 and loop4 test shared_ptr in loop
void loop4(long long num)
{
    cout << "native raw pointer: ";
    YiUtil::MSSegmentTimer segTimer(YiUtil::MSSegmentTimer::MLSEC, std::cout);
    for(int i=0; i< num; i++) {
        Thing* p1 = new Thing();
        processThing(p1);
        delete p1;
    }
}

void loop5(long long num)
{
    cout << "native boost::shared_ptr: ";
    YiUtil::MSSegmentTimer segTimer(YiUtil::MSSegmentTimer::MLSEC, std::cout);
    for(int i=0; i< num; i++) {
        ThingPtr p1(new Thing);
        processThing(p1.get());
    }
}

void loop6(long long num)
{
    cout << "optimized boost::shared_ptr: ";
    YiUtil::MSSegmentTimer segTimer(YiUtil::MSSegmentTimer::MLSEC, std::cout);
    for(int i=0; i< num; i++) {
        ThingPtr p1 = boost::make_shared<Thing>();
        processThing(p1.get());
    }
}

int main() {
    long long num = 10000000;
    cout << "test 1" << endl;
    loop1(num);
    loop2(num);
    loop3(num);

    cout << "test 2"<< endl;
    loop4(num);
    loop5(num);
    loop6(num);

    return 0;
}

VC10 compiler under release mode, gcc compiled with flag '-O3' for max optimization. Test result:

//VS2010 release mode
//boost
test 1
native raw pointer: SegmentTimer: 15 milliseconds/n
native boost::shared_ptr: SegmentTimer: 3312 milliseconds/n
optimized boost::shared_ptr: SegmentTimer: 3093 milliseconds/n
test 2
native raw pointer: SegmentTimer: 921 milliseconds/n
native boost::shared_ptr: SegmentTimer: 2359 milliseconds/n
optimized boost::shared_ptr: SegmentTimer: 2203 milliseconds/n

//std
test 1
native raw pointer: SegmentTimer: 15 milliseconds/n
native std::shared_ptr: SegmentTimer: 3390 milliseconds/n
optimized std::shared_ptr: SegmentTimer: 2203 milliseconds/n
test 2
native raw pointer: SegmentTimer: 937 milliseconds/n
native std::shared_ptr: SegmentTimer: 2359 milliseconds/n
optimized std::shared_ptr: SegmentTimer: 1343 milliseconds/n
==============================================================================
gcc 4.72 release mode
//boost
test 1
native raw pointer: SegmentTimer: 15 milliseconds/n
native boost::shared_ptr: SegmentTimer: 4874 milliseconds/n
optimized boost::shared_ptr: SegmentTimer: 3687 milliseconds/n
test 2
native raw pointer: SegmentTimer: 1109 milliseconds/n
native boost::shared_ptr: SegmentTimer: 2546 milliseconds/n
optimized boost::shared_ptr: SegmentTimer: 1578 milliseconds/n

//std
test 1
native raw pointer: SegmentTimer: 15 milliseconds/n
native std::shared_ptr: SegmentTimer: 3374 milliseconds/n
optimized std::shared_ptr: SegmentTimer: 2296 milliseconds/n
test 2
native raw pointer: SegmentTimer: 1124 milliseconds/n
native std::shared_ptr: SegmentTimer: 2531 milliseconds/n
optimized std::shared_ptr: SegmentTimer: 1468 milliseconds/n

1条回答
Deceive 欺骗
2楼-- · 2019-06-23 19:16

They perform significantly better because the Boost version is not updated to use rvalue references, which enable move semantics. Whereas the C++11 versions do use move semantics. This means that the Boost version is having to copy quite a bit more often. If you test on a pre-C++11 compiler, your target base (with std::tr1::shared_ptr) they should perform much more similarly.

查看更多
登录 后发表回答