larson.c 8.2 KB

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