Hi,
Just out of sheer curiosity I decided to build a little proggy to see what the differences would be in speed for the various available ways we can allocate memory. For this test I decided to, per method, build a list with 65536 nodes and subsequently deallocate every node again and that 16 times in succession. The results were quite 'staggering' to say the least (according to these results):
INFO : Started INFO : -Iteration [ 0 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 1 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 2 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 3 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 4 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 5 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 6 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 7 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 8 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 9 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 10 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 11 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 12 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 13 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 14 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute INFO : -Iteration [ 15 ] INFO : -- malloc INFO : -- AllocVec INFO : -- AllocVecPooled nice INFO : -- AllocVecPooled brute INFO : -- ItemPoolAlloc nice INFO : -- ItemPoolAlloc brute : Method Start Build Remove Done End Total : malloc [ 53184056 ] -- [ 53184109 ] -- [ 53365143 ] -- [ 53595826 ] -- [ 53595845 ] == [ 411789 ] : AllocVec [ 53623861 ] -- [ 53623898 ] -- [ 54376149 ] -- [ 54939848 ] -- [ 54939870 ] == [ 1316009 ] : MemPool nice [ 54969963 ] -- [ 54970181 ] -- [ 56333899 ] -- [ 57580586 ] -- [ 57580748 ] == [ 2610785 ] : MemPool brute [ 57614524 ] -- [ 57614703 ] -- [ 58976719 ] -- [ 58976737 ] -- [ 59514870 ] == [ 1900346 ] : ItemPool nice [ 59547492 ] -- [ 59547733 ] -- [ 59742363 ] -- [ 59826589 ] -- [ 59869667 ] == [ 322175 ] : ItemPool brute [ 60219450 ] -- [ 60400551 ] -- [ 60642973 ] -- [ 60642993 ] -- [ 60673755 ] == [ 454305 ] INFO : Finished
The results for both variants of 'ItemPool' are surprising: deallocating all nodes on a one by one base, the nice way, seems to be faster then the 'brute' way, the latter one taking around 40% MORE time to complete, 454305 for brute vs 322175 for noce.
The program Is this one:
/* ** ** main.c - AllocationSpeed ** ** ** Jan 23, 2026: First incarnation **************************************/ #include <stdlib.h> #include <time.h> #include <proto/dos.h> #include <proto/exec.h> void main(void) { clock_t TimeArray[5] [6] = {0}; uint16 AlloCount; struct List *L; struct Node *N, *R; IDOS->Printf("INFO : Started\n"); for (uint16 i = 0; i < 16; i++) { IDOS->Printf("INFO : -Iteration [ %ld ]\n", i); IDOS->Printf("INFO : -- malloc\n"); { TimeArray[0][0] += clock(); AlloCount = 0; if (L = malloc(sizeof(struct List))) { IExec->NewList(L); TimeArray[0][1] += clock(); do { if (N = malloc(sizeof(struct Node))) { IExec->AddTail(L, N); } } while (++AlloCount); TimeArray[0][2] += clock(); N = IExec->GetHead(L); while (N) { R = N; N = IExec->GetSucc(N); IExec->Remove(R); free(R); } TimeArray[0][3] += clock(); free(L); } TimeArray[0][4] += clock(); } /* ** --------------------------------------------------------------- */ IDOS->Printf("INFO : -- AllocVec\n"); { TimeArray[1][0] += clock(); AlloCount = 0; if (L = IExec->AllocVecTags(sizeof(struct List), TAG_END)) { IExec->NewList(L); TimeArray[1][1] += clock(); do { if (N = IExec->AllocVecTags(sizeof(struct Node), TAG_END)) { IExec->AddTail(L, N); } } while (++AlloCount); TimeArray[1][2] += clock(); N = IExec->GetHead(L); while (N) { R = N; N = IExec->GetSucc(N); IExec->Remove(R); IExec->FreeVec(R); } TimeArray[1][3] += clock(); IExec->FreeVec(L); } TimeArray[1][4] += clock(); } /* ** --------------------------------------------------------------- */ { IDOS->Printf("INFO : -- AllocVecPooled nice\n"); TimeArray[2][0] += clock(); AlloCount = 0; APTR MemPool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_CLEAR, TAG_END); if (MemPool) { if (L = IExec->AllocVecPooled(MemPool, sizeof(struct List))) { IExec->NewList(L); TimeArray[2][1] += clock(); do { if (N = IExec->AllocVecPooled(MemPool, sizeof(struct Node))) { IExec->AddTail(L, N); } } while (++AlloCount); TimeArray[2][2] += clock(); N = IExec->GetHead(L); while (N) { R = N; N = IExec->GetSucc(N); IExec->Remove(R); IExec->FreeVecPooled(MemPool, R); } TimeArray[2][3] += clock(); IExec->FreeVecPooled(MemPool, L); } IExec->FreeSysObject(ASOT_MEMPOOL, MemPool); } TimeArray[2][4] += clock(); } /* ** --------------------------------------------------------------- */ { IDOS->Printf("INFO : -- AllocVecPooled brute\n"); TimeArray[3][0] += clock(); AlloCount = 0; APTR MemPool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_CLEAR, TAG_END); if (MemPool) { if (L = IExec->AllocVecPooled(MemPool, sizeof(struct List))) { IExec->NewList(L); TimeArray[3][1] += clock(); do { if (N = IExec->AllocVecPooled(MemPool, sizeof(struct Node))) { IExec->AddTail(L, N); } } while (++AlloCount); TimeArray[3][2] += clock(); TimeArray[3][3] += clock(); IExec->FreeVecPooled(MemPool, L); } IExec->FreeSysObject(ASOT_MEMPOOL, MemPool); } TimeArray[3][4] += clock(); } /* ** --------------------------------------------------------------- */ { IDOS->Printf("INFO : -- ItemPoolAlloc nice\n"); TimeArray[4][0] += clock(); AlloCount = 0; APTR MemPool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_CLEAR, TAG_END); if (MemPool) { if (L = IExec->AllocVecPooled(MemPool, sizeof(struct List))) { IExec->NewList(L); APTR ItemPool = IExec->AllocSysObjectTags(ASOT_ITEMPOOL, ASOITEM_MFlags, MEMF_CLEAR , ASOITEM_ItemSize, sizeof(struct Node) , TAG_END); if (ItemPool) { TimeArray[4][1] += clock(); do { if (N = IExec->ItemPoolAlloc(ItemPool)) { IExec->AddTail(L, N); } } while (++AlloCount); TimeArray[4][2] += clock(); N = IExec->GetHead(L); while (N) { R = N; N = IExec->GetSucc(N); IExec->Remove(R); IExec->ItemPoolFree(ItemPool, R); } TimeArray[4][3] += clock(); IExec->FreeSysObject(ASOT_ITEMPOOL, ItemPool); } IExec->FreeVecPooled(MemPool, L); } IExec->FreeSysObject(ASOT_MEMPOOL, MemPool); } TimeArray[4][4] += clock(); } /* ** --------------------------------------------------------------- */ { IDOS->Printf("INFO : -- ItemPoolAlloc brute\n"); TimeArray[5][0] += clock(); AlloCount = 0; APTR MemPool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_CLEAR, TAG_END); if (MemPool) { if (L = IExec->AllocVecPooled(MemPool, sizeof(struct List))) { IExec->NewList(L); APTR ItemPool = IExec->AllocSysObjectTags(ASOT_ITEMPOOL, ASOITEM_MFlags, MEMF_CLEAR , ASOITEM_ItemSize, sizeof(struct Node) , TAG_END); if (ItemPool) { TimeArray[5][1] += clock(); do { if (N = IExec->ItemPoolAlloc(ItemPool)) { IExec->AddTail(L, N); } } while (++AlloCount); TimeArray[5][2] += clock(); TimeArray[5][3] += clock(); IExec->FreeSysObject(ASOT_ITEMPOOL, ItemPool); } IExec->FreeVecPooled(MemPool, L); } IExec->FreeSysObject(ASOT_MEMPOOL, MemPool); } TimeArray[5][4] += clock(); } } /* for() */ IDOS->Printf("\n : Method Start Build Remove Done End Total\n"); IDOS->Printf(" : malloc [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] == [ %8lld ]\n", TimeArray[0][0], TimeArray[0][1], TimeArray[0][2], TimeArray[0][3], TimeArray[0][4], TimeArray[0][4] - TimeArray[0][0]); IDOS->Printf(" : AllocVec [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] == [ %8lld ]\n", TimeArray[1][0], TimeArray[1][1], TimeArray[1][2], TimeArray[1][3], TimeArray[1][4], TimeArray[1][4] - TimeArray[1][0]); IDOS->Printf(" : MemPool nice [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] == [ %8lld ]\n", TimeArray[2][0], TimeArray[2][1], TimeArray[2][2], TimeArray[2][3], TimeArray[2][4], TimeArray[2][4] - TimeArray[2][0]); IDOS->Printf(" : MemPool brute [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] == [ %8lld ]\n", TimeArray[3][0], TimeArray[3][1], TimeArray[3][2], TimeArray[3][3], TimeArray[3][4], TimeArray[3][4] - TimeArray[3][0]); IDOS->Printf(" : ItemPool nice [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] == [ %8lld ]\n", TimeArray[4][0], TimeArray[4][1], TimeArray[4][2], TimeArray[4][3], TimeArray[4][4], TimeArray[4][4] - TimeArray[4][0]); IDOS->Printf(" : ItemPool brute [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] -- [ %lld ] == [ %8lld ]\n", TimeArray[5][0], TimeArray[5][1], TimeArray[5][2], TimeArray[5][3], TimeArray[5][4], TimeArray[5][4] - TimeArray[5][0]); IDOS->Printf("INFO : Finished\n"); }
And if you want to try it out for yourself, here's the applied makefile:
PROGNAME = AllocationSpeed DEFINES += -DDEBUG \ -DPROGNAME=$(PROGNAME) # -DUSE_ARGOPTS \ # -DUSE_DATETIME $(PROGNAME) : main.c gcc -o $(PROGNAME) main.c $(DEFINES) @Echo "==== Done compiling =========="
Surprising, no?
OldFart
