Some performance numbers with different Allocators

Stefan Olsson stefan@snon.net
Mon Jul 28 09:35:00 GMT 2003


Hi Abhi!

We have looked into this and the basic conclusion for the "poor 
performance of __mt_allocator" is that this test only allocates new 
memory, which then has to be fetched from the global pool thus forcing a 
thread lock and a context switch. This becomes very obvious if you run a 
vmstat 1 while running the tests...

However, in a real life application (?) you would both alloc and free 
memory and end up with a freelist for each thread (in size relative to 
the amount of memory allocated by that thread, thus limiting overall 
memory usage) which then can be reused without locking/context switching.

If you really need to write an application such as the example I would 
look into a allocator that maintains purely private freelists such as 
the SGI pthread_alloc (see http://www.sgi.com/tech/stl/Allocators.html).

Brgds

/Stefan & Ola

Abhi wrote:

> I have some numbers for these tests with the gcc optimization flags
>
> with -O2 -funroll-loops
> =======================
> CPU    malloc            malloc         STL normal        STL MT
>                      & hoard
> 1    20.230u 1.580s   13.140u 0.970s     24.410u 13.390s    17.940u 
> 7.660s
> 2    25.800u 1.810s   21.670u 0.750s  96.140u 142.020s    34.690u 26.670s
>
> Still hoard behaves better than STL MT allocators.
>
> These are for Redhat 7.3 LinuxThreads, gcc3.4
>
> thanks
> ...Abhi
>
>
>
>
> --On Wednesday, July 23, 2003 9:15 AM -0700 Abhi <abhi@qualcomm.com> 
> wrote:
>
>> I ran these tests without any gcc optimization flags.
>> I will try with -O2 -funroll-loops and post results later today.
>> Do you want me to try with some other flags?
>>
>> I do believe my test is quite simplistic, It would be interesting to see
>> some results with more elaborate/complicated test cases.
>>
>> I will also posts results using Redhat 9 (with NPTL).
>>
>> Thanks
>> ....Abhi
>>
>>
>>
>> --On Wednesday, July 23, 2003 7:18 AM +0200 Stefan Olsson
>> <stefan@snon.net> wrote:
>>
>>> Hi Abhi!
>>>
>>> Very interesting since I did a similar test with Hoard about a year ago
>>> with very different results - thus the development of mt_allocator...
>>>
>>> Please let us know how you compiled the testprogram (optimization 
>>> levels
>>> and other flags).
>>>
>>> Brgds
>>>
>>> /Stefan
>>>
>>> Abhi wrote:
>>>
>>>> Hi,
>>>>     I ran some performace tests using different allocators.
>>>>     The sample code is pretty simple,
>>>>     - it creates 4 threads
>>>>     - Each thread creates a list of string using an allocator
>>>>     - Adds 1000000 strings to the list in a for loop
>>>>     - Reads all these strings in a for loop
>>>>     - Modifies all these strings in a for loop
>>>>
>>>> I ran this code 4 times (using 4 different allocators )
>>>> malloc = An allocator that uses malloc
>>>> malloc_hoard = An allocator that uses malloc with hoard (using
>>>>            LD_PRELOAD, www.hoard.com)
>>>> STL = Default STL allocator that comes with gcc 3.4
>>>>         (pool allocator)
>>>> STL MT = MT STL allocator that comes with gcc3.4
>>>>
>>>> Test Machine
>>>> Dual CPU, Linux Redhat 7.3, GCC3.4 snapshot
>>>>
>>>> Here are the numbers
>>>> # CPU malloc         malloc_hoard    STL                STL MT
>>>>
>>>> 1  31.280u 1.500s     19.670u 0.900s  26.510u 13.470s    23.010u 
>>>> 4.330s
>>>> 2  40.850u 2.270s     38.630u 0.710s  103.820u 148.150s  51.600u
>>>> 23.660s
>>>>
>>>> Seems like for this case hoard behaves the best, although a dual CPU
>>>> machine still performs worse that a single CPU machine for a MT
>>>> application. Does this seem surprising?
>>>>
>>>> Also I guess this code is MT-safe, especially the malloc
>>>> allocators...right? Just want to be sure!
>>>>
>>>> Heres the code
>>>> ----------------------------------------------------------------------
>>>> # include <list>
>>>> # include <pthread.h>
>>>> # include <errno.h>      // ETIMEDOUT
>>>> # include <string>
>>>> // For malloc
>>>> // #include <ext/malloc_allocator.h>
>>>> // #include <bits/allocator_traits.h>
>>>> // For MT
>>>> // #include <ext/mt_allocator.h>
>>>> // #include <bits/allocator_traits.h>
>>>>
>>>>
>>>> using namespace std;
>>>>
>>>> // For Malloc
>>>> // typedef __allocator<char, __gnu_cxx::__malloc_alloc<0> >    
>>>> MyAlloc;
>>>> // typedef basic_string<char, char_traits<char>, MyAlloc>      
>>>> MyString;
>>>> // typedef std::list<MyString, __gnu_cxx::__malloc_alloc<1> >  List1;
>>>>
>>>> // For MT
>>>> // typedef __allocator<char, __gnu_cxx::__mt_alloc<0> >    MyAlloc;
>>>> // typedef basic_string<char, char_traits<char>, MyAlloc>      
>>>> MyString;
>>>> // typedef std::list<MyString, __gnu_cxx::__mt_alloc<1> >  List1;
>>>>
>>>>
>>>> // For Default STL
>>>> typedef string MyString;
>>>> typedef std::list<MyString> List1;
>>>>
>>>>
>>>>
>>>> extern "C" void* Run(void *)
>>>> {
>>>>    List1 List;
>>>>    for ( int i=0; i<1000000; ++i )
>>>>    {
>>>>     MyString s;
>>>>     s.append("Hoiiiiiii");
>>>>     List.push_back( s );
>>>>    }
>>>>
>>>>    for (List1::iterator j = List.begin(); j != List.end(); ++j)
>>>>    {
>>>>     MyString s = *j;
>>>>    }
>>>>
>>>>    for (List1::iterator j = List.begin(); j != List.end(); ++j)
>>>>    {
>>>>     MyString s("Hiiiiiii");
>>>>     *j = s;
>>>>    }
>>>>
>>>>
>>>> }
>>>>
>>>>
>>>> using namespace std;
>>>>
>>>> int main ()
>>>> {
>>>>    pthread_t  t1, t2, t3, t4;
>>>>    pthread_create(&t1,  // Thread Id for new thread
>>>>            NULL,          // Thread attributes
>>>>            Run,        // Function
>>>>            NULL);
>>>>
>>>>    pthread_create(&t2,  // Thread Id for new thread
>>>>            NULL,          // Thread attributes
>>>>            Run,        // Function
>>>>            NULL);
>>>>
>>>>    pthread_create(&t3,  // Thread Id for new thread
>>>>            NULL,          // Thread attributes
>>>>            Run,        // Function
>>>>            NULL);
>>>>
>>>>    pthread_create(&t4,  // Thread Id for new thread
>>>>            NULL,          // Thread attributes
>>>>            Run,        // Function
>>>>            NULL);
>>>>
>>>>    int errNum = pthread_join(t1, NULL);
>>>>    errNum = pthread_join(t2, NULL);
>>>>    errNum = pthread_join(t3, NULL);
>>>>    errNum = pthread_join(t4, NULL);
>>>> }
>>>>
>>>> ----------------------------------------------------------------------
>>>>
>>>> Any Insights/Ideas
>>>> Thanks
>>>> ....Abhi
>>>>
>>>>
>>>>
>>>
>>>
>>> -- 
>>> Winning isn't everything, but losing isn't anything.
>>>
>>
>>
>>
>
> ---------- End Abhi <abhi@qualcomm.com> Message ----------
>
>
>
>
>


-- 
Winning isn't everything, but losing isn't anything.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 4660 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20030728/838b2ab6/attachment.bin>


More information about the Libstdc++ mailing list