Click here to Skip to main content
Email Password   helpLost your password?

To obtain a copy of this paper in pdf format click here (or from google code). Another copy is also available on google docs in html format.

Introduction

Most of the C++ programmers do not benefit from "Garbage Collection" technique (GC). They are sick of deleting objects but have to do this. There are some C/C++ memory GC implementations, but they are complex and are not widely used.

I am going to introduce a new memory management technique named "GC Allocator". "GC Allocator" isn't an implementation, but a concept. Now, we have two "GC Allocator" implementations, named "AutoFreeAlloc" and "ScopeAlloc".

This article consists of three parts:

  1. What is GC Allocator?
  2. GC Allocator implementations: ScopeAlloc and AutoFreeAlloc
  3. Applications based on GC Allocator

What is GC Allocator?

  1. It is an Allocator for allocating memory.
  2. A better Smart Pointer.
  3. Creating a GC Allocator and allocating memory should be very fast.
  4. Another way of GC.

Concept of GC Allocator

GC Allocator is only a concept. The following is minimum specification for GC Allocator:

typedef void (*DestructorType)(void* data);
 
concept GCAllocator
{
    // Allocate memory without given a cleanup function
    void* allocate(size_t cb);
 
    // Allocate memory with a cleanup function
    void* allocate(size_t cb, DestructorType fn);
 
    // Cleanup and deallocate all allocated memory by this GC Allocator
    void clear();

    // Swap two GCAllocator instances
    void swap(GCAllocator& o);
};

When you creating a GC Allocator, You can use STD_NEW, STD_NEW_ARRAY to new objects. Let's see a very simple example:

GCAllocator alloc(initArgs); // initArgs depends on implementation
 
int* intObj = STD_NEW(alloc, int);
int* intObjWithArg = STD_NEW(alloc, int)(10);
int* intArray = STD_NEW_ARRAY(alloc, int, count);
 
MyObj* obj = STD_NEW(alloc, MyObj);
MyObj* objWithArg = STD_NEW(alloc, MyObj)(100);
MyObj* objArray = STD_NEW_ARRAY(alloc, MyObj, count);

Frankly speaking, I don't like STD_NEW and STD_NEW_ARRAY. I hope I can use the following syntax:

GCAllocator alloc(initArgs);
 
int* intObj = new(alloc) int;
int* intObjWithArg = new(alloc) int(10);
int* intArray = new(alloc) int[count];
 
MyObj* obj = new(alloc) MyObj;
MyObj* objWithArg = new(alloc) MyObj(100);
MyObj* objArray = new(alloc) MyObj[count];

A Better Smart Pointer

C++ programmers are sick of deleting objects. So they invent a technique named "Smart Pointer". There are many implementations of Smart Pointer. The simplest one is std::auto_ptr. Here is an example:

{
    std::auto_ptr<MyObj> obj(new MyObj);
    std::auto_ptr<AnotherObj> obj2(new AnotherObj);
    ... // use obj and obj2 to do something.
}

If you don't use Smart Pointer, you have to write the following code:

{
    MyObj* obj = new MyObj;    
    AnotherObj* obj2;
    try
    {
        obj2 = new AnotherObj;
    }
    catch(...}
    {
        delete obj;
        throw;
    }
    try
    {
        ... // use obj and obj2 to do something.
    }
    catch(...)
    {
        delete obj2;
        delete obj;
        throw;
    }
    delete obj2;
    delete obj;
}

When you use a GC Allocator, you can do the same things as the following:

{
    GCAllocator alloc(initArgs); // initArgs depends on implementation
 
    MyObj* obj = STD_NEW(alloc, MyObj);
    AnotherObj* obj2 = STD_NEW(alloc, AnotherObj);
    ... // use obj and obj2 to do something.
}

I think that a GC Allocator is a better smart pointer. Why?

First, if you use Smart Pointer technique, when you need an array you have to implement a new a smart pointer type for array object. The following code doesn't work well:

{
    std::auto_ptr<MyObj> objArray(new MyObj[count]);
    // ---> Error!!! You can't pass an array pointer to the auto_ptr constructor.
 
    ... // use objArray to do something.
}

But when you use GC Allocator, It is only a piece of cake:

{
    GCAllocator alloc(initArgs); // initArgs depends on implementation
 
    MyObj* objArray = STD_NEW_ARRAY(alloc, MyObj, count);
    ... // use objArray to do something.
}

Second, Most of the Smart Pointer implementations (eg. boost::shared_ptr, ATL::CComPtr, etc) are based on "Reference Counting" technique. When an algorithm needs to return a new object, "Reference Counting" is a common solution. For example:

boost::shared_ptr<MyObj> algorithm(...)
{
    boost::shared_ptr<MyObj> obj(new MyObj);
    ...
    return obj;
}

But "Reference Counting" really isn't a good solution:

  1. The Windows COM (based on "Reference Counting") programmers are sick of memory leak endlessly.
  2. It's a fact that not all of the C++ programmers like smart pointers, and not all of the C++ programmers like the SAME smart pointer. You have to convert between normal pointers and smart pointers, or between one smart pointer and another smart pointer. Then things become complex and difficult to control.
  3. Having a risk of Circular Reference.
  4. Tracking down memory leaks is more difficult when an object has a "Reference Count".

When you use GC Allocator, a GC Allocator instance will be passed to the algorithm if it needs to return a new object:

template <class AllocT>
MyObj* algorithm(AllocT& alloc, ...)
{
    MyObj* obj = STD_NEW(alloc, MyObj);
    ...
    return obj;
}

Note the allocator instance alloc is passed as a template class AllocT. At the beginning of this article, I said that GC Allocator was not a implementation, but a concept. Now you know why I say that: most of algorithms don't need to care what the alloc instance is.

Last, "Smart Pointer" is out, all what you use are just normal pointer. This is very important. It makes the code using "GC Allocator" work together with the code without using "GC Allocator" well.

Creating a GC Allocator and Allocating Memory Should Be Very Fast

Most of allocator implementations optimize allocating a lot of objects. If ONE allocator instance only allocates ONE object instance, they become slower than a normal new/delete allocation. When we consider GC Allocator as Smart Pointer, It should be fast even if It only allocate ONE object instance.

Let's see one of our test results:

PerAlloc ScopeAlloc AutoFreeAlloc AprPools MtAllocator BoostPool BoostObjectPool NewDelete
1 3.93 ms 59.26 ms 68.58 ms 56.48 ms 227.61 ms 347.08 ms 50.66 ms
peralloc-1.png

(PerAlloc means the number of objects allocated by one allocator instance)

For the detail information about the comparison, see "Allocators Performance Comparison". I 'm excited that ScopeAlloc is observably faster than a normal new/delete allocation and AutoFreeAlloc is close to a normal new/delete allocation.

Another Way of GC

I think that GC Allocator is another way of GC. Of course, GC Allocator does't work as GC in Java or C#. In fact, the core source code of our GC Allocator implementation is only about 100 code lines! It doesn't do too much, but do the most important things.

Generally GC Allocator has an abstract to algorithms like this:

GCAllocator.png

An algorithm may has two GC Allocator instances. One is named "Private GC Allocator". Another is named "Shared GC Allocator". If an object will be returned out, then it will be allocated by "Shared GC Allocator". If an object will be destroyed when the algorithm is end, then it will be allocated by "Private GC Allocator". The pseudo code looks like this:

ResultDOM* algorithm(GCAllocator& sharedAlloc, InputArgs args)
{
    GCAllocator privateAlloc(sharedAlloc);
    ...
    ResultDOM* result = STD_NEW(sharedAlloc, ResultDOM);
    ResultNode* node = STD_NEW(sharedAlloc, ResultNode);
    result->addNode(node);
    ...
    TempVariable1* temp1 = STD_NEW(privateAlloc, TempVariable1);
    TempVariable2* temp2 = STD_NEW(privateAlloc, TempVariable2);
    ...
    return result;
}

The Private GC Allocator (named privateAlloc) works like a "Smart Pointer". But unlike "Smart Pointer", ONE GC Allocator instance manages a group of objects, not ONE BY ONE.

If the amount of private allocated objects is small, privateAlloc is not needed. Then the algorithm become like this:

ResultDOM* algorithm(GCAllocator& alloc, InputArgs args)
{
    ResultDOM* result = STD_NEW(alloc, ResultDOM);
    ResultNode* node = STD_NEW(alloc, ResultNode);
    result->addNode(node);
    ...
    TempVariable1* temp1 = STD_NEW(alloc, TempVariable1);
    TempVariable2* temp2 = STD_NEW(alloc, TempVariable2);
    ...
    return result;
}

In any case, you don't need to delete objects manually. This is why I call GCAllocator "GC Allocator".

GC Allocator Implementations: ScopeAlloc and AutoFreeAlloc

We have two "GC Allocator" implementations, named "AutoFreeAlloc" and "ScopeAlloc". A brief summary of this section follows:

  1. Performance: they are faster than all other allocators you ever seen.
  2. The infrastructure of ScopeAlloc and AutoFreeAlloc.
  3. A huge stack.
  4. Only about 100 core code lines.
  5. No multithreaded locks (no need).
  6. When to use AutoFreeAlloc.
  7. Open source.

Faster Than All Allocators You Ever Seen

We toke performance comparison of:

In linux platform, we got the following result:

peralloc-1000000.png

In windows platform, we got the following result (I remove the NewDelete bar because it is too slow):

vs2005-peralloc-1000000.png

For the detail information about the comparison, see "Allocators Performance Comparison".

Why ScopeAlloc and AutoFreeAlloc are so fast? They benefit from:

  1. Its good allocation algorithm.
  2. No multithreaded locks.
  3. C++ inline functions.

The Infrastructure of ScopeAlloc and AutoFreeAlloc

The infrastructure of ScopeAlloc and AutoFreeAlloc follows:

GCAllocInfrastructure.png

There are three basic concepts: SystemAlloc, BlockPool and GCAlloc.

SystemAlloc is an abstract of the underlying system memory management service. It is only a wrapper of malloc/free procedures of C runtime:

class SystemAlloc
{
public:
    void* allocate(size_t cb) { return malloc(cb); }
    void deallocate(void* p)  { free(p); }
    void swap(SystemAlloc& o) {}
};

BlockPool is a Memory Pool. It works as a cache pool to accelerate the speed of allocating memory. BlockPool provides the same interface as SystemAlloc:

class BlockPool
{
public:
    BlockPool(int cacheSize = INT_MAX);
 
    void* allocate(size_t cb);
    void deallocate(void* p);
    void swap(BlockPool& o);
};

Why BlockPool can accelerate the speed of allocating memory? It isn't because BlockPool is a memory pool (you know SystemAlloc may also be implemented by using Memory Pool technique), but BlockPool doesn't need multithreaded locks.

The last concept is GCAlloc. It is the core of GC Allocator. And it is only about 100 core code lines!

GCAlloc: A Huge Stack

The implementation class of GCAlloc is named "GCAllocT". It provides the following interface:

template <class _Alloc>
class GCAllocT
{
public:
    GCAllocT();
    explicit GCAllocT(const _Alloc& alloc);
    explicit GCAllocT(GCAllocT& owner);
 
    // Allocate memory without given a cleanup function
    void* allocate(size_t cb);
 
    // Allocate memory with a cleanup function
    void* allocate(size_t cb, DestructorType fn);
 
    // Cleanup and deallocate all allocated memory by this GC Allocator
    void clear();
 
    // Swap two GCAllocator instances
    void swap(GCAllocT& o);
};
 
typedef GCAllocT<SystemAlloc> AutoFreeAlloc;
typedef GCAllocT<ProxyBlockPool> ScopeAlloc;

AutoFreeAlloc and ScopeAlloc are both based on GCAllocT. The only different thing is that AutoFreeAlloc is based on SystemAlloc (global malloc/free allocation procedures), while ScopeAlloc is based on a BlockPool (a cache allocator to accelerate the speed of memory allocation).

AutoFreeAlloc and ScopeAlloc have distinct performance difference due to this difference.

ScopeAlloc has the best performance in any condition. And if we allocate enough objects, performance of AutoFreeAlloc is close to ScopeAlloc.

For the detail information, see "Allocators Performance Comparison".

You know, the fastest "Allocator" is "Stack". C/C++ allocate auto objects (also named "Stack Objects") on "Stack". But "Stack" has many of limit:

  1. When exiting a procedure, all "Stack Objects" will be destroyed. So, you can't return a "Stack Object".
  2. You can't allocate too many "Stack Objects", because "Stack" has limited size.

The basic idea of GCAlloc is implemented as "a huge stack" on heap. It have similar performance as "Stack". I don't explain the detail implementation here. If you want to dive into it, refer the source code.

No Multithreaded Locks

Why doesn't GC Allocator need multithreaded locks?

Memory allocation = System memory block management + Memory management algorithm

The underlying system memory block management is provided by OS. It will optimize large memory block allocation (allocating small objects is supported, but doesn't need to optimize). And It is thread/process safe.

Memory management algorithm is provided by C/C++ runtime library, or other libraries. Memory management algorithms ARE only algorithms. Most of them are designed to be thread safe.

If we use global new/delete or malloc/free procedures to allocate memory, thread safe is a MUST (because all threads use these procedures), not OPTIONAL. But if we use allocator instances to manage memory, then thread safe becomes OPTIONAL.

Why? Sharing GC Allocator in multi threads is not recommended. It means that sharing memory between threads is also not recommended. If you REALLY want to share memory, use new/delete or anything else.

For users of GC Allocator, we suggest that only use ONE BlockPool instance in ONE thread, and ONE thread may use multiple PRIVATE "ScopeAlloc" instances (depend on your requirement) to allocate memory.

And this makes ScopeAlloc be the fastest allocator!

When to use AutoFreeAlloc

You know, ScopeAlloc is faster than AutoFreeAlloc in any condition. Then you may wonder when to use AutoFreeAlloc. Here are some conditions that you can consider to use AutoFreeAlloc:

  1. An algorithm that don't want to accept a BlockPool or ScopeAlloc parameter. If we use ScopeAlloc, we need a BlockPool or ScopeAlloc instance to construct a new ScopeAlloc object. But in some case, we don't want our users to know the implementation detail of using ScopeAlloc.
  2. An algorithm that need a lot of memory allocations. If we allocate enough objects, performance of AutoFreeAlloc is close to ScopeAlloc (see "Allocators Performance Comparison").
  3. An algorithm that will release all allocated memory when the algorithm is end.

Open Source

Yes, ScopeAlloc/AutoFreeAlloc is open source. And it's licensed under Common Public License(CPL). you can find more information in http://code.google.com/p/stdext/.

Here are quick links for source code of ScopeAlloc/AutoFreeAlloc:

Applications based on GC Allocator

Is GC Allocator useful? Yes. Things are changed for C++ developers! We also can benefit from GC like Java and C#! And There are already some applications based on it. Here are part of them:

A Word File Writer

I wrote a word file format writer with GC Allocator. I was excited that It is the fastest word file writer component I ever seen.

Interested in it? See The Fastest Word File Writer.

Rope based on GC Allocator

Rope is a complex string implementation with scaled performance. The original rope implementation is appeared in SGI STL. I rewrite the rope class based on GC Allocator. Code size is much reduced and performance is better.

Interested in it? See Rope on GC Allocator.

STL Containers based on GC Allocator

Not only rope, but most of all STL containers can be based on GC Allocator, including:

When we use ScopeAlloc, performance of STL containers has distinct promotion. Here is one of our test results (in milliseconds):

deque list set hash_set map hash_map
ScopeAlloc 5.71 ms 20.32 ms 198.44 ms 129.68 ms 225.12 ms 130.80 ms
STL 8.34 ms 66.56 ms 504.81 ms 232.63 ms 505.34 ms 242.21 ms
STLContainers.png

For the detail information about the comparison, see "Allocators Performance on STL Collections".

Note that we don't provide all STL containers based on GC Allocator. STL containers of linear data structure (eg. std::vector, std::basic_string/std::string, etc) don't need a GC allocator.

Related Topics

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
General许大侠
chenyu2202863
16:27 17 Jan '10  
在CSDN Blog就拜读过了,今天又在这儿发现了火种!
忍不住再赞叹一声!
GeneralBenchmarks for Multithreaded environment?
philippec613
18:37 26 Nov '09  
I am curious to see how this allocator would compare in a multithreaded environment vs say, hoard allocator and the allocator from Intel Threading Blocks.
QuestionConfused
Bullno1
5:59 23 Sep '08  
After reading your article and viewing the source, I'm a bit confused.

Your allocator does not use smart pointer or reference counting. How does it know when to delete an object. Especially in your following example:
ResultDOM* algorithm(GCAllocator& alloc, InputArgs args)
{
ResultDOM* result = STD_NEW(alloc, ResultDOM);
ResultNode* node = STD_NEW(alloc, ResultNode);
result->addNode(node);
...
TempVariable1* temp1 = STD_NEW(alloc, TempVariable1);
TempVariable2* temp2 = STD_NEW(alloc, TempVariable2);
...
return result;
}
temp1 and temp2 are allocated using the shared allocator. How does your allocator differentiate them from result and node(which are also allocated from the same allocator)?
GeneralScalability
chriswa
6:10 16 May '08  
I'm interested in understanding how AllocFree scales. What I'm doing is writing a framework around a base object and wish to hide the memory management implementation from my users.

My concern is that when the user is done with the object there'll be a lot of "dead" object still allocated by the object allocator. If I used a smart pointer to destroy the object, I notice from the source that destroy is a stub. Therefore for a long running application that uses a lot of dynamic objects, could potentially run out of memory due to a lot of unreleased objects. The aspect I like is that I know then the application terminates the allocator will release all objects.

Thanks.
QuestionRe: Scalability
chriswa
14:09 16 May '08  
I noticed in your boost version you have a new class called gc_alloc that provide implementation for the destroy method. Perhaps I'll take a closer look at that implementation. However I don't want to bring in the boost library. I wonder if you can provide a gc_alloc class isolated from boost?

thanks.
AnswerRe: Scalability
xushiwei
19:04 28 May '08  
Though boost-memory library is under namespace boost, but it doesn't depend any boost standard staff. Smile
Questionwhen does it free?
araud
22:35 6 May '08  
I very do like that you've done! Really excellent, but I'd like to know what is behing the curtain.

Please explain how your collector can know when to free memory block? How can it know that block is no more in use?
For example let's suppose I allocate a large video frame. I do this 25 times per second. And I have 20 cameras in one process doing that. Life cycle of each frame is depend on features found in it, for example: moving is detected, face found, autonumber, and so on. And some frames should die as soon as possible to prevent memory overhead, and other shall live very long time. Please describe how to use your GC in this scenario?

"7 You shall have no other gods before me. 8 You shall not make an images in order to bow down to them or serve them. 11 You shall not take the name of the LORD your God in vain. 12 Observe the sabbath day 16 Honor your father and your mother, that your days may be prolonged. 17 You shall not kill. 18 Neither shall you commit adultery. 19 Neither shall you steal. 20 Neither shall you bear false witness against your neighbor. 21 Neither shall you covet anything that's your neighbor's." Your God

GeneralGreat work!
Tage Lejon
4:14 5 May '08  
I can see the following advantages with this implementation, particularly for applications that need to run for long time (days) and do memory allocation and deallocation frequently
1. Fast operations
2. Much reduced memory fragmentation in the RAM, and thus more stable operations.

Valuable enhancements, great!
GeneralNothing is free
ykachanov
16:48 1 May '08  
Did you compare the memory consumption? What do you think about projects with 10,000 threads? Looks like the usual problem "time / money" or "memory / speed".
AnswerRe: Nothing is free
xushiwei
23:57 2 May '08  
No. AutoFreeAlloc/ScopeAlloc consume less memory than a general allocator.
GeneralGC in your name is very deceiving
Snaury
10:48 29 Apr '08  
I think that 'GC' in your allocator name is very deceiving. It's a well known technique to preallocate big chunk of memory for a bunch of objects to free them later all in one go, so your technique is a normal allocator, there's no 'GC' in here. So what 'GC' stands for in GC Allocator?
AnswerRe: GC in your name is very deceiving
xushiwei
15:38 29 Apr '08  
In any case, you don't need to delete objects manually. This is why I call GCAllocator "GC Allocator".
GeneralI agree.
wtwhite
4:43 7 May '08  
The term "garbage collection" has come to mean a system of memory management in which memory holding data which is provably no longer accessible is automatically reclaimed. This is not true of your allocators: it is certainly possible that the programmer may call clear() (or, presumably, the destructor) of a GCAllocT object while objects allocated by it are still in active use. (That would be the programmer's mistake; but nevertheless it is a fact that this is a mistake that cannot possibly be made with a true GC system.) It only confuses matters to label your system a "GC" system when it is not.

What you have implemented is actually called "arena memory management". It is indeed a very fast and useful way to manage memory, provided the programmer has enough discipline to call clear() at the correct times. A number of pre-existing libraries, notably APR which you mention, already provide some form of arena memory management.

Please don't take this as an attack on your work; I think the library you have produced is very worthwhile, and clearly high-performing. I would just like to see a name change away from the misleading "GCAlloc". I gave your article a 4.

WTJW
AnswerRe: I agree.
xushiwei
7:43 7 May '08  
If "GC Allocator" is only a "arena allocator", I won't write this article. And I won't say it is a "C++ Memory Management Innovation".

"GC Allocator" is a concept, not a implementation. It is not "GC". There are two different things from a "arena allocator":

1. GC Allocator manage c++ objects, not only the memory. The key feature of "GC Allocator" is that the programmer don't need to delete objects manually, or they can forget to delete objects (Some GC Allocator implementations provide interfaces to delete objects manually. eg. boost::memory::gc_alloc. gc_alloc.hpp[^]).

2. You can create an GC Allocator to allocate a few memory, and then release the GC Allocator. This should be very fast. If creating an allocator is perceived as expensive, it becomes a normal region allocator (AutoFreeAlloc is a typical example). Programmers will reuse existing allocators as necessary, and it has narrow usage.
GeneralRe: I agree.
wtwhite
7:59 7 May '08  
xushiwei wrote:
"GC Allocator" is a concept, not a implementation. It is not "GC".

That is why I suggest choosing a different name.

xushiwei wrote:
1. GC Allocator manage c++ objects, not only the memory.

Are you saying that your allocator calls destructors on all allocated objects when the GCAlloc object dies? That is certainly a very useful feature to have, but in all other respects, your GCAlloc is just like other arena allocators. (All arena allocators release the underlying memory for their objects; that's the whole point.) So, I would call your work a "C++-aware arena allocator".

xushiwei wrote:
2. You can create an GC Allocator to allocate a few memory, and then release the GC Allocator. This should be very fast.

If you do in fact call destructors for each allocated object at GCAlloc destruction time, then this step will necessarily still take linear time in the number of allocated objects. But I accept that less time will be used in the actual releasing of the underlying memory, due to the simple stack-based structure you allocate memory from.

WTJW
GeneralRe: I agree.
xushiwei
21:40 7 May '08  
You're right. The implementation of GCAlloc is based on "arena allocator". You can say that my article just suggested the programmers use region allocators instead of normal allocators as possible. I find the truth that The more programmer manually manage memory, the less performance they get. See output.txt[^]
GeneralRe: I agree.
xushiwei
21:42 7 May '08  
See http://cpp.winxgui.com/boost-memory-0-1-01[^]
GeneralRe: I agree.
wtwhite
1:10 8 May '08  
I definitely agree that the less manual memory management, the better!

I took a look at your output.txt. I couldn't find anything called "boost::memory::gc_alloc" on the web, so I'm not sure what library those results correspond to. No big deal!

WTJW
GeneralRe: I agree.
xushiwei
5:13 8 May '08  
See http://winx.googlecode.com/svn/tags/boost-memory-0.1.01/boost/memory/[^]

I moved AutoFreeAlloc, ScopeAlloc from stdext library (managed by me. homepage: http://code.google.com/p/stdext/) to boost-memory sandbox library.

* AutoFreeAlloc -> boost::memory::auto_alloc
* ScopeAlloc -> boost::memory::scoped_alloc
* boost::memory::gc_alloc (new!)
GeneralRe: I agree.
wtwhite
8:34 8 May '08  
Ah, now I see. Thanks.

WTJW
GeneralImplementation and speed question
JeanLuc_
4:29 22 Apr '08  
Hi, good work and thanks for sharing!

I have a question: I'm using Doug Lea's malloc with great success, in simply using global new/delete like this:

#include "dlmalloc.h"

void* operator new(size_t sz) { return dlmalloc(sz);}
void operator delete(void* m) { dlfree(m); }
void* operator new[](size_t sz) { return dlmalloc(sz);}
void operator delete[](void* m) { dlfree(m); }

It seems to be very fast and does the job of garbage collection if I'm not mistaken.

How does this compare to your approach in your opinion?
GeneralRe: Implementation and speed question
xushiwei
8:30 22 Apr '08  
I tested its performance. Unfortunately, It is slower than new/delete if I enable multithreaded locks. Because dlmalloc provides only global allocation procedures, so I think it HAVE TO enable multithreaded locks.

===== DLMalloc(1) =====
---> Elapse 181124460 ticks (181.12 ms) (0.00 min) ...
---> Elapse 178655741 ticks (178.66 ms) (0.00 min) ...
---> Elapse 177219158 ticks (177.22 ms) (0.00 min) ...
---> Elapse 178737811 ticks (178.74 ms) (0.00 min) ...
---> Elapse 176783149 ticks (176.78 ms) (0.00 min) ...
---> Elapse 177809091 ticks (177.81 ms) (0.00 min) ...
---> Elapse 178711327 ticks (178.71 ms) (0.00 min) ...
---> Elapse 177744952 ticks (177.74 ms) (0.00 min) ...
---> Elapse 178503177 ticks (178.50 ms) (0.00 min) ...
---> Elapse 177637012 ticks (177.64 ms) (0.00 min) ...
---> Elapse 177574634 ticks (177.57 ms) (0.00 min) ...
---> Elapse 177149896 ticks (177.15 ms) (0.00 min) ...
---> Elapse 178983791 ticks (178.98 ms) (0.00 min) ...
---> Elapse 177712539 ticks (177.71 ms) (0.00 min) ...
---> Elapse 178620051 ticks (178.62 ms) (0.00 min) ...
---> Elapse 178487586 ticks (178.49 ms) (0.00 min) ...
Average: ---> Elapse 178215898 ticks (178.22 ms) (0.00 min) ...

===== NewDelete(1) =====
---> Elapse 59600378 ticks (59.60 ms) (0.00 min) ...
---> Elapse 60418109 ticks (60.42 ms) (0.00 min) ...
---> Elapse 60124627 ticks (60.12 ms) (0.00 min) ...
---> Elapse 59669931 ticks (59.67 ms) (0.00 min) ...
---> Elapse 60055694 ticks (60.06 ms) (0.00 min) ...
---> Elapse 60024992 ticks (60.02 ms) (0.00 min) ...
---> Elapse 60347888 ticks (60.35 ms) (0.00 min) ...
---> Elapse 60060293 ticks (60.06 ms) (0.00 min) ...
---> Elapse 60624331 ticks (60.62 ms) (0.00 min) ...
---> Elapse 60378184 ticks (60.38 ms) (0.00 min) ...
---> Elapse 59836192 ticks (59.84 ms) (0.00 min) ...
---> Elapse 60033045 ticks (60.03 ms) (0.00 min) ...
---> Elapse 60505688 ticks (60.51 ms) (0.00 min) ...
---> Elapse 59959021 ticks (59.96 ms) (0.00 min) ...
---> Elapse 60383854 ticks (60.38 ms) (0.00 min) ...
---> Elapse 59993257 ticks (59.99 ms) (0.00 min) ...
Average: ---> Elapse 60125967 ticks (60.13 ms) (0.00 min) ...
GeneralGood Work
Martin.Holzherr
0:39 22 Apr '08  
Memory Pools as used by your work even have further interesting
applications.
A promising application is hyper fast serialization of memory
to disk.
Have a look at the article <Backyard Hotrodding C++> from Walter Bright.
http://www.artima.com/cppsource/backyard.html[^]


Last Updated 4 May 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010