在 Visual C 上哪个更快? 2010 - std::shared_ptr 还是 boost::shared_ptr?

发布于 2024-11-16 22:55:33 字数 228 浏览 2 评论 0原文

有人在发布模式构建中测试过这个吗?或者实现如此相似,没有显着差异?

我对以下速度感兴趣:

  1. 创建一个新的shared_ptr

  2. 创建shared_ptr的副本

  3. 取消引用访问被指点的指针

这将在一个针对速度而优化的发布版本中,并使用 make_shared() 创建新的shared_ptrs

Has anyone tested this in release mode builds? Or are the implementations so similar there's no significant difference?

I'm interested in the speed to:

  1. Create a new shared_ptr

  2. Create a copy of the shared_ptr

  3. De-reference the pointer to access the pointee

This would be in a release build optimized for speed with new shared_ptrs being created with make_shared()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

也只是曾经 2024-11-23 22:55:33

好吧,看来没有人这样做过。以下是我在 WIN32 控制台应用程序中使用标准 VC 10 优化设置时发现的结果:

  1. 在填充 1000 万个指针的向量时,Visual C++ 2010 SP1 std::make_shared 和 std::shared_ptr 比 Boost 1.46.1 等效项更快条目(20 次运行的平均时间为 1.96 秒与 0.92 秒)

  2. Boost 1.46.1 稍快复制包含 1000 万个指针条目的数组时,与 Visual C++ 2010 SP1 相比( 秒与 0.17 秒

  3. )(0.15 秒与 20 次运行的平均时间为 0.17 秒)

    Visual C++ 2010 SP1 比 Boost 1.46.1 等效版本稍快当取消引用包含 1000 万个指针条目的向量 20 次时(0.72 秒与 20 次运行的平均值为 0.811 秒)

:创建shared_ptr 来填充向量时存在显着差异。 Visual C++ 2010 share_ptr 的速度几乎是 Boost 1.46.1 的两倍,这表明在实现上存在显着差异。

其他测试没有显示出显着差异。

这是我使用的代码:

#include "stdafx.h"

struct A
{
    A( const unsigned A) : m_value(A)
    {
    }

    const unsigned m_value;
};

typedef std::shared_ptr<A> APtr;
typedef boost::shared_ptr<A> ABoostPtr;


double TestSTLCreateSpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<APtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    boost::timer timer;

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( std::make_shared<A>(nEntry) );
    }

    const double timeTaken = timer.elapsed();

    std::cout << "STL create test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double BoostSTLCreateSpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<ABoostPtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    boost::timer timer;

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( boost::make_shared<A>(nEntry) );
    }

    const double timeTaken = timer.elapsed();

    std::cout << "BOOST create test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double TestSTLCopySpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<APtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( std::make_shared<A>(nEntry) );
    }

    boost::timer timer;
    std::vector<APtr> buffer2 = buffer;

    const double timeTaken = timer.elapsed();

    std::cout << "STL copy test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double TestBoostCopySpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<ABoostPtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( boost::make_shared<A>(nEntry) );
    }

    boost::timer timer;
    std::vector<ABoostPtr> buffer2 = buffer;

    const double timeTaken = timer.elapsed();

    std::cout << "BOOST copy test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double TestBoostDerefSpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<ABoostPtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( boost::make_shared<A>(nEntry) );
    }

    boost::timer timer;

    unsigned total = 0;

    for(unsigned nIter = 0; nIter < 20; ++nIter)
    {
        std::for_each( buffer.begin(), buffer.end(),
            [&](const ABoostPtr& pA){ 
                total += pA->m_value;
        });
    }

    const double timeTaken = timer.elapsed();

    std::cout << "BOOST deref total =  " << total << ".\r\n";

    std::cout << "BOOST deref test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double TestSTLDerefSpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<APtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( std::make_shared<A>(nEntry) );
    }

    boost::timer timer;

    unsigned total = 0;
    for(unsigned nIter = 0; nIter < 20; ++nIter)
    {
        std::for_each( buffer.begin(), buffer.end(),
            [&](const APtr& pA){ 
                total += pA->m_value;
        });
    }

    const double timeTaken = timer.elapsed();

    std::cout << "STL deref total =  " << total << ".\r\n";

    std::cout << "STL deref test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

int _tmain(int argc, _TCHAR* argv[])
{
    double totalTime = 0.0;
    const unsigned NUM_TESTS = 20;

    totalTime = 0.0;

    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += BoostSTLCreateSpeed();
    }

    std::cout << "BOOST create test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestSTLCreateSpeed();
    }

    std::cout << "STL create test took " << totalTime / NUM_TESTS << " secs average.\r\n";


    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestBoostCopySpeed();
    }

    std::cout << "BOOST copy test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestSTLCopySpeed();
    }

    std::cout << "STL copy test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestBoostDerefSpeed();
    }

    std::cout << "Boost deref test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestSTLDerefSpeed();
    }

    std::cout << "STL deref test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    return 0;
}

我会等待一段时间,如果没有人反驳我的结果或提出一些更好的结论,我会接受我自己的答案。

Ok, so it doesn't look like anyone has done this. Here's what I found using the standard VC 10 optimized settings for a WIN32 console app:

  1. Visual C++ 2010 SP1 std::make_shared and std::shared_ptr were faster than the Boost 1.46.1 equivalents when populating a vector of 10 million pointer entries ( 1.96 secs versus 0.92 secs averaged across 20 runs)

  2. Boost 1.46.1 was slightly faster than Visual C++ 2010 SP1 when copying an array of 10 million pointer entries ( 0.15 secs versus 0.17 secs averaged over 20 runs)

  3. Visual C++ 2010 SP1 was slightly faster than the Boost 1.46.1 equivalents when dereferencing a vector of 10 million pointer entries 20 times ( 0.72 secs versus 0.811 secs averaged over 20 runs)

CONCLUSION: There was a significant difference when creating shared_ptrs to populate a vector. The Visual C++ 2010 shared_ptr was nearly twice as fast indicating a substantial difference in implementation compared to Boost 1.46.1.

The other tests didn't show a significant difference.

Here's the code I used:

#include "stdafx.h"

struct A
{
    A( const unsigned A) : m_value(A)
    {
    }

    const unsigned m_value;
};

typedef std::shared_ptr<A> APtr;
typedef boost::shared_ptr<A> ABoostPtr;


double TestSTLCreateSpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<APtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    boost::timer timer;

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( std::make_shared<A>(nEntry) );
    }

    const double timeTaken = timer.elapsed();

    std::cout << "STL create test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double BoostSTLCreateSpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<ABoostPtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    boost::timer timer;

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( boost::make_shared<A>(nEntry) );
    }

    const double timeTaken = timer.elapsed();

    std::cout << "BOOST create test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double TestSTLCopySpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<APtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( std::make_shared<A>(nEntry) );
    }

    boost::timer timer;
    std::vector<APtr> buffer2 = buffer;

    const double timeTaken = timer.elapsed();

    std::cout << "STL copy test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double TestBoostCopySpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<ABoostPtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( boost::make_shared<A>(nEntry) );
    }

    boost::timer timer;
    std::vector<ABoostPtr> buffer2 = buffer;

    const double timeTaken = timer.elapsed();

    std::cout << "BOOST copy test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double TestBoostDerefSpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<ABoostPtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( boost::make_shared<A>(nEntry) );
    }

    boost::timer timer;

    unsigned total = 0;

    for(unsigned nIter = 0; nIter < 20; ++nIter)
    {
        std::for_each( buffer.begin(), buffer.end(),
            [&](const ABoostPtr& pA){ 
                total += pA->m_value;
        });
    }

    const double timeTaken = timer.elapsed();

    std::cout << "BOOST deref total =  " << total << ".\r\n";

    std::cout << "BOOST deref test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

double TestSTLDerefSpeed()
{
    const unsigned NUM_ENTRIES = 10000000;
    std::vector<APtr> buffer;
    buffer.reserve(NUM_ENTRIES);

    for( unsigned nEntry = 0; nEntry < NUM_ENTRIES; ++nEntry)
    {
        buffer.emplace_back( std::make_shared<A>(nEntry) );
    }

    boost::timer timer;

    unsigned total = 0;
    for(unsigned nIter = 0; nIter < 20; ++nIter)
    {
        std::for_each( buffer.begin(), buffer.end(),
            [&](const APtr& pA){ 
                total += pA->m_value;
        });
    }

    const double timeTaken = timer.elapsed();

    std::cout << "STL deref total =  " << total << ".\r\n";

    std::cout << "STL deref test took " << timeTaken << " secs.\r\n";
    return timeTaken;
}

int _tmain(int argc, _TCHAR* argv[])
{
    double totalTime = 0.0;
    const unsigned NUM_TESTS = 20;

    totalTime = 0.0;

    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += BoostSTLCreateSpeed();
    }

    std::cout << "BOOST create test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestSTLCreateSpeed();
    }

    std::cout << "STL create test took " << totalTime / NUM_TESTS << " secs average.\r\n";


    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestBoostCopySpeed();
    }

    std::cout << "BOOST copy test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestSTLCopySpeed();
    }

    std::cout << "STL copy test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestBoostDerefSpeed();
    }

    std::cout << "Boost deref test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    totalTime = 0.0;
    for ( unsigned nTest = 0; nTest < NUM_TESTS; ++nTest)
    {
        totalTime += TestSTLDerefSpeed();
    }

    std::cout << "STL deref test took " << totalTime / NUM_TESTS << " secs average.\r\n";

    return 0;
}

I'll wait a while and if no one has refuted my results or come up with some better conclusions I'll accept my own answer.

苄①跕圉湢 2024-11-23 22:55:33

VS10 的版本在可能的情况下使用右值引用和移动语义,因此原则上它比 Boost C++98 实现更具优势。不过,您可能必须相当努力地创建一个能够显示出显着的实际差异的程序......但是请尝试一下。另外不要忘记 std::make_shared,由于转发,它是 C++0x 中的新增内容。

更新:在任何情况下,取消引用和复制实际上都是相同的。也许自定义删除器和分配器的存储方式以及 make_shared 的实现方式存在一些有趣的差异。让我检查一下来源。

更新 2:有趣的是,使用可变参数模板和右值引用的 Boost 版本看起来肯定比 VS10 版本更好,因为 VS10 没有可变参数模板并且必须使用伪造这种行为的可怕黑术。但这完全是一个编译时问题,因此不相关。

VS10's version uses rvalue references and move semantics when possible, so in principle it has the upper hand over the Boost C++98 implementation. You'd probably have to work fairly hard to create a program that would show a significant practical difference, though... but do give it a try. Also don't forget about std::make_shared, which is new in C++0x thanks to forwarding.

Update: Dereferencing and copying are going to be practically identical in any case. Perhaps there are some interesting differences in the way custom deleters and allocators are stored, and in how make_shared is implemented. Let me check the source.

Update 2: Funnily enough, the Boost version that uses variadic templates and rvalue references definitely looks better than the VS10 version, since VS10 doesn't have variadic templates and has to employ horrible black arts to fake that behaviour. But that's entirely a compile-time issue so it's not relevant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文