STL vs Массив(замер скорости)
От: WolfHound  
Дата: 07.05.03 07:09
Оценка:
Тесты проводились на VC++7.0 конфигурация Release /Ob2. Celeron 1000 256M WinXP.
Следовательно сделаные выводы касаются только его и его родного STL.
for_all vec             0.114540
for_all_ref vec         0.133207
for_all lst             0.395151
for_all_ref lst         0.395573
vec[i].Hi()             0.115812
arr[i].Hi()             0.025971

for_all vecp            0.672557
for_all_ptr vecp        0.671437
for_all lstp            0.661827
for_all_ptr lstp        0.660183
vecp[i]->Hi()           0.668313
arrp[i]->Hi()           0.684243

Выводы:
Контейнеры обьектов проигрывают обычным массивам причем сильно по сему использование их в критичных по скорости местах не рекомендую.(На не полиморфных обьектах отставание меньше.)
Но при использовании полиморфных контейнеров скорость примерно одинаковая. Особенно меня порадовал std::list который какимто чудом всех сделал(не сильно но сделал). А если учесть что вставка/удаление происходят за константное время то ИМХО для полиморфных контейнеров без альтернатив.


Если изменить параметры так(только не забудте сказать линкеру что метр под стек это мало)
    enum
    {
        ArrSize=1000000,
        IterCount=10,
    };

то
for_all vec             0.132461
for_all_ref vec         0.133806
for_all lst             0.388159
for_all_ref lst         0.385950
vec[i].Hi()             0.131733
arr[i].Hi()             0.128936

for_all vecp            0.672520
for_all_ptr vecp        0.671783
for_all lstp            0.650277
for_all_ptr lstp        0.649454
vecp[i]->Hi()           0.673344
arrp[i]->Hi()           0.672832

На длинных дистанциях у массивов начинаются проблемы... А на полиморфных обьектах std::list сделал всех еще сильнее.


    enum
    {
        ArrSize=100,
        IterCount=100000,
    };

for_all vec             0.113320
for_all_ref vec         0.115010
for_all lst             0.139346
for_all_ref lst         0.124963
vec[i].Hi()             0.110228
arr[i].Hi()             0.026199

for_all vecp            0.131513
for_all_ptr vecp        0.127315
for_all lstp            0.129233
for_all_ptr lstp        0.132465
vecp[i]->Hi()           0.127523
arrp[i]->Hi()           0.129062

А на коротких дистанциях полиморфные контейнеры почти не отстают.


Код:
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <vector>
#include <list>
#include <functional>
#include <memory>
unsigned int s;
struct TestBase
{
    virtual void Hi()=0;
    virtual ~TestBase(){}
};
struct Test:TestBase
{
    int g;//Начинка для того чтобы компилятор не соптимизировал циклы в ничто.
    void Hi()
    {
        static int x;
        x+=x+325;
        s+=x;
        g+=s;
    }
};
template<class T, class F>//Просто болие удобная замена for_each если надо перебрать ВСЕ элементы
inline F for_all(T& t, F f)
{
    for(T::iterator i=t.begin(), e=t.end();i!=e;++i)
        (f)(*i);
    return f;
}
template<class T, class F>
inline F for_all_ref(T& t, F f)
{
    for(T::iterator i=t.begin(), e=t.end();i!=e;++i)
        ((*i).*f)();
    return f;
}
template<class T, class F>
inline F for_all_ptr(T& t, F f)
{
    for(T::iterator i=t.begin(), e=t.end();i!=e;++i)
        ((**i).*f)();
    return f;
}
template<class T>//Эмуляция умного указателя
struct SmartPtr//В реальных проектах рекомендую boost::shared_ptr.(boost'а под рукой не было)
{
    T* p_;
    SmartPtr()
        :p_(0)
    {}
    SmartPtr(T* p)
        :p_(p)
    {}
    operator T*()
    {
        return p_;
    }
    T* operator ->()
    {
        return p_;
    }
};
int _tmain(int argc, _TCHAR* argv[])
{
    enum
    {
        ArrSize=10000,
        IterCount=1000,
    };
    Test arr[ArrSize];
    std::auto_ptr<TestBase> arrp[ArrSize];
    unsigned __int64 freq, begin, end;
    QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
    s=0;
    std::vector<Test> vec;
    vec.resize(ArrSize);
    std::list<Test> lst;
    lst.resize(ArrSize);
    std::vector<SmartPtr<TestBase> > vecp;
    std::list<SmartPtr<TestBase> > lstp;
    for(int i=0;i<ArrSize;++i)
    {
        std::auto_ptr<Test> p(new Test());
        arrp[i]=p;
        vecp.push_back(&*arrp[i]);
        lstp.push_back(&*arrp[i]);
    }
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for_all(vec, std::mem_fun_ref(&Test::Hi));
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("for_all vec \t\t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for_all_ref(vec, &Test::Hi);
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("for_all_ref vec \t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for_all(lst, std::mem_fun_ref(&Test::Hi));
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("for_all lst \t\t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for_all_ref(lst, &Test::Hi);
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("for_all_ref lst \t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for(int i=0;i<ArrSize;++i)
            vec[i].Hi();
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("vec[i].Hi() \t\t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for(int i=0;i<ArrSize;++i)
            arr[i].Hi();
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("arr[i].Hi() \t\t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
    printf("\n");
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for_all(vecp, std::mem_fun(&TestBase::Hi));
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("for_all vecp \t\t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for_all_ptr(vecp, &TestBase::Hi);
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("for_all_ptr vecp \t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for_all(lstp, std::mem_fun(&TestBase::Hi));
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("for_all lstp \t\t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for_all_ptr(lstp, &TestBase::Hi);
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("for_all_ptr lstp \t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for(int i=0;i<ArrSize;++i)
            vecp[i]->Hi();
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("vecp[i]->Hi() \t\t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
    QueryPerformanceCounter((LARGE_INTEGER*)&begin);
    for(int c=0;c<IterCount;++c)
        for(int i=0;i<ArrSize;++i)
            arrp[i]->Hi();
    QueryPerformanceCounter((LARGE_INTEGER*)&end);
    printf("arrp[i]->Hi() \t\t%f\n", (float(end-begin))/freq);
////////////////////////////////////////////////////////////////////////
    return s;
}
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.