Some curiosities about speeddifferences for various allocationmethods

1 post / 0 new
OldFart
OldFart's picture
Offline
Last seen: 10 hours 33 min ago
Joined: 2010-11-30 14:09
Some curiosities about speeddifferences for various allocationmethods

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):

  1. INFO : Started
  2. INFO : -Iteration [ 0 ]
  3. INFO : -- malloc
  4. INFO : -- AllocVec
  5. INFO : -- AllocVecPooled nice
  6. INFO : -- AllocVecPooled brute
  7. INFO : -- ItemPoolAlloc nice
  8. INFO : -- ItemPoolAlloc brute
  9. INFO : -Iteration [ 1 ]
  10. INFO : -- malloc
  11. INFO : -- AllocVec
  12. INFO : -- AllocVecPooled nice
  13. INFO : -- AllocVecPooled brute
  14. INFO : -- ItemPoolAlloc nice
  15. INFO : -- ItemPoolAlloc brute
  16. INFO : -Iteration [ 2 ]
  17. INFO : -- malloc
  18. INFO : -- AllocVec
  19. INFO : -- AllocVecPooled nice
  20. INFO : -- AllocVecPooled brute
  21. INFO : -- ItemPoolAlloc nice
  22. INFO : -- ItemPoolAlloc brute
  23. INFO : -Iteration [ 3 ]
  24. INFO : -- malloc
  25. INFO : -- AllocVec
  26. INFO : -- AllocVecPooled nice
  27. INFO : -- AllocVecPooled brute
  28. INFO : -- ItemPoolAlloc nice
  29. INFO : -- ItemPoolAlloc brute
  30. INFO : -Iteration [ 4 ]
  31. INFO : -- malloc
  32. INFO : -- AllocVec
  33. INFO : -- AllocVecPooled nice
  34. INFO : -- AllocVecPooled brute
  35. INFO : -- ItemPoolAlloc nice
  36. INFO : -- ItemPoolAlloc brute
  37. INFO : -Iteration [ 5 ]
  38. INFO : -- malloc
  39. INFO : -- AllocVec
  40. INFO : -- AllocVecPooled nice
  41. INFO : -- AllocVecPooled brute
  42. INFO : -- ItemPoolAlloc nice
  43. INFO : -- ItemPoolAlloc brute
  44. INFO : -Iteration [ 6 ]
  45. INFO : -- malloc
  46. INFO : -- AllocVec
  47. INFO : -- AllocVecPooled nice
  48. INFO : -- AllocVecPooled brute
  49. INFO : -- ItemPoolAlloc nice
  50. INFO : -- ItemPoolAlloc brute
  51. INFO : -Iteration [ 7 ]
  52. INFO : -- malloc
  53. INFO : -- AllocVec
  54. INFO : -- AllocVecPooled nice
  55. INFO : -- AllocVecPooled brute
  56. INFO : -- ItemPoolAlloc nice
  57. INFO : -- ItemPoolAlloc brute
  58. INFO : -Iteration [ 8 ]
  59. INFO : -- malloc
  60. INFO : -- AllocVec
  61. INFO : -- AllocVecPooled nice
  62. INFO : -- AllocVecPooled brute
  63. INFO : -- ItemPoolAlloc nice
  64. INFO : -- ItemPoolAlloc brute
  65. INFO : -Iteration [ 9 ]
  66. INFO : -- malloc
  67. INFO : -- AllocVec
  68. INFO : -- AllocVecPooled nice
  69. INFO : -- AllocVecPooled brute
  70. INFO : -- ItemPoolAlloc nice
  71. INFO : -- ItemPoolAlloc brute
  72. INFO : -Iteration [ 10 ]
  73. INFO : -- malloc
  74. INFO : -- AllocVec
  75. INFO : -- AllocVecPooled nice
  76. INFO : -- AllocVecPooled brute
  77. INFO : -- ItemPoolAlloc nice
  78. INFO : -- ItemPoolAlloc brute
  79. INFO : -Iteration [ 11 ]
  80. INFO : -- malloc
  81. INFO : -- AllocVec
  82. INFO : -- AllocVecPooled nice
  83. INFO : -- AllocVecPooled brute
  84. INFO : -- ItemPoolAlloc nice
  85. INFO : -- ItemPoolAlloc brute
  86. INFO : -Iteration [ 12 ]
  87. INFO : -- malloc
  88. INFO : -- AllocVec
  89. INFO : -- AllocVecPooled nice
  90. INFO : -- AllocVecPooled brute
  91. INFO : -- ItemPoolAlloc nice
  92. INFO : -- ItemPoolAlloc brute
  93. INFO : -Iteration [ 13 ]
  94. INFO : -- malloc
  95. INFO : -- AllocVec
  96. INFO : -- AllocVecPooled nice
  97. INFO : -- AllocVecPooled brute
  98. INFO : -- ItemPoolAlloc nice
  99. INFO : -- ItemPoolAlloc brute
  100. INFO : -Iteration [ 14 ]
  101. INFO : -- malloc
  102. INFO : -- AllocVec
  103. INFO : -- AllocVecPooled nice
  104. INFO : -- AllocVecPooled brute
  105. INFO : -- ItemPoolAlloc nice
  106. INFO : -- ItemPoolAlloc brute
  107. INFO : -Iteration [ 15 ]
  108. INFO : -- malloc
  109. INFO : -- AllocVec
  110. INFO : -- AllocVecPooled nice
  111. INFO : -- AllocVecPooled brute
  112. INFO : -- ItemPoolAlloc nice
  113. INFO : -- ItemPoolAlloc brute
  114.  
  115. : Method Start Build Remove Done End Total
  116. : malloc [ 53184056 ] -- [ 53184109 ] -- [ 53365143 ] -- [ 53595826 ] -- [ 53595845 ] == [ 411789 ]
  117. : AllocVec [ 53623861 ] -- [ 53623898 ] -- [ 54376149 ] -- [ 54939848 ] -- [ 54939870 ] == [ 1316009 ]
  118. : MemPool nice [ 54969963 ] -- [ 54970181 ] -- [ 56333899 ] -- [ 57580586 ] -- [ 57580748 ] == [ 2610785 ]
  119. : MemPool brute [ 57614524 ] -- [ 57614703 ] -- [ 58976719 ] -- [ 58976737 ] -- [ 59514870 ] == [ 1900346 ]
  120. : ItemPool nice [ 59547492 ] -- [ 59547733 ] -- [ 59742363 ] -- [ 59826589 ] -- [ 59869667 ] == [ 322175 ]
  121. : ItemPool brute [ 60219450 ] -- [ 60400551 ] -- [ 60642973 ] -- [ 60642993 ] -- [ 60673755 ] == [ 454305 ]
  122. 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:

  1. /*
  2. **
  3. ** main.c - AllocationSpeed
  4. **
  5. **
  6. ** Jan 23, 2026: First incarnation
  7. **************************************/
  8. #include <stdlib.h>
  9. #include <time.h>
  10.  
  11. #include <proto/dos.h>
  12. #include <proto/exec.h>
  13.  
  14. void main(void)
  15. {
  16. clock_t TimeArray[5] [6] = {0};
  17. uint16 AlloCount;
  18.  
  19. struct List *L;
  20. struct Node *N,
  21. *R;
  22.  
  23. IDOS->Printf("INFO : Started\n");
  24.  
  25. for (uint16 i = 0; i < 16; i++)
  26. {
  27. IDOS->Printf("INFO : -Iteration [ %ld ]\n", i);
  28.  
  29.  
  30. IDOS->Printf("INFO : -- malloc\n");
  31. {
  32. TimeArray[0][0] += clock();
  33. AlloCount = 0;
  34.  
  35. if (L = malloc(sizeof(struct List)))
  36. {
  37. IExec->NewList(L);
  38.  
  39. TimeArray[0][1] += clock();
  40.  
  41. do
  42. {
  43. if (N = malloc(sizeof(struct Node)))
  44. {
  45. IExec->AddTail(L, N);
  46. }
  47. }
  48. while (++AlloCount);
  49.  
  50. TimeArray[0][2] += clock();
  51. N = IExec->GetHead(L);
  52.  
  53. while (N)
  54. {
  55. R = N;
  56. N = IExec->GetSucc(N);
  57.  
  58. IExec->Remove(R);
  59. free(R);
  60. }
  61.  
  62. TimeArray[0][3] += clock();
  63. free(L);
  64. }
  65.  
  66. TimeArray[0][4] += clock();
  67. }
  68.  
  69. /*
  70.   ** ---------------------------------------------------------------
  71.   */
  72.  
  73. IDOS->Printf("INFO : -- AllocVec\n");
  74. {
  75. TimeArray[1][0] += clock();
  76. AlloCount = 0;
  77.  
  78. if (L = IExec->AllocVecTags(sizeof(struct List), TAG_END))
  79. {
  80. IExec->NewList(L);
  81.  
  82. TimeArray[1][1] += clock();
  83.  
  84. do
  85. {
  86. if (N = IExec->AllocVecTags(sizeof(struct Node), TAG_END))
  87. {
  88. IExec->AddTail(L, N);
  89. }
  90. }
  91. while (++AlloCount);
  92.  
  93. TimeArray[1][2] += clock();
  94. N = IExec->GetHead(L);
  95.  
  96. while (N)
  97. {
  98. R = N;
  99. N = IExec->GetSucc(N);
  100.  
  101. IExec->Remove(R);
  102. IExec->FreeVec(R);
  103. }
  104.  
  105. TimeArray[1][3] += clock();
  106. IExec->FreeVec(L);
  107. }
  108.  
  109. TimeArray[1][4] += clock();
  110. }
  111.  
  112. /*
  113.   ** ---------------------------------------------------------------
  114.   */
  115.  
  116. {
  117. IDOS->Printf("INFO : -- AllocVecPooled nice\n");
  118. TimeArray[2][0] += clock();
  119. AlloCount = 0;
  120.  
  121. APTR MemPool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_CLEAR, TAG_END);
  122.  
  123. if (MemPool)
  124. {
  125. if (L = IExec->AllocVecPooled(MemPool, sizeof(struct List)))
  126. {
  127. IExec->NewList(L);
  128.  
  129. TimeArray[2][1] += clock();
  130.  
  131. do
  132. {
  133. if (N = IExec->AllocVecPooled(MemPool, sizeof(struct Node)))
  134. {
  135. IExec->AddTail(L, N);
  136. }
  137. }
  138. while (++AlloCount);
  139.  
  140. TimeArray[2][2] += clock();
  141. N = IExec->GetHead(L);
  142.  
  143. while (N)
  144. {
  145. R = N;
  146. N = IExec->GetSucc(N);
  147.  
  148. IExec->Remove(R);
  149. IExec->FreeVecPooled(MemPool, R);
  150. }
  151.  
  152. TimeArray[2][3] += clock();
  153. IExec->FreeVecPooled(MemPool, L);
  154. }
  155.  
  156. IExec->FreeSysObject(ASOT_MEMPOOL, MemPool);
  157. }
  158.  
  159. TimeArray[2][4] += clock();
  160. }
  161.  
  162. /*
  163.   ** ---------------------------------------------------------------
  164.   */
  165.  
  166. {
  167. IDOS->Printf("INFO : -- AllocVecPooled brute\n");
  168. TimeArray[3][0] += clock();
  169. AlloCount = 0;
  170.  
  171. APTR MemPool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_CLEAR, TAG_END);
  172.  
  173. if (MemPool)
  174. {
  175. if (L = IExec->AllocVecPooled(MemPool, sizeof(struct List)))
  176. {
  177. IExec->NewList(L);
  178.  
  179. TimeArray[3][1] += clock();
  180.  
  181. do
  182. {
  183. if (N = IExec->AllocVecPooled(MemPool, sizeof(struct Node)))
  184. {
  185. IExec->AddTail(L, N);
  186. }
  187. }
  188. while (++AlloCount);
  189.  
  190. TimeArray[3][2] += clock();
  191. TimeArray[3][3] += clock();
  192. IExec->FreeVecPooled(MemPool, L);
  193. }
  194.  
  195. IExec->FreeSysObject(ASOT_MEMPOOL, MemPool);
  196. }
  197.  
  198. TimeArray[3][4] += clock();
  199. }
  200.  
  201. /*
  202.   ** ---------------------------------------------------------------
  203.   */
  204.  
  205. {
  206. IDOS->Printf("INFO : -- ItemPoolAlloc nice\n");
  207. TimeArray[4][0] += clock();
  208. AlloCount = 0;
  209.  
  210. APTR MemPool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_CLEAR, TAG_END);
  211.  
  212. if (MemPool)
  213. {
  214. if (L = IExec->AllocVecPooled(MemPool, sizeof(struct List)))
  215. {
  216. IExec->NewList(L);
  217.  
  218. APTR ItemPool = IExec->AllocSysObjectTags(ASOT_ITEMPOOL, ASOITEM_MFlags, MEMF_CLEAR
  219. , ASOITEM_ItemSize, sizeof(struct Node)
  220. , TAG_END);
  221.  
  222. if (ItemPool)
  223. {
  224. TimeArray[4][1] += clock();
  225.  
  226. do
  227. {
  228. if (N = IExec->ItemPoolAlloc(ItemPool))
  229. {
  230. IExec->AddTail(L, N);
  231. }
  232. }
  233. while (++AlloCount);
  234.  
  235. TimeArray[4][2] += clock();
  236. N = IExec->GetHead(L);
  237.  
  238. while (N)
  239. {
  240. R = N;
  241. N = IExec->GetSucc(N);
  242.  
  243. IExec->Remove(R);
  244. IExec->ItemPoolFree(ItemPool, R);
  245. }
  246.  
  247. TimeArray[4][3] += clock();
  248. IExec->FreeSysObject(ASOT_ITEMPOOL, ItemPool);
  249. }
  250.  
  251. IExec->FreeVecPooled(MemPool, L);
  252. }
  253.  
  254. IExec->FreeSysObject(ASOT_MEMPOOL, MemPool);
  255. }
  256.  
  257. TimeArray[4][4] += clock();
  258. }
  259.  
  260. /*
  261.   ** ---------------------------------------------------------------
  262.   */
  263.  
  264. {
  265. IDOS->Printf("INFO : -- ItemPoolAlloc brute\n");
  266. TimeArray[5][0] += clock();
  267. AlloCount = 0;
  268.  
  269. APTR MemPool = IExec->AllocSysObjectTags(ASOT_MEMPOOL, ASOPOOL_MFlags, MEMF_CLEAR, TAG_END);
  270.  
  271. if (MemPool)
  272. {
  273. if (L = IExec->AllocVecPooled(MemPool, sizeof(struct List)))
  274. {
  275. IExec->NewList(L);
  276.  
  277. APTR ItemPool = IExec->AllocSysObjectTags(ASOT_ITEMPOOL, ASOITEM_MFlags, MEMF_CLEAR
  278. , ASOITEM_ItemSize, sizeof(struct Node)
  279. , TAG_END);
  280.  
  281. if (ItemPool)
  282. {
  283. TimeArray[5][1] += clock();
  284.  
  285. do
  286. {
  287. if (N = IExec->ItemPoolAlloc(ItemPool))
  288. {
  289. IExec->AddTail(L, N);
  290. }
  291. }
  292. while (++AlloCount);
  293.  
  294. TimeArray[5][2] += clock();
  295. TimeArray[5][3] += clock();
  296. IExec->FreeSysObject(ASOT_ITEMPOOL, ItemPool);
  297. }
  298.  
  299. IExec->FreeVecPooled(MemPool, L);
  300. }
  301.  
  302. IExec->FreeSysObject(ASOT_MEMPOOL, MemPool);
  303. }
  304.  
  305. TimeArray[5][4] += clock();
  306. }
  307.  
  308. } /* for() */
  309.  
  310. IDOS->Printf("\n : Method Start Build Remove Done End Total\n");
  311. 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]);
  312. 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]);
  313. 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]);
  314. 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]);
  315. 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]);
  316. 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]);
  317.  
  318. IDOS->Printf("INFO : Finished\n");
  319. }

And if you want to try it out for yourself, here's the applied makefile:

  1. PROGNAME = AllocationSpeed
  2.  
  3. DEFINES += -DDEBUG \
  4. -DPROGNAME=$(PROGNAME)
  5.  
  6. # -DUSE_ARGOPTS \
  7. # -DUSE_DATETIME
  8.  
  9. $(PROGNAME) : main.c
  10. gcc -o $(PROGNAME) main.c $(DEFINES)
  11. @Echo "==== Done compiling =========="

Surprising, no?

OldFart