time_pool_alloc.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. // Copyright (C) 2000, 2001 Stephen Cleary
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/pool/pool_alloc.hpp>
  7. #include <boost/pool/object_pool.hpp>
  8. #include <iostream>
  9. #include <vector>
  10. #include <list>
  11. #include <set>
  12. #include <ctime>
  13. #include <cerrno>
  14. #include "sys_allocator.hpp"
  15. unsigned long num_ints;
  16. unsigned long num_loops = 10;
  17. unsigned l;
  18. template <unsigned N>
  19. struct larger_structure
  20. {
  21. char data[N];
  22. };
  23. unsigned test_number;
  24. template <unsigned N>
  25. static void timing_test_alloc_larger()
  26. {
  27. typedef boost::fast_pool_allocator<larger_structure<N>,
  28. boost::default_user_allocator_new_delete,
  29. boost::details::pool::null_mutex> alloc;
  30. typedef boost::fast_pool_allocator<larger_structure<N> > alloc_sync;
  31. double end[1][6];
  32. std::clock_t start;
  33. start = std::clock();
  34. for(l = 0; l < num_loops; ++l)
  35. {
  36. std::allocator<larger_structure<N> > a;
  37. for (unsigned long i = 0; i < num_ints; ++i)
  38. a.deallocate(a.allocate(1), 1);
  39. }
  40. end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  41. start = std::clock();
  42. for(l = 0; l < num_loops; ++l)
  43. {
  44. for (unsigned long i = 0; i < num_ints; ++i)
  45. std::free(std::malloc(sizeof(larger_structure<N>)));
  46. }
  47. end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  48. start = std::clock();
  49. for(l = 0; l < num_loops; ++l)
  50. {
  51. for (unsigned long i = 0; i < num_ints; ++i)
  52. delete new (std::nothrow) larger_structure<N>;
  53. }
  54. end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  55. start = std::clock();
  56. for(l = 0; l < num_loops; ++l)
  57. {
  58. for (unsigned long i = 0; i < num_ints; ++i)
  59. alloc::deallocate(alloc::allocate());
  60. }
  61. end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  62. start = std::clock();
  63. for(l = 0; l < num_loops; ++l)
  64. {
  65. for (unsigned long i = 0; i < num_ints; ++i)
  66. alloc_sync::deallocate(alloc_sync::allocate());
  67. }
  68. end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  69. start = std::clock();
  70. for(l = 0; l < num_loops; ++l)
  71. {
  72. boost::pool<> p(sizeof(larger_structure<N>));
  73. for (unsigned long i = 0; i < num_ints; ++i)
  74. {
  75. void * const t = p.malloc();
  76. if (t != 0)
  77. p.free(t);
  78. }
  79. }
  80. end[0][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  81. std::cout << "Test " << test_number++ << ": Alloc & Dealloc " << num_ints << " structures of size " << sizeof(larger_structure<N>) << ":" << std::endl;
  82. std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
  83. std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
  84. std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
  85. std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
  86. std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
  87. std::cout << " Pool: " << end[0][5] << " seconds" << std::endl;
  88. }
  89. static void timing_test_alloc()
  90. {
  91. typedef boost::fast_pool_allocator<int,
  92. boost::default_user_allocator_new_delete,
  93. boost::details::pool::null_mutex> alloc;
  94. typedef boost::fast_pool_allocator<int> alloc_sync;
  95. double end[2][6];
  96. std::clock_t start;
  97. int ** p = new int*[num_ints];
  98. start = std::clock();
  99. for(l = 0; l < num_loops; ++l)
  100. {
  101. std::allocator<int> a;
  102. for (unsigned long i = 0; i < num_ints; ++i)
  103. a.deallocate(a.allocate(1), 1);
  104. }
  105. end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  106. start = std::clock();
  107. for(l = 0; l < num_loops; ++l)
  108. {
  109. for (unsigned long i = 0; i < num_ints; ++i)
  110. std::free(std::malloc(sizeof(int)));
  111. }
  112. end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  113. start = std::clock();
  114. for(l = 0; l < num_loops; ++l)
  115. {
  116. for (unsigned long i = 0; i < num_ints; ++i)
  117. delete new (std::nothrow) int;
  118. }
  119. end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  120. start = std::clock();
  121. for(l = 0; l < num_loops; ++l)
  122. {
  123. for (unsigned long i = 0; i < num_ints; ++i)
  124. alloc::deallocate(alloc::allocate());
  125. }
  126. end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  127. start = std::clock();
  128. for(l = 0; l < num_loops; ++l)
  129. {
  130. for (unsigned long i = 0; i < num_ints; ++i)
  131. alloc_sync::deallocate(alloc_sync::allocate());
  132. }
  133. end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  134. start = std::clock();
  135. for(l = 0; l < num_loops; ++l)
  136. {
  137. boost::pool<> p2(sizeof(int));
  138. for (unsigned long i = 0; i < num_ints; ++i)
  139. {
  140. void * const t = p2.malloc();
  141. if (t != 0)
  142. p2.free(t);
  143. }
  144. }
  145. end[0][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  146. start = std::clock();
  147. for(l = 0; l < num_loops; ++l)
  148. {
  149. std::allocator<int> a;
  150. for (unsigned long i = 0; i < num_ints; ++i)
  151. p[i] = a.allocate(1);
  152. for (unsigned long i = 0; i < num_ints; ++i)
  153. a.deallocate(p[i], 1);
  154. }
  155. end[1][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  156. start = std::clock();
  157. for(l = 0; l < num_loops; ++l)
  158. {
  159. for (unsigned long i = 0; i < num_ints; ++i)
  160. p[i] = (int *) std::malloc(sizeof(int));
  161. for (unsigned long i = 0; i < num_ints; ++i)
  162. std::free(p[i]);
  163. }
  164. end[1][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  165. start = std::clock();
  166. for(l = 0; l < num_loops; ++l)
  167. {
  168. for (unsigned long i = 0; i < num_ints; ++i)
  169. p[i] = new (std::nothrow) int;
  170. for (unsigned long i = 0; i < num_ints; ++i)
  171. delete p[i];
  172. }
  173. end[1][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  174. start = std::clock();
  175. for(l = 0; l < num_loops; ++l)
  176. {
  177. for (unsigned long i = 0; i < num_ints; ++i)
  178. p[i] = alloc::allocate();
  179. for (unsigned long i = 0; i < num_ints; ++i)
  180. alloc::deallocate(p[i]);
  181. }
  182. end[1][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  183. start = std::clock();
  184. for(l = 0; l < num_loops; ++l)
  185. {
  186. for (unsigned long i = 0; i < num_ints; ++i)
  187. p[i] = alloc_sync::allocate();
  188. for (unsigned long i = 0; i < num_ints; ++i)
  189. alloc_sync::deallocate(p[i]);
  190. }
  191. end[1][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  192. start = std::clock();
  193. for(l = 0; l < num_loops; ++l)
  194. {
  195. boost::pool<> pl(sizeof(int));
  196. for (unsigned long i = 0; i < num_ints; ++i)
  197. p[i] = reinterpret_cast<int *>(pl.malloc());
  198. for (unsigned long i = 0; i < num_ints; ++i)
  199. if (p[i] != 0)
  200. pl.free(p[i]);
  201. }
  202. end[1][5] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  203. delete [] p;
  204. std::cout << "Test 3: Alloc & Dealloc " << num_ints << " ints:" << std::endl;
  205. std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
  206. std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
  207. std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
  208. std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
  209. std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
  210. std::cout << " Pool: " << end[0][5] << " seconds" << std::endl;
  211. std::cout << "Test 4: Alloc " << num_ints << " ints & Dealloc " << num_ints << " ints:" << std::endl;
  212. std::cout << " std::allocator: " << end[1][0] << " seconds" << std::endl;
  213. std::cout << " malloc/free: " << end[1][1] << " seconds" << std::endl;
  214. std::cout << " new/delete: " << end[1][2] << " seconds" << std::endl;
  215. std::cout << " Pool Alloc: " << end[1][3] << " seconds" << std::endl;
  216. std::cout << " Pool /w Sync: " << end[1][4] << " seconds" << std::endl;
  217. std::cout << " Pool: " << end[1][5] << " seconds" << std::endl;
  218. }
  219. static void timing_test_containers()
  220. {
  221. typedef boost::pool_allocator<int,
  222. boost::default_user_allocator_new_delete,
  223. boost::details::pool::null_mutex> alloc;
  224. typedef boost::pool_allocator<int> alloc_sync;
  225. typedef boost::fast_pool_allocator<int,
  226. boost::default_user_allocator_new_delete,
  227. boost::details::pool::null_mutex> fast_alloc;
  228. typedef boost::fast_pool_allocator<int> fast_alloc_sync;
  229. double end[3][5];
  230. std::clock_t start;
  231. start = std::clock();
  232. for(l = 0; l < num_loops; ++l)
  233. {
  234. std::vector<int, std::allocator<int> > x;
  235. for (unsigned long i = 0; i < num_ints; ++i)
  236. x.push_back(0);
  237. }
  238. end[0][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  239. start = std::clock();
  240. for(l = 0; l < num_loops; ++l)
  241. {
  242. std::vector<int, malloc_allocator<int> > x;
  243. for (unsigned long i = 0; i < num_ints; ++i)
  244. x.push_back(0);
  245. }
  246. end[0][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  247. start = std::clock();
  248. for(l = 0; l < num_loops; ++l)
  249. {
  250. std::vector<int, new_delete_allocator<int> > x;
  251. for (unsigned long i = 0; i < num_ints; ++i)
  252. x.push_back(0);
  253. }
  254. end[0][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  255. start = std::clock();
  256. for(l = 0; l < num_loops; ++l)
  257. {
  258. std::vector<int, alloc> x;
  259. for (unsigned long i = 0; i < num_ints; ++i)
  260. x.push_back(0);
  261. }
  262. end[0][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  263. start = std::clock();
  264. for(l = 0; l < num_loops; ++l)
  265. {
  266. std::vector<int, alloc_sync> x;
  267. for (unsigned long i = 0; i < num_ints; ++i)
  268. x.push_back(0);
  269. }
  270. end[0][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  271. start = std::clock();
  272. for(l = 0; l < num_loops; ++l)
  273. {
  274. std::set<int, std::less<int>, std::allocator<int> > x;
  275. for (unsigned long i = 0; i < num_ints; ++i)
  276. x.insert(0);
  277. }
  278. end[1][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  279. start = std::clock();
  280. for(l = 0; l < num_loops; ++l)
  281. {
  282. std::set<int, std::less<int>, malloc_allocator<int> > x;
  283. for (unsigned long i = 0; i < num_ints; ++i)
  284. x.insert(0);
  285. }
  286. end[1][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  287. start = std::clock();
  288. for(l = 0; l < num_loops; ++l)
  289. {
  290. std::set<int, std::less<int>, new_delete_allocator<int> > x;
  291. for (unsigned long i = 0; i < num_ints; ++i)
  292. x.insert(0);
  293. }
  294. end[1][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  295. start = std::clock();
  296. for(l = 0; l < num_loops; ++l)
  297. {
  298. std::set<int, std::less<int>, fast_alloc> x;
  299. for (unsigned long i = 0; i < num_ints; ++i)
  300. x.insert(0);
  301. }
  302. end[1][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  303. start = std::clock();
  304. for(l = 0; l < num_loops; ++l)
  305. {
  306. std::set<int, std::less<int>, fast_alloc_sync> x;
  307. for (unsigned long i = 0; i < num_ints; ++i)
  308. x.insert(0);
  309. }
  310. end[1][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  311. start = std::clock();
  312. for(l = 0; l < num_loops; ++l)
  313. {
  314. std::list<int, std::allocator<int> > x;
  315. for (unsigned long i = 0; i < num_ints; ++i)
  316. x.push_back(0);
  317. }
  318. end[2][0] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  319. start = std::clock();
  320. for(l = 0; l < num_loops; ++l)
  321. {
  322. std::list<int, malloc_allocator<int> > x;
  323. for (unsigned long i = 0; i < num_ints; ++i)
  324. x.push_back(0);
  325. }
  326. end[2][1] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  327. start = std::clock();
  328. for(l = 0; l < num_loops; ++l)
  329. {
  330. std::list<int, new_delete_allocator<int> > x;
  331. for (unsigned long i = 0; i < num_ints; ++i)
  332. x.push_back(0);
  333. }
  334. end[2][2] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  335. start = std::clock();
  336. for(l = 0; l < num_loops; ++l)
  337. {
  338. std::list<int, fast_alloc> x;
  339. for (unsigned long i = 0; i < num_ints; ++i)
  340. x.push_back(0);
  341. }
  342. end[2][3] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  343. start = std::clock();
  344. for(l = 0; l < num_loops; ++l)
  345. {
  346. std::list<int, fast_alloc_sync> x;
  347. for (unsigned long i = 0; i < num_ints; ++i)
  348. x.push_back(0);
  349. }
  350. end[2][4] = (std::clock() - start) / ((double) CLOCKS_PER_SEC);
  351. std::cout << "Test 0: Insertion & deletion of " << num_ints << " ints in a vector:" << std::endl;
  352. std::cout << " std::allocator: " << end[0][0] << " seconds" << std::endl;
  353. std::cout << " malloc/free: " << end[0][1] << " seconds" << std::endl;
  354. std::cout << " new/delete: " << end[0][2] << " seconds" << std::endl;
  355. std::cout << " Pool Alloc: " << end[0][3] << " seconds" << std::endl;
  356. std::cout << " Pool /w Sync: " << end[0][4] << " seconds" << std::endl;
  357. std::cout << " Pool: not possible" << std::endl;
  358. std::cout << "Test 1: Insertion & deletion of " << num_ints << " ints in a set:" << std::endl;
  359. std::cout << " std::allocator: " << end[1][0] << " seconds" << std::endl;
  360. std::cout << " malloc/free: " << end[1][1] << " seconds" << std::endl;
  361. std::cout << " new/delete: " << end[1][2] << " seconds" << std::endl;
  362. std::cout << " Pool Alloc: " << end[1][3] << " seconds" << std::endl;
  363. std::cout << " Pool /w Sync: " << end[1][4] << " seconds" << std::endl;
  364. std::cout << " Pool: not possible" << std::endl;
  365. std::cout << "Test 2: Insertion & deletion of " << num_ints << " ints in a list:" << std::endl;
  366. std::cout << " std::allocator: " << end[2][0] << " seconds" << std::endl;
  367. std::cout << " malloc/free: " << end[2][1] << " seconds" << std::endl;
  368. std::cout << " new/delete: " << end[2][2] << " seconds" << std::endl;
  369. std::cout << " Pool Alloc: " << end[2][3] << " seconds" << std::endl;
  370. std::cout << " Pool /w Sync: " << end[2][4] << " seconds" << std::endl;
  371. std::cout << " Pool: not possible" << std::endl;
  372. }
  373. int main(int argc, char * argv[])
  374. {
  375. if (argc != 1 && argc != 2)
  376. {
  377. std::cerr << "Usage: " << argv[0]
  378. << " [number_of_ints_to_use_each_try]" << std::endl;
  379. return 1;
  380. }
  381. errno = 0;
  382. if (argc == 2)
  383. {
  384. num_ints = std::strtoul(argv[1], 0, 10);
  385. if (errno != 0)
  386. {
  387. std::cerr << "Cannot convert number \"" << argv[1] << '"' << std::endl;
  388. return 2;
  389. }
  390. }
  391. else
  392. num_ints = 700000;
  393. #ifndef _NDEBUG
  394. num_ints /= 100;
  395. #endif
  396. try
  397. {
  398. timing_test_containers();
  399. timing_test_alloc();
  400. test_number = 5;
  401. timing_test_alloc_larger<64>();
  402. test_number = 6;
  403. timing_test_alloc_larger<256>();
  404. test_number = 7;
  405. timing_test_alloc_larger<4096>();
  406. }
  407. catch (const std::bad_alloc &)
  408. {
  409. std::cerr << "Timing tests ran out of memory; try again with a lower value for number of ints"
  410. << " (current value is " << num_ints << ")" << std::endl;
  411. return 3;
  412. }
  413. catch (const std::exception & e)
  414. {
  415. std::cerr << "Error: " << e.what() << std::endl;
  416. return 4;
  417. }
  418. catch (...)
  419. {
  420. std::cerr << "Unknown error" << std::endl;
  421. return 5;
  422. }
  423. return 0;
  424. }
  425. /*
  426. Output:
  427. MSVC 10.0 using mutli-threaded DLL
  428. time_pool_alloc.cpp
  429. Creating library J:\Cpp\pool\pool\Release\alloc_example.lib and object J:\Cpp\pool\pool\Release\alloc_example.exp
  430. Generating code
  431. Finished generating code
  432. alloc_example.vcxproj -> J:\Cpp\pool\pool\Release\alloc_example.exe
  433. Test 0: Insertion & deletion of 700000 ints in a vector:
  434. std::allocator: 0.062 seconds
  435. malloc/free: 0.078 seconds
  436. new/delete: 0.078 seconds
  437. Pool Alloc: 0.328 seconds
  438. Pool /w Sync: 0.343 seconds
  439. Pool: not possible
  440. Test 1: Insertion & deletion of 700000 ints in a set:
  441. std::allocator: 0.561 seconds
  442. malloc/free: 0.546 seconds
  443. new/delete: 0.562 seconds
  444. Pool Alloc: 0.109 seconds
  445. Pool /w Sync: 0.094 seconds
  446. Pool: not possible
  447. Test 2: Insertion & deletion of 700000 ints in a list:
  448. std::allocator: 0.671 seconds
  449. malloc/free: 0.67 seconds
  450. new/delete: 0.671 seconds
  451. Pool Alloc: 0.094 seconds
  452. Pool /w Sync: 0.093 seconds
  453. Pool: not possible
  454. Test 3: Alloc & Dealloc 700000 ints:
  455. std::allocator: 0.5 seconds
  456. malloc/free: 0.468 seconds
  457. new/delete: 0.592 seconds
  458. Pool Alloc: 0.032 seconds
  459. Pool /w Sync: 0.015 seconds
  460. Pool: 0.016 seconds
  461. Test 4: Alloc 700000 ints & Dealloc 700000 ints:
  462. std::allocator: 0.593 seconds
  463. malloc/free: 0.577 seconds
  464. new/delete: 0.717 seconds
  465. Pool Alloc: 0.032 seconds
  466. Pool /w Sync: 0.031 seconds
  467. Pool: 0.047 seconds
  468. Test 5: Alloc & Dealloc 700000 structures of size 64:
  469. std::allocator: 0.499 seconds
  470. malloc/free: 0.483 seconds
  471. new/delete: 0.624 seconds
  472. Pool Alloc: 0.016 seconds
  473. Pool /w Sync: 0.031 seconds
  474. Pool: 0.016 seconds
  475. Test 6: Alloc & Dealloc 700000 structures of size 256:
  476. std::allocator: 0.499 seconds
  477. malloc/free: 0.484 seconds
  478. new/delete: 0.639 seconds
  479. Pool Alloc: 0.016 seconds
  480. Pool /w Sync: 0.015 seconds
  481. Pool: 0.016 seconds
  482. Test 7: Alloc & Dealloc 700000 structures of size 4096:
  483. std::allocator: 0.515 seconds
  484. malloc/free: 0.515 seconds
  485. new/delete: 0.639 seconds
  486. Pool Alloc: 0.031 seconds
  487. Pool /w Sync: 0.016 seconds
  488. Pool: 0.016 seconds
  489. */