larson.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /* Original version in Hoard Memory Allocator v2.1.2d
  2. *
  3. * This is a UNIX port of the latest version of the benchmark described
  4. * by Larson & Krishnan in "Memory Allocation for Long-Running Server
  5. * Applications", ISMM 1998.
  6. *
  7. * To see how it scales, try the following parameters, where P = 1 and
  8. * then the number of processors on your system, for larson and
  9. * larson_hoard:
  10. *
  11. * Multi-threaded test driver
  12. * C++ version (new and delete)
  13. * runtime (sec): 30
  14. * chunk size (min,max): 8 16
  15. * threads (min, max): P P
  16. * chunks/thread: 10000
  17. * no of rounds: 10
  18. * random seed: 1
  19. */
  20. #include <pthread.h>
  21. #include <stdio.h>
  22. #include <sys/time.h>
  23. #include <string.h>
  24. #include <assert.h>
  25. #include <unistd.h>
  26. /* #include <stdlib.h> */
  27. #include <dmmlib/dmmlib.h>
  28. /* #include <dmmlib/print_stats.h> */
  29. #include "lran2.h"
  30. #define MAX_THREADS 100
  31. #define MAX_BLOCKS 1000000
  32. #ifndef BOOLEAN
  33. #define BOOLEAN
  34. enum BOOLEAN { FALSE, TRUE };
  35. #endif /* BOOLEAN */
  36. typedef void * LPVOID;
  37. typedef unsigned long ULONG;
  38. typedef long long _int64;
  39. typedef void * VoidFunction (void *);
  40. typedef struct thr_data {
  41. int threadno;
  42. int NumBlocks;
  43. long seed;
  44. int min_size;
  45. int max_size;
  46. char **array;
  47. long *blksize;
  48. int asize;
  49. int cAllocs;
  50. int cFrees;
  51. int cThreads;
  52. int cBytesAlloced;
  53. volatile int finished;
  54. struct lran2_st rgen;
  55. } thread_data;
  56. int volatile stopflag = FALSE;
  57. int min_size = 10, max_size = 500;
  58. struct lran2_st rgen;
  59. char *blkp[MAX_BLOCKS];
  60. long blksize[MAX_BLOCKS];
  61. static void QueryPerformanceFrequency(long *x) {
  62. *x = 1000000L;
  63. }
  64. static void QueryPerformanceCounter (long *x) {
  65. struct timeval tv;
  66. gettimeofday(&tv, NULL);
  67. *x = tv.tv_sec * 1000000L + tv.tv_usec;
  68. }
  69. static void Sleep(long x) {
  70. // printf ("sleeping for %ld seconds.\n", x/1000);
  71. sleep((unsigned int) (x/1000));
  72. }
  73. static void _beginthread(VoidFunction x, void * z) {
  74. pthread_t pt;
  75. pthread_attr_t pa;
  76. pthread_attr_init (&pa);
  77. // printf ("creating a thread.\n");
  78. pthread_create(&pt, &pa, x, z);
  79. }
  80. static void warmup(char **blkp, int num_chunks) {
  81. int cblks;
  82. long victim;
  83. long blk_size;
  84. LPVOID tmp;
  85. for(cblks = 0; cblks < num_chunks; cblks++) {
  86. blk_size = min_size + lran2(&rgen) % (max_size - min_size);
  87. blkp[cblks] = (char *) dmmlib_malloc((size_t) blk_size);
  88. blksize[cblks] = blk_size;
  89. assert(blkp[cblks] != NULL);
  90. }
  91. /* generate a random permutation of the chunks */
  92. for(cblks = num_chunks; cblks > 0 ; cblks--) {
  93. victim = lran2(&rgen) % cblks;
  94. tmp = blkp[victim];
  95. blkp[victim] = blkp[cblks-1];
  96. blkp[cblks-1] = (char *) tmp;
  97. }
  98. for(cblks=0; cblks < 4 * num_chunks; cblks++) {
  99. victim = lran2(&rgen) % num_chunks;
  100. dmmlib_free(blkp[victim]);
  101. blk_size = min_size + lran2(&rgen) % (max_size - min_size);
  102. blkp[victim] = (char *) dmmlib_malloc((size_t) blk_size);
  103. blksize[victim] = blk_size;
  104. assert(blkp[victim] != NULL);
  105. }
  106. }
  107. static void * exercise_heap( void *pinput) {
  108. thread_data *pdea;
  109. int cblks = 0;
  110. long victim;
  111. long blk_size;
  112. int range;
  113. if( stopflag ) return 0;
  114. pdea = (thread_data *) pinput;
  115. pdea->finished = FALSE;
  116. pdea->cThreads++;
  117. range = pdea->max_size - pdea->min_size;
  118. /* allocate NumBlocks chunks of random size */
  119. for(cblks=0; cblks < pdea->NumBlocks; cblks++) {
  120. victim = lran2(&pdea->rgen)%pdea->asize;
  121. dmmlib_free(pdea->array[victim]);
  122. pdea->cFrees++;
  123. blk_size = pdea->min_size+lran2(&pdea->rgen)%range;
  124. pdea->array[victim] = (char *) dmmlib_malloc((size_t) blk_size);
  125. pdea->blksize[victim] = blk_size;
  126. assert(pdea->array[victim] != NULL);
  127. pdea->cAllocs++;
  128. /* Write something! */
  129. volatile char * chptr = ((char *) pdea->array[victim]);
  130. *chptr++ = 'a';
  131. volatile char ch = *((char *) pdea->array[victim]);
  132. *chptr = 'b';
  133. if( stopflag ) break;
  134. }
  135. // printf("Thread %u terminating: %d allocs, %d frees\n",
  136. // pdea->threadno, pdea->cAllocs, pdea->cFrees) ;
  137. pdea->finished = TRUE;
  138. if( !stopflag ) {
  139. _beginthread(exercise_heap, pdea);
  140. }
  141. return 0;
  142. }
  143. static void runthreads(long sleep_cnt, int min_threads, int max_threads, int chperthread, int num_rounds) {
  144. thread_data de_area[MAX_THREADS];
  145. thread_data *pdea;
  146. long ticks_per_sec;
  147. int prevthreads;
  148. int num_threads;
  149. int nperthread;
  150. int sum_threads;
  151. int sum_allocs;
  152. int sum_frees;
  153. int i;
  154. long start_cnt, end_cnt;
  155. _int64 ticks;
  156. double duration ;
  157. double rate_1 = 0, rate_n;
  158. size_t reqd_space;
  159. size_t used_space;
  160. QueryPerformanceFrequency( &ticks_per_sec );
  161. pdea = &de_area[0];
  162. memset(&de_area[0], 0, sizeof(thread_data));
  163. prevthreads = 0 ;
  164. for(num_threads=min_threads; num_threads <= max_threads; num_threads++) {
  165. warmup(&blkp[prevthreads*chperthread], (num_threads-prevthreads)*chperthread );
  166. nperthread = chperthread ;
  167. stopflag = FALSE ;
  168. for(i = 0; i < num_threads; i++) {
  169. de_area[i].threadno = i+1 ;
  170. de_area[i].NumBlocks = num_rounds*nperthread;
  171. de_area[i].array = &blkp[i*nperthread];
  172. de_area[i].blksize = &blksize[i*nperthread];
  173. de_area[i].asize = nperthread;
  174. de_area[i].min_size = min_size;
  175. de_area[i].max_size = max_size;
  176. de_area[i].seed = lran2(&rgen);
  177. de_area[i].finished = 0;
  178. de_area[i].cAllocs = 0;
  179. de_area[i].cFrees = 0;
  180. de_area[i].cThreads = 0;
  181. de_area[i].finished = FALSE;
  182. lran2_init(&de_area[i].rgen, de_area[i].seed);
  183. _beginthread(exercise_heap, &de_area[i]);
  184. }
  185. QueryPerformanceCounter( &start_cnt );
  186. printf ("Sleeping for %ld seconds.\n", sleep_cnt);
  187. Sleep(sleep_cnt * 1000L) ;
  188. stopflag = TRUE ;
  189. for(i = 0; i < num_threads; i++) {
  190. while( !de_area[i].finished ) {
  191. sched_yield();
  192. }
  193. }
  194. QueryPerformanceCounter( &end_cnt );
  195. sum_frees = sum_allocs =0 ;
  196. sum_threads = 0 ;
  197. for(i=0;i< num_threads; i++){
  198. sum_allocs += de_area[i].cAllocs ;
  199. sum_frees += de_area[i].cFrees ;
  200. sum_threads += de_area[i].cThreads ;
  201. de_area[i].cAllocs = de_area[i].cFrees = 0;
  202. }
  203. ticks = end_cnt - start_cnt ;
  204. duration = (double)(ticks/ticks_per_sec);
  205. for(i = 0; i < num_threads; i++) {
  206. if( !de_area[i].finished ) {
  207. printf("Thread at %d not finished\n", i);
  208. }
  209. }
  210. rate_n = sum_allocs/duration ;
  211. if( rate_1 == 0){
  212. rate_1 = rate_n ;
  213. }
  214. //reqd_space = (0.5*(min_size+max_size)*num_threads*chperthread) ;
  215. //used_space = CountReservedSpace() - init_space;
  216. // FIXME Currently only one heap is used in the example
  217. /* used_space = get_allocated_space(&systemallocator.heaps[0]); */
  218. /* reqd_space = get_used_space(&systemallocator.heaps[0]); */
  219. //used_space = 0;
  220. printf(" Used space: %zu\n Requested space: %zu\n", used_space, reqd_space);
  221. printf("%2d ", num_threads ) ;
  222. printf("%6.3f", duration ) ;
  223. printf("%6.3f", rate_n/rate_1 );
  224. printf("%8.0f", sum_allocs/duration);
  225. /* printf(" %6.3f %.3f", (double)(used_space/(1024*1024)), (used_space/reqd_space)); */
  226. printf("\n") ;
  227. Sleep(5000L) ; // wait 5 sec for old threads to die
  228. prevthreads = num_threads;
  229. }
  230. }
  231. int main(void) {
  232. long sleep_cnt;
  233. int min_threads, max_threads;
  234. int num_chunks = 10000;
  235. int num_rounds;
  236. int chperthread;
  237. printf("Larson benchmark\n");
  238. printf("runtime (sec): ") ;
  239. //scanf ("%ld", &sleep_cnt);
  240. sleep_cnt = 30;
  241. printf("%ld\n", sleep_cnt);
  242. printf("chunk size (min,max): ") ;
  243. //scanf("%d %d", &min_size, &max_size ) ;
  244. min_size = 32;
  245. max_size = 64;
  246. printf("%d %d\n", min_size, max_size);
  247. printf("threads (min, max): ") ;
  248. //scanf("%d %d", &min_threads, &max_threads) ;
  249. min_threads = 2;
  250. max_threads = 2;
  251. printf("%d %d\n", min_threads, max_threads);
  252. pthread_setconcurrency(max_threads);
  253. printf("chunks/thread: ");
  254. //scanf("%d", &chperthread );
  255. chperthread = 10000;
  256. printf("%d\n", chperthread);
  257. num_chunks = max_threads * chperthread ;
  258. if( num_chunks > MAX_BLOCKS ){
  259. printf("Max %d chunks - exiting\n", MAX_BLOCKS ) ;
  260. return 1;
  261. }
  262. printf("no of rounds: ");
  263. //scanf("%d", &num_rounds );
  264. num_rounds = 10;
  265. printf("%d\n", num_rounds);
  266. runthreads(sleep_cnt, min_threads, max_threads, chperthread, num_rounds) ;
  267. return 0;
  268. }