├── Makefile.txt ├── README.md ├── clock.c ├── clock.h ├── clock.o ├── config.h ├── fcyc.c ├── fcyc.h ├── fcyc.o ├── fsecs.c ├── fsecs.h ├── fsecs.o ├── ftimer.c ├── ftimer.h ├── ftimer.o ├── mdriver ├── mdriver.c ├── mdriver.o ├── memlib.c ├── memlib.h ├── memlib.o ├── mm.c ├── mm.c~ ├── mm.h ├── mm.o ├── short1-bal.rep ├── short2-bal.rep ├── traces ├── amptjp-bal.rep ├── binary-bal.rep ├── binary2-bal.rep ├── cccp-bal.rep ├── coalescing-bal.rep ├── cp-decl-bal.rep ├── expr-bal.rep ├── random-bal.rep ├── random2-bal.rep ├── realloc-bal.rep ├── realloc-bal.rep~ ├── realloc2-bal.rep ├── realloc2-bal.rep~ ├── short1-bal.rep └── short2-bal.rep ├── writeup.txt └── writeup.txt~ /Makefile.txt: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -m32 -Wall -Wextra -O2 -g 3 | 4 | OBJS = mdriver.o mm.o memlib.o fsecs.o fcyc.o clock.o ftimer.o 5 | 6 | mdriver: $(OBJS) 7 | $(CC) $(CFLAGS) -o mdriver $(OBJS) 8 | 9 | mdriver.o: mdriver.c fsecs.h fcyc.h clock.h memlib.h config.h mm.h 10 | memlib.o: memlib.c memlib.h 11 | mm.o: mm.c mm.h memlib.h 12 | fsecs.o: fsecs.c fsecs.h config.h 13 | fcyc.o: fcyc.c fcyc.h 14 | ftimer.o: ftimer.c ftimer.h config.h 15 | clock.o: clock.c clock.h 16 | 17 | clean: 18 | rm -f *~ *.o mdriver 19 | 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | malloc-lab 2 | ========== 3 | 4 | > **COMP 221 Project 5: Malloc Dynamic Memory Allocator :** An implementation of malloc in C using explicit free list, as according to the lab assignment of CS-APP book , reaching 91 % efficiency. 5 | 6 | 7 | --- 8 | 9 | ### DESCRIPTION 10 | 11 | The solution adopted is of using an explicit free list to maintain the list of pointers to free blocks. This enhances performace of allocator, compared to the use of an implicit free list, since allocator does not need to traverse the allocated blocks to find appropiate size of free memory. This improves throughput to great extent. To improve memory allocation (util) , some changes have been made in reallocation strategy. Finally to improve performance a little more, some changes have been made in find fit function so as to prevent very long traversals sometimes. 12 | 13 | ### DESIGN 14 | 15 | In all there are 3 main features that has been added to allocator (changed from default allocator given) 16 | 17 | * Implemented explicit free list to maintain the list of pointers to free blocks. 18 | 19 | * DataStructure used of free list is Doubly Linked List. 20 | * Programmer accesses only that memory which is allocated (that is, the allocated blocks). So free blocks can be used efficiently to store other important information, considering how much of an expensive resource memory is. Since the minimum block size given is 4 words , no free block can be less than 4 words. With this fact, we can easiliy store 2 pointers in free blocks (which requires only 2 words). First pointer will point to the free block (in heap) previous to the current free block (in which I am storing pointers) and the second will point to the free block next to the current free block. 21 | 22 | #### 1. 23 | Any free block in heap will be of following format. 24 | 25 | ``` 26 | -------------------------------------------------------------------------- 27 | | Prev Free Block ptr (1 word) | Next Free Block ptr(1 word) | ... | 28 | -------------------------------------------------------------------------- 29 | ``` 30 | 31 | Hence if we have a pointer bp to a free block then we can access next and previous free blocks using macros: 32 | 33 | ``` 34 | #define GET_NEXT_PTR(bp) (*(char **)(bp + WSIZE)) 35 | #define GET_PREV_PTR(bp) (*(char **)(bp)) 36 | ``` 37 | And to set previous and next pointer we have used: 38 | ``` 39 | #define SET_NEXT_PTR(bp, qp) (GET_NEXT_PTR(bp) = qp) 40 | #define SET_PREV_PTR(bp, qp) (GET_PREV_PTR(bp) = qp) 41 | ``` 42 | Further two functions : 43 | ``` 44 | void insert_in_free_list(void *bp) 45 | remove_from_free_list(void *bp) 46 | ``` 47 | have been implemented using above macros so as to maintain free list. 48 | 49 | #### 2. 50 | 51 | Changed realloc function so as to improve the dropping performance in realloc-bal.rep and realloc2-bal.rep 52 | 53 | The default realloc function was inefficient due to the reason that it would always call malloc again so find memory of new size and copy all contents to it, even when it is not necessary. 54 | 55 | To fix this, we have added a condition in realloc. 56 | 57 | Eg, for scenario where realloc asks for newsize of space and current size of block is oldsize and newsize is greater than oldsize. Ie (block needs to expand) then, it should first check if the next block is free or not. In case next block is free and sum total of both block (this block and next block) is greater than the oldsize then we can only change the size of current block, fix header, footer and we are done. No need to copy contents anywhere. Contents of old block are still intact and safe. 58 | 59 | For example, 60 | 61 | ``` 62 | -------------------------------------------------------------------- 63 | | Current Block (oldsize =8 words)| Next Block (8 word) (free) | 64 | -------------------------------------------------------------------- 65 | ``` 66 | Now if current block is requested by programmer to extend to 16 words then no need to call malloc again and copy contents. 67 | Just combine two blocks while taking care of extra space remaining: 68 | ``` 69 | ----------------------------------------------------------------------- 70 | | Current Block (newsize =16 words) | 71 | ----------------------------------------------------------------------- 72 | ``` 73 | 74 | #### 3. 75 | 76 | Preventing dropping performance due to repetitive same sized malloc calls. 77 | 78 | I have a test file called binary-bal.rep in which same malloc requests are made many many of times in a row. Implementing first fit algorithm using explicit list reduces time- efficiency. To prevent this situation, we can use the following scheme: 79 | 80 | If it is realized that many times (say > 30 times) same malloc size request has been made, then instead of traversing the full free list , when I know it is going to take long, I can just extend the heap by the requested amount. However care has to be taken so as to prevent many extend_heap calls to make program run out of memory. 81 | 82 | ##### Extra points about the program: 83 | 84 | Headers and Footer have been kept as such in the program. It has the following structure: 85 | ``` 86 | 31 3 2 1 0 87 | ----------------------------------- 88 | | s s s s ... s s s 0 0 a/f 89 | ----------------------------------- 90 | ``` 91 | * Coalescing scheme is immediate coalescing using boundary tag coalescing. 92 | * Searching through free list executes first fit algorithm. 93 | 94 | -------------------------------------------------------------------------------- /clock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * clock.c - Routines for using the cycle counters on x86, 3 | * Alpha, and Sparc boxes. 4 | * 5 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 6 | * May not be used, modified, or copied without permission. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "clock.h" 14 | 15 | 16 | /******************************************************* 17 | * Machine dependent functions 18 | * 19 | * Note: the constants __i386__ and __alpha 20 | * are set by GCC when it calls the C preprocessor 21 | * You can verify this for yourself using gcc -v. 22 | *******************************************************/ 23 | 24 | #if defined(__i386__) 25 | /******************************************************* 26 | * Pentium versions of start_counter() and get_counter() 27 | *******************************************************/ 28 | 29 | 30 | /* $begin x86cyclecounter */ 31 | /* Initialize the cycle counter */ 32 | static unsigned cyc_hi = 0; 33 | static unsigned cyc_lo = 0; 34 | 35 | 36 | /* Set *hi and *lo to the high and low order bits of the cycle counter. 37 | Implementation requires assembly code to use the rdtsc instruction. */ 38 | void access_counter(unsigned *hi, unsigned *lo) 39 | { 40 | asm("rdtsc; movl %%edx,%0; movl %%eax,%1" /* Read cycle counter */ 41 | : "=r" (*hi), "=r" (*lo) /* and move results to */ 42 | : /* No input */ /* the two outputs */ 43 | : "%edx", "%eax"); 44 | } 45 | 46 | /* Record the current value of the cycle counter. */ 47 | void start_counter() 48 | { 49 | access_counter(&cyc_hi, &cyc_lo); 50 | } 51 | 52 | /* Return the number of cycles since the last call to start_counter. */ 53 | double get_counter() 54 | { 55 | unsigned ncyc_hi, ncyc_lo; 56 | unsigned hi, lo, borrow; 57 | double result; 58 | 59 | /* Get cycle counter */ 60 | access_counter(&ncyc_hi, &ncyc_lo); 61 | 62 | /* Do double precision subtraction */ 63 | lo = ncyc_lo - cyc_lo; 64 | borrow = lo > ncyc_lo; 65 | hi = ncyc_hi - cyc_hi - borrow; 66 | result = (double) hi * (1 << 30) * 4 + lo; 67 | if (result < 0) { 68 | fprintf(stderr, "Error: counter returns neg value: %.0f\n", result); 69 | } 70 | return result; 71 | } 72 | /* $end x86cyclecounter */ 73 | 74 | #elif defined(__alpha) 75 | 76 | /**************************************************** 77 | * Alpha versions of start_counter() and get_counter() 78 | ***************************************************/ 79 | 80 | /* Initialize the cycle counter */ 81 | static unsigned cyc_hi = 0; 82 | static unsigned cyc_lo = 0; 83 | 84 | 85 | /* Use Alpha cycle timer to compute cycles. Then use 86 | measured clock speed to compute seconds 87 | */ 88 | 89 | /* 90 | * counterRoutine is an array of Alpha instructions to access 91 | * the Alpha's processor cycle counter. It uses the rpcc 92 | * instruction to access the counter. This 64 bit register is 93 | * divided into two parts. The lower 32 bits are the cycles 94 | * used by the current process. The upper 32 bits are wall 95 | * clock cycles. These instructions read the counter, and 96 | * convert the lower 32 bits into an unsigned int - this is the 97 | * user space counter value. 98 | * NOTE: The counter has a very limited time span. With a 99 | * 450MhZ clock the counter can time things for about 9 100 | * seconds. */ 101 | static unsigned int counterRoutine[] = 102 | { 103 | 0x601fc000u, 104 | 0x401f0000u, 105 | 0x6bfa8001u 106 | }; 107 | 108 | /* Cast the above instructions into a function. */ 109 | static unsigned int (*counter)(void)= (void *)counterRoutine; 110 | 111 | 112 | void start_counter() 113 | { 114 | /* Get cycle counter */ 115 | cyc_hi = 0; 116 | cyc_lo = counter(); 117 | } 118 | 119 | double get_counter() 120 | { 121 | unsigned ncyc_hi, ncyc_lo; 122 | unsigned hi, lo, borrow; 123 | double result; 124 | ncyc_lo = counter(); 125 | ncyc_hi = 0; 126 | lo = ncyc_lo - cyc_lo; 127 | borrow = lo > ncyc_lo; 128 | hi = ncyc_hi - cyc_hi - borrow; 129 | result = (double) hi * (1 << 30) * 4 + lo; 130 | if (result < 0) { 131 | fprintf(stderr, "Error: Cycle counter returning negative value: %.0f\n", result); 132 | } 133 | return result; 134 | } 135 | 136 | #else 137 | 138 | /**************************************************************** 139 | * All the other platforms for which we haven't implemented cycle 140 | * counter routines. Newer models of sparcs (v8plus) have cycle 141 | * counters that can be accessed from user programs, but since there 142 | * are still many sparc boxes out there that don't support this, we 143 | * haven't provided a Sparc version here. 144 | ***************************************************************/ 145 | 146 | void start_counter() 147 | { 148 | printf("ERROR: You are trying to use a start_counter routine in clock.c\n"); 149 | printf("that has not been implemented yet on this platform.\n"); 150 | printf("Please choose another timing package in config.h.\n"); 151 | exit(1); 152 | } 153 | 154 | double get_counter() 155 | { 156 | printf("ERROR: You are trying to use a get_counter routine in clock.c\n"); 157 | printf("that has not been implemented yet on this platform.\n"); 158 | printf("Please choose another timing package in config.h.\n"); 159 | exit(1); 160 | } 161 | #endif 162 | 163 | 164 | 165 | 166 | /******************************* 167 | * Machine-independent functions 168 | ******************************/ 169 | double ovhd() 170 | { 171 | /* Do it twice to eliminate cache effects */ 172 | int i; 173 | double result; 174 | 175 | for (i = 0; i < 2; i++) { 176 | start_counter(); 177 | result = get_counter(); 178 | } 179 | return result; 180 | } 181 | 182 | /* $begin mhz */ 183 | /* Estimate the clock rate by measuring the cycles that elapse */ 184 | /* while sleeping for sleeptime seconds */ 185 | double mhz_full(int verbose, int sleeptime) 186 | { 187 | double rate; 188 | 189 | start_counter(); 190 | sleep(sleeptime); 191 | rate = get_counter() / (1e6*sleeptime); 192 | if (verbose) 193 | printf("Processor clock rate ~= %.1f MHz\n", rate); 194 | return rate; 195 | } 196 | /* $end mhz */ 197 | 198 | /* Version using a default sleeptime */ 199 | double mhz(int verbose) 200 | { 201 | return mhz_full(verbose, 2); 202 | } 203 | 204 | /** Special counters that compensate for timer interrupt overhead */ 205 | 206 | static double cyc_per_tick = 0.0; 207 | 208 | #define NEVENT 100 209 | #define THRESHOLD 1000 210 | #define RECORDTHRESH 3000 211 | 212 | /* Attempt to see how much time is used by timer interrupt */ 213 | static void callibrate(int verbose) 214 | { 215 | double oldt; 216 | struct tms t; 217 | clock_t oldc; 218 | int e = 0; 219 | 220 | times(&t); 221 | oldc = t.tms_utime; 222 | start_counter(); 223 | oldt = get_counter(); 224 | while (e = THRESHOLD) { 228 | clock_t newc; 229 | times(&t); 230 | newc = t.tms_utime; 231 | if (newc > oldc) { 232 | double cpt = (newt-oldt)/(newc-oldc); 233 | if ((cyc_per_tick == 0.0 || cyc_per_tick > cpt) && cpt > RECORDTHRESH) 234 | cyc_per_tick = cpt; 235 | /* 236 | if (verbose) 237 | printf("Saw event lasting %.0f cycles and %d ticks. Ratio = %f\n", 238 | newt-oldt, (int) (newc-oldc), cpt); 239 | */ 240 | e++; 241 | oldc = newc; 242 | } 243 | oldt = newt; 244 | } 245 | } 246 | if (verbose) 247 | printf("Setting cyc_per_tick to %f\n", cyc_per_tick); 248 | } 249 | 250 | static clock_t start_tick = 0; 251 | 252 | void start_comp_counter() 253 | { 254 | struct tms t; 255 | 256 | if (cyc_per_tick == 0.0) 257 | callibrate(0); 258 | times(&t); 259 | start_tick = t.tms_utime; 260 | start_counter(); 261 | } 262 | 263 | double get_comp_counter() 264 | { 265 | double time = get_counter(); 266 | double ctime; 267 | struct tms t; 268 | clock_t ticks; 269 | 270 | times(&t); 271 | ticks = t.tms_utime - start_tick; 272 | ctime = time - ticks*cyc_per_tick; 273 | /* 274 | printf("Measured %.0f cycles. Ticks = %d. Corrected %.0f cycles\n", 275 | time, (int) ticks, ctime); 276 | */ 277 | return ctime; 278 | } 279 | 280 | -------------------------------------------------------------------------------- /clock.h: -------------------------------------------------------------------------------- 1 | /* Routines for using cycle counter */ 2 | 3 | /* Start the counter */ 4 | void start_counter(); 5 | 6 | /* Get # cycles since counter started */ 7 | double get_counter(); 8 | 9 | /* Measure overhead for counter */ 10 | double ovhd(); 11 | 12 | /* Determine clock rate of processor (using a default sleeptime) */ 13 | double mhz(int verbose); 14 | 15 | /* Determine clock rate of processor, having more control over accuracy */ 16 | double mhz_full(int verbose, int sleeptime); 17 | 18 | /** Special counters that compensate for timer interrupt overhead */ 19 | 20 | void start_comp_counter(); 21 | 22 | double get_comp_counter(); 23 | -------------------------------------------------------------------------------- /clock.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshTrivedi/malloc/031275f125c81bec3eb56bff95a1ce72f3554307/clock.o -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONFIG_H_ 2 | #define __CONFIG_H_ 3 | 4 | /* 5 | * config.h - malloc lab configuration file 6 | * 7 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 8 | * May not be used, modified, or copied without permission. 9 | */ 10 | 11 | /* 12 | * This is the default path where the driver will look for the 13 | * default tracefiles. You can override it at runtime with the -t flag. 14 | */ 15 | #define TRACEDIR "./traces/" 16 | 17 | /* 18 | * This is the list of default tracefiles in TRACEDIR that the driver 19 | * will use for testing. Modify this if you want to add or delete 20 | * traces from the driver's test suite. For example, if you don't want 21 | * your students to implement realloc, you can delete the last two 22 | * traces. 23 | */ 24 | #define DEFAULT_TRACEFILES \ 25 | "amptjp-bal.rep",\ 26 | "cccp-bal.rep",\ 27 | "cp-decl-bal.rep",\ 28 | "expr-bal.rep",\ 29 | "coalescing-bal.rep",\ 30 | "random-bal.rep",\ 31 | "random2-bal.rep",\ 32 | "binary-bal.rep",\ 33 | "binary2-bal.rep",\ 34 | "realloc-bal.rep",\ 35 | "realloc2-bal.rep" 36 | 37 | /* 38 | * This constant gives the estimated performance of the libc malloc 39 | * package using our traces on some reference system, typically the 40 | * same kind of system the students use. Its purpose is to cap the 41 | * contribution of throughput to the performance index. Once the 42 | * students surpass the AVG_LIBC_THRUPUT, they get no further benefit 43 | * to their score. This deters students from building extremely fast, 44 | * but extremely stupid malloc packages. 45 | */ 46 | #define AVG_LIBC_THRUPUT 10750E3 /* 10,750 Kops/sec */ 47 | 48 | /* 49 | * This constant determines the contributions of space utilization 50 | * (UTIL_WEIGHT) and throughput (1 - UTIL_WEIGHT) to the performance 51 | * index. 52 | */ 53 | #define UTIL_WEIGHT .40 54 | 55 | /* 56 | * Alignment requirement in bytes 57 | */ 58 | #define ALIGNMENT 8 59 | 60 | /* 61 | * Maximum heap size in bytes 62 | */ 63 | #define MAX_HEAP (20*(1<<20)) /* 20 MB */ 64 | 65 | /***************************************************************************** 66 | * Set exactly one of these USE_xxx constants to "1" to select a timing method 67 | *****************************************************************************/ 68 | #define USE_FCYC 0 /* cycle counter w/K-best scheme (x86 & Alpha only) */ 69 | #define USE_ITIMER 0 /* interval timer (any Unix box) */ 70 | #define USE_GETTOD 1 /* gettimeofday (any Unix box) */ 71 | 72 | #endif /* __CONFIG_H */ 73 | -------------------------------------------------------------------------------- /fcyc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fcyc.c - Estimate the time (in CPU cycles) used by a function f 3 | * 4 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 5 | * May not be used, modified, or copied without permission. 6 | * 7 | * Uses the cycle timer routines in clock.c to estimate the 8 | * the time in CPU cycles for a function f. 9 | */ 10 | #include 11 | #include 12 | #include 13 | 14 | #include "fcyc.h" 15 | #include "clock.h" 16 | 17 | /* Default values */ 18 | #define K 3 /* Value of K in K-best scheme */ 19 | #define MAXSAMPLES 20 /* Give up after MAXSAMPLES */ 20 | #define EPSILON 0.01 /* K samples should be EPSILON of each other*/ 21 | #define COMPENSATE 0 /* 1-> try to compensate for clock ticks */ 22 | #define CLEAR_CACHE 0 /* Clear cache before running test function */ 23 | #define CACHE_BYTES (1<<19) /* Max cache size in bytes */ 24 | #define CACHE_BLOCK 32 /* Cache block size in bytes */ 25 | 26 | static int kbest = K; 27 | static int maxsamples = MAXSAMPLES; 28 | static double epsilon = EPSILON; 29 | static int compensate = COMPENSATE; 30 | static int clear_cache = CLEAR_CACHE; 31 | static int cache_bytes = CACHE_BYTES; 32 | static int cache_block = CACHE_BLOCK; 33 | 34 | static int *cache_buf = NULL; 35 | 36 | static double *values = NULL; 37 | static int samplecount = 0; 38 | 39 | /* for debugging only */ 40 | #define KEEP_VALS 0 41 | #define KEEP_SAMPLES 0 42 | 43 | #if KEEP_SAMPLES 44 | static double *samples = NULL; 45 | #endif 46 | 47 | /* 48 | * init_sampler - Start new sampling process 49 | */ 50 | static void init_sampler() 51 | { 52 | if (values) 53 | free(values); 54 | values = calloc(kbest, sizeof(double)); 55 | #if KEEP_SAMPLES 56 | if (samples) 57 | free(samples); 58 | /* Allocate extra for wraparound analysis */ 59 | samples = calloc(maxsamples+kbest, sizeof(double)); 60 | #endif 61 | samplecount = 0; 62 | } 63 | 64 | /* 65 | * add_sample - Add new sample 66 | */ 67 | static void add_sample(double val) 68 | { 69 | int pos = 0; 70 | if (samplecount < kbest) { 71 | pos = samplecount; 72 | values[pos] = val; 73 | } else if (val < values[kbest-1]) { 74 | pos = kbest-1; 75 | values[pos] = val; 76 | } 77 | #if KEEP_SAMPLES 78 | samples[samplecount] = val; 79 | #endif 80 | samplecount++; 81 | /* Insertion sort */ 82 | while (pos > 0 && values[pos-1] > values[pos]) { 83 | double temp = values[pos-1]; 84 | values[pos-1] = values[pos]; 85 | values[pos] = temp; 86 | pos--; 87 | } 88 | } 89 | 90 | /* 91 | * has_converged- Have kbest minimum measurements converged within epsilon? 92 | */ 93 | static int has_converged() 94 | { 95 | return 96 | (samplecount >= kbest) && 97 | ((1 + epsilon)*values[0] >= values[kbest-1]); 98 | } 99 | 100 | /* 101 | * clear - Code to clear cache 102 | */ 103 | static volatile int sink = 0; 104 | 105 | static void clear() 106 | { 107 | int x = sink; 108 | int *cptr, *cend; 109 | int incr = cache_block/sizeof(int); 110 | if (!cache_buf) { 111 | cache_buf = malloc(cache_bytes); 112 | if (!cache_buf) { 113 | fprintf(stderr, "Fatal error. Malloc returned null when trying to clear cache\n"); 114 | exit(1); 115 | } 116 | } 117 | cptr = (int *) cache_buf; 118 | cend = cptr + cache_bytes/sizeof(int); 119 | while (cptr < cend) { 120 | x += *cptr; 121 | cptr += incr; 122 | } 123 | sink = x; 124 | } 125 | 126 | /* 127 | * fcyc - Use K-best scheme to estimate the running time of function f 128 | */ 129 | double fcyc(test_funct f, void *argp) 130 | { 131 | double result; 132 | init_sampler(); 133 | if (compensate) { 134 | do { 135 | double cyc; 136 | if (clear_cache) 137 | clear(); 138 | start_comp_counter(); 139 | f(argp); 140 | cyc = get_comp_counter(); 141 | add_sample(cyc); 142 | } while (!has_converged() && samplecount < maxsamples); 143 | } else { 144 | do { 145 | double cyc; 146 | if (clear_cache) 147 | clear(); 148 | start_counter(); 149 | f(argp); 150 | cyc = get_counter(); 151 | add_sample(cyc); 152 | } while (!has_converged() && samplecount < maxsamples); 153 | } 154 | #ifdef DEBUG 155 | { 156 | int i; 157 | printf(" %d smallest values: [", kbest); 158 | for (i = 0; i < kbest; i++) 159 | printf("%.0f%s", values[i], i==kbest-1 ? "]\n" : ", "); 160 | } 161 | #endif 162 | result = values[0]; 163 | #if !KEEP_VALS 164 | free(values); 165 | values = NULL; 166 | #endif 167 | return result; 168 | } 169 | 170 | 171 | /************************************************************* 172 | * Set the various parameters used by the measurement routines 173 | ************************************************************/ 174 | 175 | /* 176 | * set_fcyc_clear_cache - When set, will run code to clear cache 177 | * before each measurement. 178 | * Default = 0 179 | */ 180 | void set_fcyc_clear_cache(int clear) 181 | { 182 | clear_cache = clear; 183 | } 184 | 185 | /* 186 | * set_fcyc_cache_size - Set size of cache to use when clearing cache 187 | * Default = 1<<19 (512KB) 188 | */ 189 | void set_fcyc_cache_size(int bytes) 190 | { 191 | if (bytes != cache_bytes) { 192 | cache_bytes = bytes; 193 | if (cache_buf) { 194 | free(cache_buf); 195 | cache_buf = NULL; 196 | } 197 | } 198 | } 199 | 200 | /* 201 | * set_fcyc_cache_block - Set size of cache block 202 | * Default = 32 203 | */ 204 | void set_fcyc_cache_block(int bytes) { 205 | cache_block = bytes; 206 | } 207 | 208 | 209 | /* 210 | * set_fcyc_compensate- When set, will attempt to compensate for 211 | * timer interrupt overhead 212 | * Default = 0 213 | */ 214 | void set_fcyc_compensate(int compensate_arg) 215 | { 216 | compensate = compensate_arg; 217 | } 218 | 219 | /* 220 | * set_fcyc_k - Value of K in K-best measurement scheme 221 | * Default = 3 222 | */ 223 | void set_fcyc_k(int k) 224 | { 225 | kbest = k; 226 | } 227 | 228 | /* 229 | * set_fcyc_maxsamples - Maximum number of samples attempting to find 230 | * K-best within some tolerance. 231 | * When exceeded, just return best sample found. 232 | * Default = 20 233 | */ 234 | void set_fcyc_maxsamples(int maxsamples_arg) 235 | { 236 | maxsamples = maxsamples_arg; 237 | } 238 | 239 | /* 240 | * set_fcyc_epsilon - Tolerance required for K-best 241 | * Default = 0.01 242 | */ 243 | void set_fcyc_epsilon(double epsilon_arg) 244 | { 245 | epsilon = epsilon_arg; 246 | } 247 | 248 | 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /fcyc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fcyc.h - prototypes for the routines in fcyc.c that estimate the 3 | * time in CPU cycles used by a test function f 4 | * 5 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 6 | * May not be used, modified, or copied without permission. 7 | * 8 | */ 9 | 10 | /* The test function takes a generic pointer as input */ 11 | typedef void (*test_funct)(void *); 12 | 13 | /* Compute number of cycles used by test function f */ 14 | double fcyc(test_funct f, void* argp); 15 | 16 | /********************************************************* 17 | * Set the various parameters used by measurement routines 18 | *********************************************************/ 19 | 20 | /* 21 | * set_fcyc_clear_cache - When set, will run code to clear cache 22 | * before each measurement. 23 | * Default = 0 24 | */ 25 | void set_fcyc_clear_cache(int clear); 26 | 27 | /* 28 | * set_fcyc_cache_size - Set size of cache to use when clearing cache 29 | * Default = 1<<19 (512KB) 30 | */ 31 | void set_fcyc_cache_size(int bytes); 32 | 33 | /* 34 | * set_fcyc_cache_block - Set size of cache block 35 | * Default = 32 36 | */ 37 | void set_fcyc_cache_block(int bytes); 38 | 39 | /* 40 | * set_fcyc_compensate- When set, will attempt to compensate for 41 | * timer interrupt overhead 42 | * Default = 0 43 | */ 44 | void set_fcyc_compensate(int compensate_arg); 45 | 46 | /* 47 | * set_fcyc_k - Value of K in K-best measurement scheme 48 | * Default = 3 49 | */ 50 | void set_fcyc_k(int k); 51 | 52 | /* 53 | * set_fcyc_maxsamples - Maximum number of samples attempting to find 54 | * K-best within some tolerance. 55 | * When exceeded, just return best sample found. 56 | * Default = 20 57 | */ 58 | void set_fcyc_maxsamples(int maxsamples_arg); 59 | 60 | /* 61 | * set_fcyc_epsilon - Tolerance required for K-best 62 | * Default = 0.01 63 | */ 64 | void set_fcyc_epsilon(double epsilon_arg); 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /fcyc.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshTrivedi/malloc/031275f125c81bec3eb56bff95a1ce72f3554307/fcyc.o -------------------------------------------------------------------------------- /fsecs.c: -------------------------------------------------------------------------------- 1 | /**************************** 2 | * High-level timing wrappers 3 | ****************************/ 4 | #include 5 | #include "fsecs.h" 6 | #include "fcyc.h" 7 | #include "clock.h" 8 | #include "ftimer.h" 9 | #include "config.h" 10 | 11 | static double Mhz; /* estimated CPU clock frequency */ 12 | 13 | extern int verbose; /* -v option in mdriver.c */ 14 | 15 | /* 16 | * init_fsecs - initialize the timing package 17 | */ 18 | void init_fsecs(void) 19 | { 20 | Mhz = 0; /* keep gcc -Wall happy */ 21 | 22 | #if USE_FCYC 23 | if (verbose) 24 | printf("Measuring performance with a cycle counter.\n"); 25 | 26 | /* set key parameters for the fcyc package */ 27 | set_fcyc_maxsamples(20); 28 | set_fcyc_clear_cache(1); 29 | set_fcyc_compensate(1); 30 | set_fcyc_epsilon(0.01); 31 | set_fcyc_k(3); 32 | Mhz = mhz(verbose > 0); 33 | #elif USE_ITIMER 34 | if (verbose) 35 | printf("Measuring performance with the interval timer.\n"); 36 | #elif USE_GETTOD 37 | if (verbose) 38 | printf("Measuring performance with gettimeofday().\n"); 39 | #endif 40 | } 41 | 42 | /* 43 | * fsecs - Return the running time of a function f (in seconds) 44 | */ 45 | double fsecs(fsecs_test_funct f, void *argp) 46 | { 47 | #if USE_FCYC 48 | double cycles = fcyc(f, argp); 49 | return cycles/(Mhz*1e6); 50 | #elif USE_ITIMER 51 | return ftimer_itimer(f, argp, 10); 52 | #elif USE_GETTOD 53 | return ftimer_gettod(f, argp, 10); 54 | #endif 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /fsecs.h: -------------------------------------------------------------------------------- 1 | typedef void (*fsecs_test_funct)(void *); 2 | 3 | void init_fsecs(void); 4 | double fsecs(fsecs_test_funct f, void *argp); 5 | -------------------------------------------------------------------------------- /fsecs.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshTrivedi/malloc/031275f125c81bec3eb56bff95a1ce72f3554307/fsecs.o -------------------------------------------------------------------------------- /ftimer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ftimer.c - Estimate the time (in seconds) used by a function f 3 | * 4 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 5 | * May not be used, modified, or copied without permission. 6 | * 7 | * Function timers that estimate the running time (in seconds) of a function f. 8 | * ftimer_itimer: version that uses the interval timer 9 | * ftimer_gettod: version that uses gettimeofday 10 | */ 11 | #include 12 | #include 13 | #include "ftimer.h" 14 | 15 | /* function prototypes */ 16 | static void init_etime(void); 17 | static double get_etime(void); 18 | 19 | /* 20 | * ftimer_itimer - Use the interval timer to estimate the running time 21 | * of f(argp). Return the average of n runs. 22 | */ 23 | double ftimer_itimer(ftimer_test_funct f, void *argp, int n) 24 | { 25 | double start, tmeas; 26 | int i; 27 | 28 | init_etime(); 29 | start = get_etime(); 30 | for (i = 0; i < n; i++) 31 | f(argp); 32 | tmeas = get_etime() - start; 33 | return tmeas / n; 34 | } 35 | 36 | /* 37 | * ftimer_gettod - Use gettimeofday to estimate the running time of 38 | * f(argp). Return the average of n runs. 39 | */ 40 | double ftimer_gettod(ftimer_test_funct f, void *argp, int n) 41 | { 42 | int i; 43 | struct timeval stv, etv; 44 | double diff; 45 | 46 | gettimeofday(&stv, NULL); 47 | for (i = 0; i < n; i++) 48 | f(argp); 49 | gettimeofday(&etv,NULL); 50 | diff = 1E3*(etv.tv_sec - stv.tv_sec) + 1E-3*(etv.tv_usec-stv.tv_usec); 51 | diff /= n; 52 | return (1E-3*diff); 53 | } 54 | 55 | 56 | /* 57 | * Routines for manipulating the Unix interval timer 58 | */ 59 | 60 | /* The initial value of the interval timer */ 61 | #define MAX_ETIME 86400 62 | 63 | /* static variables that hold the initial value of the interval timer */ 64 | static struct itimerval first_u; /* user time */ 65 | static struct itimerval first_r; /* real time */ 66 | static struct itimerval first_p; /* prof time*/ 67 | 68 | /* init the timer */ 69 | static void init_etime(void) 70 | { 71 | first_u.it_interval.tv_sec = 0; 72 | first_u.it_interval.tv_usec = 0; 73 | first_u.it_value.tv_sec = MAX_ETIME; 74 | first_u.it_value.tv_usec = 0; 75 | setitimer(ITIMER_VIRTUAL, &first_u, NULL); 76 | 77 | first_r.it_interval.tv_sec = 0; 78 | first_r.it_interval.tv_usec = 0; 79 | first_r.it_value.tv_sec = MAX_ETIME; 80 | first_r.it_value.tv_usec = 0; 81 | setitimer(ITIMER_REAL, &first_r, NULL); 82 | 83 | first_p.it_interval.tv_sec = 0; 84 | first_p.it_interval.tv_usec = 0; 85 | first_p.it_value.tv_sec = MAX_ETIME; 86 | first_p.it_value.tv_usec = 0; 87 | setitimer(ITIMER_PROF, &first_p, NULL); 88 | } 89 | 90 | /* return elapsed real seconds since call to init_etime */ 91 | static double get_etime(void) { 92 | struct itimerval v_curr; 93 | struct itimerval r_curr; 94 | struct itimerval p_curr; 95 | 96 | getitimer(ITIMER_VIRTUAL, &v_curr); 97 | getitimer(ITIMER_REAL,&r_curr); 98 | getitimer(ITIMER_PROF,&p_curr); 99 | 100 | return (double) ((first_p.it_value.tv_sec - r_curr.it_value.tv_sec) + 101 | (first_p.it_value.tv_usec - r_curr.it_value.tv_usec)*1e-6); 102 | } 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /ftimer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Function timers 3 | */ 4 | typedef void (*ftimer_test_funct)(void *); 5 | 6 | /* Estimate the running time of f(argp) using the Unix interval timer. 7 | Return the average of n runs */ 8 | double ftimer_itimer(ftimer_test_funct f, void *argp, int n); 9 | 10 | 11 | /* Estimate the running time of f(argp) using gettimeofday 12 | Return the average of n runs */ 13 | double ftimer_gettod(ftimer_test_funct f, void *argp, int n); 14 | 15 | -------------------------------------------------------------------------------- /ftimer.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshTrivedi/malloc/031275f125c81bec3eb56bff95a1ce72f3554307/ftimer.o -------------------------------------------------------------------------------- /mdriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshTrivedi/malloc/031275f125c81bec3eb56bff95a1ce72f3554307/mdriver -------------------------------------------------------------------------------- /mdriver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mdriver.c - CS:APP Malloc Lab Driver 3 | * 4 | * Uses a collection of trace files to tests a malloc/free/realloc 5 | * implementation in mm.c. 6 | * 7 | * Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. 8 | * May not be used, modified, or copied without permission. 9 | */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "mm.h" 21 | #include "memlib.h" 22 | #include "fsecs.h" 23 | #include "config.h" 24 | 25 | /********************** 26 | * Constants and macros 27 | **********************/ 28 | 29 | /* Misc */ 30 | #define MAXLINE 1024 /* max string size */ 31 | #define HDRLINES 4 /* number of header lines in a trace file */ 32 | #define LINENUM(i) (i+5) /* cnvt trace request nums to linenums (origin 1) */ 33 | 34 | /* Returns true if p is ALIGNMENT-byte aligned */ 35 | #define IS_ALIGNED(p) ((((uintptr_t)(p)) % ALIGNMENT) == 0) 36 | 37 | /****************************** 38 | * The key compound data types 39 | *****************************/ 40 | 41 | /* Records the extent of each block's payload */ 42 | typedef struct range_t { 43 | char *lo; /* low payload address */ 44 | char *hi; /* high payload address */ 45 | struct range_t *next; /* next list element */ 46 | } range_t; 47 | 48 | /* Characterizes a single trace operation (allocator request) */ 49 | typedef struct { 50 | enum {ALLOC, FREE, REALLOC} type; /* type of request */ 51 | int index; /* index for free() to use later */ 52 | int size; /* byte size of alloc/realloc request */ 53 | } traceop_t; 54 | 55 | /* Holds the information for one trace file*/ 56 | typedef struct { 57 | unsigned sugg_heapsize; /* suggested heap size (unused) */ 58 | unsigned num_ids; /* number of alloc/realloc ids */ 59 | unsigned num_ops; /* number of distinct requests */ 60 | unsigned weight; /* weight for this trace (unused) */ 61 | traceop_t *ops; /* array of requests */ 62 | char **blocks; /* array of ptrs returned by malloc/realloc... */ 63 | size_t *block_sizes; /* ... and a corresponding array of payload sizes */ 64 | } trace_t; 65 | 66 | /* 67 | * Holds the params to the xxx_speed functions, which are timed by fcyc. 68 | * This struct is necessary because fcyc accepts only a pointer array 69 | * as input. 70 | */ 71 | typedef struct { 72 | trace_t *trace; 73 | range_t *ranges; 74 | } speed_t; 75 | 76 | /* Summarizes the important stats for some malloc function on some trace */ 77 | typedef struct { 78 | /* defined for both libc malloc and student malloc package (mm.c) */ 79 | double ops; /* number of ops (malloc/free/realloc) in the trace */ 80 | int valid; /* was the trace processed correctly by the allocator? */ 81 | double secs; /* number of secs needed to run the trace */ 82 | 83 | /* defined only for the student malloc package */ 84 | double util; /* space utilization for this trace (always 0 for libc) */ 85 | 86 | /* Note: secs and util are only defined if valid is true */ 87 | } stats_t; 88 | 89 | /******************** 90 | * Global variables 91 | *******************/ 92 | int verbose = 0; /* global flag for verbose output */ 93 | static int errors = 0; /* number of errs found when running student malloc */ 94 | char msg[MAXLINE]; /* for whenever we need to compose an error message */ 95 | 96 | /* Directory where default tracefiles are found */ 97 | static char tracedir[MAXLINE] = TRACEDIR; 98 | 99 | /* The filenames of the default tracefiles */ 100 | static char *default_tracefiles[] = { 101 | DEFAULT_TRACEFILES, NULL 102 | }; 103 | 104 | 105 | /********************* 106 | * Function prototypes 107 | *********************/ 108 | 109 | /* these functions manipulate range lists */ 110 | static int add_range(range_t **ranges, char *lo, int size, 111 | int tracenum, int opnum); 112 | static void remove_range(range_t **ranges, char *lo); 113 | static void clear_ranges(range_t **ranges); 114 | 115 | /* These functions read, allocate, and free storage for traces */ 116 | static trace_t *read_trace(char *tracedir, char *filename); 117 | static void free_trace(trace_t *trace); 118 | 119 | /* Routines for evaluating the correctness and speed of libc malloc */ 120 | static int eval_libc_valid(trace_t *trace, int tracenum); 121 | static void eval_libc_speed(void *ptr); 122 | 123 | /* Routines for evaluating correctnes, space utilization, and speed 124 | of the student's malloc package in mm.c */ 125 | static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges); 126 | static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges); 127 | static void eval_mm_speed(void *ptr); 128 | 129 | /* Various helper routines */ 130 | static void printresults(int n, stats_t *stats); 131 | static void usage(void); 132 | static void unix_error(char *msg); 133 | static void malloc_error(int tracenum, int opnum, char *msg); 134 | static void app_error(char *msg); 135 | 136 | /************** 137 | * Main routine 138 | **************/ 139 | int main(int argc, char **argv) 140 | { 141 | int i; 142 | char c; 143 | char **tracefiles = NULL; /* null-terminated array of trace file names */ 144 | int num_tracefiles = 0; /* the number of traces in that array */ 145 | trace_t *trace = NULL; /* stores a single trace file in memory */ 146 | range_t *ranges = NULL; /* keeps track of block extents for one trace */ 147 | stats_t *libc_stats = NULL;/* libc stats for each trace */ 148 | stats_t *mm_stats = NULL; /* mm (i.e. student) stats for each trace */ 149 | speed_t speed_params; /* input parameters to the xx_speed routines */ 150 | 151 | int team_check = 1; /* If set, check team structure (reset by -a) */ 152 | int run_libc = 0; /* If set, run libc malloc (set by -l) */ 153 | int autograder = 0; /* If set, emit summary info for autograder (-g) */ 154 | 155 | /* temporaries used to compute the performance index */ 156 | double secs, ops, util, avg_mm_util, avg_mm_throughput, p1, p2, perfindex; 157 | int numcorrect; 158 | 159 | /* 160 | * Read and interpret the command line arguments 161 | */ 162 | while ((c = getopt(argc, argv, "f:t:hvVgal")) != EOF) { 163 | switch (c) { 164 | case 'g': /* Generate summary info for the autograder */ 165 | autograder = 1; 166 | break; 167 | case 'f': /* Use one specific trace file only (relative to curr dir) */ 168 | num_tracefiles = 1; 169 | if ((tracefiles = realloc(tracefiles, 2*sizeof(char *))) == NULL) 170 | unix_error("ERROR: realloc failed in main"); 171 | strcpy(tracedir, "./"); 172 | tracefiles[0] = strdup(optarg); 173 | tracefiles[1] = NULL; 174 | break; 175 | case 't': /* Directory where the traces are located */ 176 | if (num_tracefiles == 1) /* ignore if -f already encountered */ 177 | break; 178 | strcpy(tracedir, optarg); 179 | if (tracedir[strlen(tracedir)-1] != '/') 180 | strcat(tracedir, "/"); /* path always ends with "/" */ 181 | break; 182 | case 'a': /* Don't check team structure */ 183 | team_check = 0; 184 | break; 185 | case 'l': /* Run libc malloc */ 186 | run_libc = 1; 187 | break; 188 | case 'v': /* Print per-trace performance breakdown */ 189 | verbose = 1; 190 | break; 191 | case 'V': /* Be more verbose than -v */ 192 | verbose = 2; 193 | break; 194 | case 'h': /* Print this message */ 195 | usage(); 196 | exit(0); 197 | default: 198 | usage(); 199 | exit(1); 200 | } 201 | } 202 | 203 | /* 204 | * Check and print team info 205 | */ 206 | if (team_check) { 207 | /* Students must fill in their team information */ 208 | if (!strcmp(team.teamname, "")) { 209 | printf("ERROR: Please provide the information about your team in mm.c.\n"); 210 | exit(1); 211 | } else 212 | printf("Team Name:%s\n", team.teamname); 213 | if ((*team.name1 == '\0') || (*team.id1 == '\0')) { 214 | printf("ERROR. You must fill in all team member 1 fields!\n"); 215 | exit(1); 216 | } 217 | else 218 | printf("Member 1 :%s:%s\n", team.name1, team.id1); 219 | 220 | if (((*team.name2 != '\0') && (*team.id2 == '\0')) || 221 | ((*team.name2 == '\0') && (*team.id2 != '\0'))) { 222 | printf("ERROR. You must fill in all or none of the team member 2 ID fields!\n"); 223 | exit(1); 224 | } 225 | else if (*team.name2 != '\0') 226 | printf("Member 2 :%s:%s\n", team.name2, team.id2); 227 | } 228 | 229 | /* 230 | * If no -f command line arg, then use the entire set of tracefiles 231 | * defined in default_traces[] 232 | */ 233 | if (tracefiles == NULL) { 234 | tracefiles = default_tracefiles; 235 | num_tracefiles = sizeof(default_tracefiles) / sizeof(char *) - 1; 236 | printf("Using default tracefiles in %s\n", tracedir); 237 | } 238 | 239 | /* Initialize the timing package */ 240 | init_fsecs(); 241 | 242 | /* 243 | * Optionally run and evaluate the libc malloc package 244 | */ 245 | if (run_libc) { 246 | if (verbose > 1) 247 | printf("\nTesting libc malloc\n"); 248 | 249 | /* Allocate libc stats array, with one stats_t struct per tracefile */ 250 | libc_stats = (stats_t *)calloc(num_tracefiles, sizeof(stats_t)); 251 | if (libc_stats == NULL) 252 | unix_error("libc_stats calloc in main failed"); 253 | 254 | /* Evaluate the libc malloc package using the K-best scheme */ 255 | for (i=0; i < num_tracefiles; i++) { 256 | trace = read_trace(tracedir, tracefiles[i]); 257 | libc_stats[i].ops = trace->num_ops; 258 | if (verbose > 1) 259 | printf("Checking libc malloc for correctness, "); 260 | libc_stats[i].valid = eval_libc_valid(trace, i); 261 | if (libc_stats[i].valid) { 262 | speed_params.trace = trace; 263 | if (verbose > 1) 264 | printf("and performance.\n"); 265 | libc_stats[i].secs = fsecs(eval_libc_speed, &speed_params); 266 | } 267 | free_trace(trace); 268 | } 269 | 270 | /* Display the libc results in a compact table */ 271 | if (verbose) { 272 | printf("\nResults for libc malloc:\n"); 273 | printresults(num_tracefiles, libc_stats); 274 | } 275 | } 276 | 277 | /* 278 | * Always run and evaluate the student's mm package 279 | */ 280 | if (verbose > 1) 281 | printf("\nTesting mm malloc\n"); 282 | 283 | /* Allocate the mm stats array, with one stats_t struct per tracefile */ 284 | mm_stats = (stats_t *)calloc(num_tracefiles, sizeof(stats_t)); 285 | if (mm_stats == NULL) 286 | unix_error("mm_stats calloc in main failed"); 287 | 288 | /* Initialize the simulated memory system in memlib.c */ 289 | mem_init(); 290 | 291 | /* Evaluate student's mm malloc package using the K-best scheme */ 292 | for (i=0; i < num_tracefiles; i++) { 293 | trace = read_trace(tracedir, tracefiles[i]); 294 | mm_stats[i].ops = trace->num_ops; 295 | if (verbose > 1) 296 | printf("Checking mm_malloc for correctness, "); 297 | mm_stats[i].valid = eval_mm_valid(trace, i, &ranges); 298 | if (mm_stats[i].valid) { 299 | if (verbose > 1) 300 | printf("efficiency, "); 301 | mm_stats[i].util = eval_mm_util(trace, i, &ranges); 302 | speed_params.trace = trace; 303 | speed_params.ranges = ranges; 304 | if (verbose > 1) 305 | printf("and performance.\n"); 306 | mm_stats[i].secs = fsecs(eval_mm_speed, &speed_params); 307 | } 308 | free_trace(trace); 309 | } 310 | 311 | /* Display the mm results in a compact table */ 312 | if (verbose) { 313 | printf("\nResults for mm malloc:\n"); 314 | printresults(num_tracefiles, mm_stats); 315 | printf("\n"); 316 | } 317 | 318 | /* 319 | * Accumulate the aggregate statistics for the student's mm package 320 | */ 321 | secs = 0; 322 | ops = 0; 323 | util = 0; 324 | numcorrect = 0; 325 | for (i=0; i < num_tracefiles; i++) { 326 | secs += mm_stats[i].secs; 327 | ops += mm_stats[i].ops; 328 | util += mm_stats[i].util; 329 | if (mm_stats[i].valid) 330 | numcorrect++; 331 | } 332 | avg_mm_util = util/num_tracefiles; 333 | 334 | /* 335 | * Compute and print the performance index 336 | */ 337 | if (errors == 0) { 338 | avg_mm_throughput = ops/secs; 339 | 340 | p1 = UTIL_WEIGHT * avg_mm_util; 341 | if (avg_mm_throughput > AVG_LIBC_THRUPUT) { 342 | p2 = (double)(1.0 - UTIL_WEIGHT); 343 | } 344 | else { 345 | p2 = ((double) (1.0 - UTIL_WEIGHT)) * 346 | (avg_mm_throughput/AVG_LIBC_THRUPUT); 347 | } 348 | 349 | perfindex = (p1 + p2)*100.0; 350 | printf("Perf index = %.0f/%.0f (util) + %.0f/%.0f (thru) = %.0f/100\n", 351 | p1*100, UTIL_WEIGHT*100, 352 | p2*100, (1.0-UTIL_WEIGHT)*100, 353 | perfindex); 354 | 355 | } 356 | else { /* There were errors */ 357 | perfindex = 0.0; 358 | printf("Terminated with %d errors\n", errors); 359 | } 360 | 361 | if (autograder) { 362 | printf("correct:%d\n", numcorrect); 363 | printf("perfidx:%.0f\n", perfindex); 364 | } 365 | 366 | exit(0); 367 | } 368 | 369 | 370 | /***************************************************************** 371 | * The following routines manipulate the range list, which keeps 372 | * track of the extent of every allocated block payload. We use the 373 | * range list to detect any overlapping allocated blocks. 374 | ****************************************************************/ 375 | 376 | /* 377 | * add_range - As directed by request opnum in trace tracenum, 378 | * we've just called the student's mm_malloc to allocate a block of 379 | * size bytes at addr lo. After checking the block for correctness, 380 | * we create a range struct for this block and add it to the range list. 381 | */ 382 | static int add_range(range_t **ranges, char *lo, int size, 383 | int tracenum, int opnum) 384 | { 385 | char *hi = lo + size - 1; 386 | range_t *p; 387 | char msg[MAXLINE]; 388 | 389 | assert(size > 0); 390 | 391 | /* Payload addresses must be ALIGNMENT-byte aligned */ 392 | if (!IS_ALIGNED(lo)) { 393 | sprintf(msg, "Payload address (%p) not aligned to %d bytes", 394 | lo, ALIGNMENT); 395 | malloc_error(tracenum, opnum, msg); 396 | return 0; 397 | } 398 | 399 | /* The payload must lie within the extent of the heap */ 400 | if ((lo < (char *)mem_heap_lo()) || (lo > (char *)mem_heap_hi()) || 401 | (hi < (char *)mem_heap_lo()) || (hi > (char *)mem_heap_hi())) { 402 | sprintf(msg, "Payload (%p:%p) lies outside heap (%p:%p)", 403 | lo, hi, mem_heap_lo(), mem_heap_hi()); 404 | malloc_error(tracenum, opnum, msg); 405 | return 0; 406 | } 407 | 408 | /* The payload must not overlap any other payloads */ 409 | for (p = *ranges; p != NULL; p = p->next) { 410 | if ((lo >= p->lo && lo <= p-> hi) || 411 | (hi >= p->lo && hi <= p->hi)) { 412 | sprintf(msg, "Payload (%p:%p) overlaps another payload (%p:%p)\n", 413 | lo, hi, p->lo, p->hi); 414 | malloc_error(tracenum, opnum, msg); 415 | return 0; 416 | } 417 | } 418 | 419 | /* 420 | * Everything looks OK, so remember the extent of this block 421 | * by creating a range struct and adding it the range list. 422 | */ 423 | if ((p = (range_t *)malloc(sizeof(range_t))) == NULL) 424 | unix_error("malloc error in add_range"); 425 | p->next = *ranges; 426 | p->lo = lo; 427 | p->hi = hi; 428 | *ranges = p; 429 | return 1; 430 | } 431 | 432 | /* 433 | * remove_range - Free the range record of block whose payload starts at lo 434 | */ 435 | static void remove_range(range_t **ranges, char *lo) 436 | { 437 | range_t *p; 438 | range_t **prevpp = ranges; 439 | int size; 440 | 441 | for (p = *ranges; p != NULL; p = p->next) { 442 | if (p->lo == lo) { 443 | *prevpp = p->next; 444 | size = p->hi - p->lo + 1; 445 | free(p); 446 | break; 447 | } 448 | prevpp = &(p->next); 449 | } 450 | } 451 | 452 | /* 453 | * clear_ranges - free all of the range records for a trace 454 | */ 455 | static void clear_ranges(range_t **ranges) 456 | { 457 | range_t *p; 458 | range_t *pnext; 459 | 460 | for (p = *ranges; p != NULL; p = pnext) { 461 | pnext = p->next; 462 | free(p); 463 | } 464 | *ranges = NULL; 465 | } 466 | 467 | 468 | /********************************************** 469 | * The following routines manipulate tracefiles 470 | *********************************************/ 471 | 472 | /* 473 | * read_trace - read a trace file and store it in memory 474 | */ 475 | static trace_t *read_trace(char *tracedir, char *filename) 476 | { 477 | FILE *tracefile; 478 | trace_t *trace; 479 | char type[MAXLINE]; 480 | char path[MAXLINE]; 481 | unsigned index, size; 482 | unsigned max_index = 0; 483 | unsigned op_index; 484 | 485 | if (verbose > 1) 486 | printf("Reading tracefile: %s\n", filename); 487 | 488 | /* Allocate the trace record */ 489 | if ((trace = (trace_t *) malloc(sizeof(trace_t))) == NULL) 490 | unix_error("malloc 1 failed in read_trance"); 491 | 492 | /* Read the trace file header */ 493 | strcpy(path, tracedir); 494 | strcat(path, filename); 495 | if ((tracefile = fopen(path, "r")) == NULL) { 496 | sprintf(msg, "Could not open %s in read_trace", path); 497 | unix_error(msg); 498 | } 499 | fscanf(tracefile, "%u", &(trace->sugg_heapsize)); /* not used */ 500 | fscanf(tracefile, "%u", &(trace->num_ids)); 501 | fscanf(tracefile, "%u", &(trace->num_ops)); 502 | fscanf(tracefile, "%u", &(trace->weight)); /* not used */ 503 | 504 | /* We'll store each request line in the trace in this array */ 505 | if ((trace->ops = 506 | (traceop_t *)malloc(trace->num_ops * sizeof(traceop_t))) == NULL) 507 | unix_error("malloc 2 failed in read_trace"); 508 | 509 | /* We'll keep an array of pointers to the allocated blocks here... */ 510 | if ((trace->blocks = 511 | (char **)malloc(trace->num_ids * sizeof(char *))) == NULL) 512 | unix_error("malloc 3 failed in read_trace"); 513 | 514 | /* ... along with the corresponding byte sizes of each block */ 515 | if ((trace->block_sizes = 516 | (size_t *)malloc(trace->num_ids * sizeof(size_t))) == NULL) 517 | unix_error("malloc 4 failed in read_trace"); 518 | 519 | /* read every request line in the trace file */ 520 | index = 0; 521 | op_index = 0; 522 | while (fscanf(tracefile, "%s", type) != EOF) { 523 | switch(type[0]) { 524 | case 'a': 525 | fscanf(tracefile, "%u %u", &index, &size); 526 | trace->ops[op_index].type = ALLOC; 527 | trace->ops[op_index].index = index; 528 | trace->ops[op_index].size = size; 529 | max_index = (index > max_index) ? index : max_index; 530 | break; 531 | case 'r': 532 | fscanf(tracefile, "%u %u", &index, &size); 533 | trace->ops[op_index].type = REALLOC; 534 | trace->ops[op_index].index = index; 535 | trace->ops[op_index].size = size; 536 | max_index = (index > max_index) ? index : max_index; 537 | break; 538 | case 'f': 539 | fscanf(tracefile, "%ud", &index); 540 | trace->ops[op_index].type = FREE; 541 | trace->ops[op_index].index = index; 542 | break; 543 | default: 544 | printf("Bogus type character (%c) in tracefile %s\n", 545 | type[0], path); 546 | exit(1); 547 | } 548 | op_index++; 549 | 550 | } 551 | fclose(tracefile); 552 | assert(max_index == trace->num_ids - 1); 553 | assert(trace->num_ops == op_index); 554 | 555 | return trace; 556 | } 557 | 558 | /* 559 | * free_trace - Free the trace record and the three arrays it points 560 | * to, all of which were allocated in read_trace(). 561 | */ 562 | void free_trace(trace_t *trace) 563 | { 564 | free(trace->ops); /* free the three arrays... */ 565 | free(trace->blocks); 566 | free(trace->block_sizes); 567 | free(trace); /* and the trace record itself... */ 568 | } 569 | 570 | /********************************************************************** 571 | * The following functions evaluate the correctness, space utilization, 572 | * and throughput of the libc and mm malloc packages. 573 | **********************************************************************/ 574 | 575 | /* 576 | * eval_mm_valid - Check the mm malloc package for correctness 577 | */ 578 | static int eval_mm_valid(trace_t *trace, int tracenum, range_t **ranges) 579 | { 580 | unsigned i, j; 581 | int index; 582 | unsigned size; 583 | unsigned oldsize; 584 | char *newp; 585 | char *oldp; 586 | char *p; 587 | 588 | /* Reset the heap and free any records in the range list */ 589 | mem_reset_brk(); 590 | clear_ranges(ranges); 591 | 592 | /* Call the mm package's init function */ 593 | if (mm_init() < 0) { 594 | malloc_error(tracenum, 0, "mm_init failed."); 595 | return 0; 596 | } 597 | 598 | /* Interpret each operation in the trace in order */ 599 | for (i = 0; i < trace->num_ops; i++) { 600 | index = trace->ops[i].index; 601 | size = trace->ops[i].size; 602 | 603 | switch (trace->ops[i].type) { 604 | 605 | case ALLOC: /* mm_malloc */ 606 | 607 | /* Call the student's malloc */ 608 | if ((p = mm_malloc(size)) == NULL) { 609 | malloc_error(tracenum, i, "mm_malloc failed."); 610 | return 0; 611 | } 612 | 613 | /* 614 | * Test the range of the new block for correctness and add it 615 | * to the range list if OK. The block must be be aligned properly, 616 | * and must not overlap any currently allocated block. 617 | */ 618 | if (add_range(ranges, p, size, tracenum, i) == 0) 619 | return 0; 620 | 621 | /* ADDED: cgw 622 | * fill range with low byte of index. This will be used later 623 | * if we realloc the block and wish to make sure that the old 624 | * data was copied to the new block 625 | */ 626 | memset(p, index & 0xFF, size); 627 | 628 | /* Remember region */ 629 | trace->blocks[index] = p; 630 | trace->block_sizes[index] = size; 631 | break; 632 | 633 | case REALLOC: /* mm_realloc */ 634 | 635 | /* Call the student's realloc */ 636 | oldp = trace->blocks[index]; 637 | if ((newp = mm_realloc(oldp, size)) == NULL) { 638 | malloc_error(tracenum, i, "mm_realloc failed."); 639 | return 0; 640 | } 641 | 642 | /* Remove the old region from the range list */ 643 | remove_range(ranges, oldp); 644 | 645 | /* Check new block for correctness and add it to range list */ 646 | if (add_range(ranges, newp, size, tracenum, i) == 0) 647 | return 0; 648 | 649 | /* ADDED: cgw 650 | * Make sure that the new block contains the data from the old 651 | * block and then fill in the new block with the low order byte 652 | * of the new index 653 | */ 654 | oldsize = trace->block_sizes[index]; 655 | if (size < oldsize) oldsize = size; 656 | for (j = 0; j < oldsize; j++) { 657 | if (newp[j] != (index & 0xFF)) { 658 | malloc_error(tracenum, i, "mm_realloc did not preserve the " 659 | "data from old block"); 660 | return 0; 661 | } 662 | } 663 | memset(newp, index & 0xFF, size); 664 | 665 | /* Remember region */ 666 | trace->blocks[index] = newp; 667 | trace->block_sizes[index] = size; 668 | break; 669 | 670 | case FREE: /* mm_free */ 671 | 672 | /* Remove region from list and call student's free function */ 673 | p = trace->blocks[index]; 674 | remove_range(ranges, p); 675 | mm_free(p); 676 | break; 677 | 678 | default: 679 | app_error("Nonexistent request type in eval_mm_valid"); 680 | } 681 | 682 | } 683 | 684 | /* As far as we know, this is a valid malloc package */ 685 | return 1; 686 | } 687 | 688 | /* 689 | * eval_mm_util - Evaluate the space utilization of the student's package 690 | * The idea is to remember the high water mark "hwm" of the heap for 691 | * an optimal allocator, i.e., no gaps and no internal fragmentation. 692 | * Utilization is the ratio hwm/heapsize, where heapsize is the 693 | * size of the heap in bytes after running the student's malloc 694 | * package on the trace. Note that our implementation of mem_sbrk() 695 | * doesn't allow the students to decrement the brk pointer, so brk 696 | * is always the high water mark of the heap. 697 | * 698 | */ 699 | static double eval_mm_util(trace_t *trace, int tracenum, range_t **ranges) 700 | { 701 | unsigned i; 702 | int index; 703 | unsigned size, newsize, oldsize; 704 | int max_total_size = 0; 705 | int total_size = 0; 706 | char *p; 707 | char *newp, *oldp; 708 | 709 | /* Remove the unused variable warnings */ 710 | tracenum = tracenum; 711 | ranges = ranges; 712 | 713 | /* initialize the heap and the mm malloc package */ 714 | mem_reset_brk(); 715 | if (mm_init() < 0) 716 | app_error("mm_init failed in eval_mm_util"); 717 | 718 | for (i = 0; i < trace->num_ops; i++) { 719 | switch (trace->ops[i].type) { 720 | 721 | case ALLOC: /* mm_alloc */ 722 | index = trace->ops[i].index; 723 | size = trace->ops[i].size; 724 | 725 | if ((p = mm_malloc(size)) == NULL) 726 | app_error("mm_malloc failed in eval_mm_util"); 727 | 728 | /* Remember region and size */ 729 | trace->blocks[index] = p; 730 | trace->block_sizes[index] = size; 731 | 732 | /* Keep track of current total size 733 | * of all allocated blocks */ 734 | total_size += size; 735 | 736 | /* Update statistics */ 737 | max_total_size = (total_size > max_total_size) ? 738 | total_size : max_total_size; 739 | break; 740 | 741 | case REALLOC: /* mm_realloc */ 742 | index = trace->ops[i].index; 743 | newsize = trace->ops[i].size; 744 | oldsize = trace->block_sizes[index]; 745 | 746 | oldp = trace->blocks[index]; 747 | if ((newp = mm_realloc(oldp,newsize)) == NULL) 748 | app_error("mm_realloc failed in eval_mm_util"); 749 | 750 | /* Remember region and size */ 751 | trace->blocks[index] = newp; 752 | trace->block_sizes[index] = newsize; 753 | 754 | /* Keep track of current total size 755 | * of all allocated blocks */ 756 | total_size += (newsize - oldsize); 757 | 758 | /* Update statistics */ 759 | max_total_size = (total_size > max_total_size) ? 760 | total_size : max_total_size; 761 | break; 762 | 763 | case FREE: /* mm_free */ 764 | index = trace->ops[i].index; 765 | size = trace->block_sizes[index]; 766 | p = trace->blocks[index]; 767 | 768 | mm_free(p); 769 | 770 | /* Keep track of current total size 771 | * of all allocated blocks */ 772 | total_size -= size; 773 | 774 | break; 775 | 776 | default: 777 | app_error("Nonexistent request type in eval_mm_util"); 778 | 779 | } 780 | } 781 | 782 | return ((double)max_total_size / (double)mem_heapsize()); 783 | } 784 | 785 | 786 | /* 787 | * eval_mm_speed - This is the function that is used by fcyc() 788 | * to measure the running time of the mm malloc package. 789 | */ 790 | static void eval_mm_speed(void *ptr) 791 | { 792 | unsigned i, index, size, newsize; 793 | char *p, *newp, *oldp, *block; 794 | trace_t *trace = ((speed_t *)ptr)->trace; 795 | 796 | /* Reset the heap and initialize the mm package */ 797 | mem_reset_brk(); 798 | if (mm_init() < 0) 799 | app_error("mm_init failed in eval_mm_speed"); 800 | 801 | /* Interpret each trace request */ 802 | for (i = 0; i < trace->num_ops; i++) 803 | switch (trace->ops[i].type) { 804 | 805 | case ALLOC: /* mm_malloc */ 806 | index = trace->ops[i].index; 807 | size = trace->ops[i].size; 808 | if ((p = mm_malloc(size)) == NULL) 809 | app_error("mm_malloc error in eval_mm_speed"); 810 | trace->blocks[index] = p; 811 | break; 812 | 813 | case REALLOC: /* mm_realloc */ 814 | index = trace->ops[i].index; 815 | newsize = trace->ops[i].size; 816 | oldp = trace->blocks[index]; 817 | if ((newp = mm_realloc(oldp,newsize)) == NULL) 818 | app_error("mm_realloc error in eval_mm_speed"); 819 | trace->blocks[index] = newp; 820 | break; 821 | 822 | case FREE: /* mm_free */ 823 | index = trace->ops[i].index; 824 | block = trace->blocks[index]; 825 | mm_free(block); 826 | break; 827 | 828 | default: 829 | app_error("Nonexistent request type in eval_mm_valid"); 830 | } 831 | } 832 | 833 | /* 834 | * eval_libc_valid - We run this function to make sure that the 835 | * libc malloc can run to completion on the set of traces. 836 | * We'll be conservative and terminate if any libc malloc call fails. 837 | * 838 | */ 839 | static int eval_libc_valid(trace_t *trace, int tracenum) 840 | { 841 | unsigned i, newsize; 842 | char *p, *newp, *oldp; 843 | 844 | for (i = 0; i < trace->num_ops; i++) { 845 | switch (trace->ops[i].type) { 846 | 847 | case ALLOC: /* malloc */ 848 | if ((p = malloc(trace->ops[i].size)) == NULL) { 849 | malloc_error(tracenum, i, "libc malloc failed"); 850 | unix_error("System message"); 851 | } 852 | trace->blocks[trace->ops[i].index] = p; 853 | break; 854 | 855 | case REALLOC: /* realloc */ 856 | newsize = trace->ops[i].size; 857 | oldp = trace->blocks[trace->ops[i].index]; 858 | if ((newp = realloc(oldp, newsize)) == NULL) { 859 | malloc_error(tracenum, i, "libc realloc failed"); 860 | unix_error("System message"); 861 | } 862 | trace->blocks[trace->ops[i].index] = newp; 863 | break; 864 | 865 | case FREE: /* free */ 866 | free(trace->blocks[trace->ops[i].index]); 867 | break; 868 | 869 | default: 870 | app_error("invalid operation type in eval_libc_valid"); 871 | } 872 | } 873 | 874 | return 1; 875 | } 876 | 877 | /* 878 | * eval_libc_speed - This is the function that is used by fcyc() to 879 | * measure the running time of the libc malloc package on the set 880 | * of traces. 881 | */ 882 | static void eval_libc_speed(void *ptr) 883 | { 884 | unsigned i; 885 | int index, size, newsize; 886 | char *p, *newp, *oldp, *block; 887 | trace_t *trace = ((speed_t *)ptr)->trace; 888 | 889 | for (i = 0; i < trace->num_ops; i++) { 890 | switch (trace->ops[i].type) { 891 | case ALLOC: /* malloc */ 892 | index = trace->ops[i].index; 893 | size = trace->ops[i].size; 894 | if ((p = malloc(size)) == NULL) 895 | unix_error("malloc failed in eval_libc_speed"); 896 | trace->blocks[index] = p; 897 | break; 898 | 899 | case REALLOC: /* realloc */ 900 | index = trace->ops[i].index; 901 | newsize = trace->ops[i].size; 902 | oldp = trace->blocks[index]; 903 | if ((newp = realloc(oldp, newsize)) == NULL) 904 | unix_error("realloc failed in eval_libc_speed\n"); 905 | 906 | trace->blocks[index] = newp; 907 | break; 908 | 909 | case FREE: /* free */ 910 | index = trace->ops[i].index; 911 | block = trace->blocks[index]; 912 | free(block); 913 | break; 914 | } 915 | } 916 | } 917 | 918 | /************************************* 919 | * Some miscellaneous helper routines 920 | ************************************/ 921 | 922 | 923 | /* 924 | * printresults - prints a performance summary for some malloc package 925 | */ 926 | static void printresults(int n, stats_t *stats) 927 | { 928 | int i; 929 | double secs = 0; 930 | double ops = 0; 931 | double util = 0; 932 | 933 | /* Print the individual results for each trace */ 934 | /* All the space before the last number on each line is added by 935 | * Zheng Cai, for better formatting */ 936 | printf("%5s%7s %5s%8s%10s %6s\n", 937 | "trace", " valid", "util", "ops", "secs", "Kops"); 938 | for (i=0; i < n; i++) { 939 | if (stats[i].valid) { 940 | printf("%2d%10s%5.0f%%%8.0f%10.6f %6.0f\n", 941 | i, 942 | "yes", 943 | stats[i].util*100.0, 944 | stats[i].ops, 945 | stats[i].secs, 946 | (stats[i].ops/1e3)/stats[i].secs); 947 | secs += stats[i].secs; 948 | ops += stats[i].ops; 949 | util += stats[i].util; 950 | } 951 | else { 952 | printf("%2d%10s%6s%8s%10s %6s\n", 953 | i, 954 | "no", 955 | "-", 956 | "-", 957 | "-", 958 | "-"); 959 | } 960 | } 961 | 962 | /* Print the aggregate results for the set of traces */ 963 | if (errors == 0) { 964 | printf("%12s%5.0f%%%8.0f%10.6f %6.0f\n", 965 | "Total ", 966 | (util/n)*100.0, 967 | ops, 968 | secs, 969 | (ops/1e3)/secs); 970 | } 971 | else { 972 | printf("%12s%6s%8s%10s %6s\n", 973 | "Total ", 974 | "-", 975 | "-", 976 | "-", 977 | "-"); 978 | } 979 | 980 | } 981 | 982 | /* 983 | * app_error - Report an arbitrary application error 984 | */ 985 | void app_error(char *msg) 986 | { 987 | printf("%s\n", msg); 988 | exit(1); 989 | } 990 | 991 | /* 992 | * unix_error - Report a Unix-style error 993 | */ 994 | void unix_error(char *msg) 995 | { 996 | printf("%s: %s\n", msg, strerror(errno)); 997 | exit(1); 998 | } 999 | 1000 | /* 1001 | * malloc_error - Report an error returned by the mm_malloc package 1002 | */ 1003 | void malloc_error(int tracenum, int opnum, char *msg) 1004 | { 1005 | errors++; 1006 | printf("ERROR [trace %d, line %d]: %s\n", tracenum, LINENUM(opnum), msg); 1007 | } 1008 | 1009 | /* 1010 | * usage - Explain the command line arguments 1011 | */ 1012 | static void usage(void) 1013 | { 1014 | fprintf(stderr, "Usage: mdriver [-hvVal] [-f ] [-t ]\n"); 1015 | fprintf(stderr, "Options\n"); 1016 | fprintf(stderr, "\t-a Don't check the team structure.\n"); 1017 | fprintf(stderr, "\t-f Use as the trace file.\n"); 1018 | fprintf(stderr, "\t-g Generate summary info for autograder.\n"); 1019 | fprintf(stderr, "\t-h Print this message.\n"); 1020 | fprintf(stderr, "\t-l Run libc malloc as well.\n"); 1021 | fprintf(stderr, "\t-t Directory to find default traces.\n"); 1022 | fprintf(stderr, "\t-v Print per-trace performance breakdowns.\n"); 1023 | fprintf(stderr, "\t-V Print additional debug info.\n"); 1024 | } 1025 | -------------------------------------------------------------------------------- /mdriver.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshTrivedi/malloc/031275f125c81bec3eb56bff95a1ce72f3554307/mdriver.o -------------------------------------------------------------------------------- /memlib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * memlib.c - a module that simulates the memory system. Needed because it 3 | * allows us to interleave calls from the student's malloc package 4 | * with the system's malloc package in libc. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "memlib.h" 15 | #include "config.h" 16 | 17 | /* private variables */ 18 | static char *mem_start_brk; /* points to first byte of heap */ 19 | static char *mem_brk; /* points to last byte of heap */ 20 | static char *mem_max_addr; /* largest legal heap address */ 21 | 22 | /* 23 | * mem_init - initialize the memory system model 24 | */ 25 | void mem_init(void) 26 | { 27 | /* allocate the storage we will use to model the available VM */ 28 | if ((mem_start_brk = (char *)malloc(MAX_HEAP)) == NULL) { 29 | fprintf(stderr, "mem_init_vm: malloc error\n"); 30 | exit(1); 31 | } 32 | 33 | mem_max_addr = mem_start_brk + MAX_HEAP; /* max legal heap address */ 34 | mem_brk = mem_start_brk; /* heap is empty initially */ 35 | } 36 | 37 | /* 38 | * mem_deinit - free the storage used by the memory system model 39 | */ 40 | void mem_deinit(void) 41 | { 42 | free(mem_start_brk); 43 | } 44 | 45 | /* 46 | * mem_reset_brk - reset the simulated brk pointer to make an empty heap 47 | */ 48 | void mem_reset_brk() 49 | { 50 | mem_brk = mem_start_brk; 51 | } 52 | 53 | /* 54 | * mem_sbrk - simple model of the sbrk function. Extends the heap 55 | * by incr bytes and returns the start address of the new area. In 56 | * this model, the heap cannot be shrunk. 57 | */ 58 | void *mem_sbrk(intptr_t incr) 59 | { 60 | char *old_brk = mem_brk; 61 | 62 | if ( (incr < 0) || ((mem_brk + incr) > mem_max_addr)) { 63 | errno = ENOMEM; 64 | fprintf(stderr, "ERROR: mem_sbrk failed. Ran out of memory...\n"); 65 | return (void *)-1; 66 | } 67 | mem_brk += incr; 68 | return (void *)old_brk; 69 | } 70 | 71 | /* 72 | * mem_heap_lo - return address of the first heap byte 73 | */ 74 | void *mem_heap_lo() 75 | { 76 | return (void *)mem_start_brk; 77 | } 78 | 79 | /* 80 | * mem_heap_hi - return address of last heap byte 81 | */ 82 | void *mem_heap_hi() 83 | { 84 | return (void *)(mem_brk - 1); 85 | } 86 | 87 | /* 88 | * mem_heapsize() - returns the heap size in bytes 89 | */ 90 | size_t mem_heapsize() 91 | { 92 | return (size_t)(mem_brk - mem_start_brk); 93 | } 94 | 95 | /* 96 | * mem_pagesize() - returns the page size of the system 97 | */ 98 | size_t mem_pagesize() 99 | { 100 | return (size_t)getpagesize(); 101 | } 102 | -------------------------------------------------------------------------------- /memlib.h: -------------------------------------------------------------------------------- 1 | void mem_init(void); 2 | void mem_deinit(void); 3 | void *mem_sbrk(intptr_t incr); 4 | void mem_reset_brk(void); 5 | void *mem_heap_lo(void); 6 | void *mem_heap_hi(void); 7 | size_t mem_heapsize(void); 8 | size_t mem_pagesize(void); 9 | -------------------------------------------------------------------------------- /memlib.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshTrivedi/malloc/031275f125c81bec3eb56bff95a1ce72f3554307/memlib.o -------------------------------------------------------------------------------- /mm.c: -------------------------------------------------------------------------------- 1 | /* Blocks are aligned to double-word boundaries. This 2 | * yields 8-byte aligned blocks on a 32-bit processor, and 16-byte aligned 3 | * blocks on a 64-bit processor. However, 16-byte alignment is stricter 4 | * than necessary; the assignment only requires 8-byte alignment. The 5 | * minimum block size taken is 4 words. 6 | * This allocator uses the size of a pointer, e.g., sizeof(void *), to 7 | * define the size of a word. This allocator also uses the standard 8 | * type uintptr_t to define unsigned integers that are the same size 9 | * as a pointer, i.e., sizeof(uintptr_t) == sizeof(void *). 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "memlib.h" 18 | #include "mm.h" 19 | /********************************************************* 20 | * NOTE TO STUDENTS: Before you do anything else, please 21 | * provide your team information in the following struct. 22 | ********************************************************/ 23 | 24 | team_t team = { 25 | "Memory Allocator", 26 | "HARSH TRIVEDI ", 27 | "201201042", 28 | "KARAN TANKSHALI ", 29 | "201201043" 30 | }; 31 | 32 | //* Basic constants and macros: */ 33 | #define WSIZE sizeof(void *) /* Word and header/footer size (bytes) */ 34 | #define DSIZE (2 * WSIZE) /* Doubleword size (bytes) */ 35 | #define CHUNKSIZE (1 << 12) /* Extend heap by this amount (bytes) */ 36 | 37 | /*Max value of 2 values*/ 38 | #define MAX(x, y) ((x) > (y) ? (x) : (y)) 39 | 40 | /* Pack a size and allocated bit into a word */ 41 | #define PACK(size, alloc) ((size) | (alloc)) 42 | 43 | /* Read and write a word at address p. */ 44 | #define GET(p) (*(uintptr_t *)(p)) 45 | #define PUT(p, val) (*(uintptr_t *)(p) = (val)) 46 | 47 | /* Read the size and allocated fields from address p */ 48 | #define GET_SIZE(p) (GET(p) & ~(DSIZE - 1)) 49 | #define GET_ALLOC(p) (GET(p) & 0x1) 50 | 51 | 52 | /* Given block ptr bp, compute address of its header and footer */ 53 | #define HDRP(bp) ((void *)(bp) - WSIZE) 54 | #define FTRP(bp) ((void *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) 55 | 56 | /* Given block ptr bp, compute address of next and previous blocks */ 57 | #define NEXT_BLK(bp) ((void *)(bp) + GET_SIZE(HDRP(bp))) 58 | #define PREV_BLK(bp) ((void *)(bp) - GET_SIZE((void *)(bp) - DSIZE)) 59 | 60 | /* Given ptr in free list, get next and previous ptr in the list */ 61 | /* bp is address of the free block. Since minimum Block size is 16 bytes, 62 | we utilize to store the address of previous block pointer and next block pointer. 63 | */ 64 | #define GET_NEXT_PTR(bp) (*(char **)(bp + WSIZE)) 65 | #define GET_PREV_PTR(bp) (*(char **)(bp)) 66 | 67 | /* Puts pointers in the next and previous elements of free list */ 68 | #define SET_NEXT_PTR(bp, qp) (GET_NEXT_PTR(bp) = qp) 69 | #define SET_PREV_PTR(bp, qp) (GET_PREV_PTR(bp) = qp) 70 | 71 | /* Global declarations */ 72 | static char *heap_listp = 0; 73 | static char *free_list_start = 0; 74 | 75 | /* Function prototypes for internal helper routines */ 76 | static void *coalesce(void *bp); 77 | static void *extend_heap(size_t words); 78 | static void *find_fit(size_t asize); 79 | static void place(void *bp, size_t asize); 80 | 81 | /* Function prototypes for maintaining free list*/ 82 | static void insert_in_free_list(void *bp); 83 | static void remove_from_free_list(void *bp); 84 | 85 | /* Function prototypes for heap consistency checker routines: */ 86 | static void checkblock(void *bp); 87 | static void checkheap(bool verbose); 88 | static void printblock(void *bp); 89 | 90 | /** 91 | * Initialize the memory manager. 92 | * @param - void no parameter passed in 93 | * @return - int 0 for success or -1 for failure 94 | */ 95 | int mm_init(void) { 96 | 97 | /* Create the initial empty heap. */ 98 | if ((heap_listp = mem_sbrk(8*WSIZE)) == NULL) 99 | return -1; 100 | 101 | PUT(heap_listp, 0); /* Alignment padding */ 102 | PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); /* Prologue header */ 103 | PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1)); /* Prologue footer */ 104 | PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */ 105 | free_list_start = heap_listp + 2*WSIZE; 106 | 107 | /* Extend the empty heap with a free block of minimum possible block size */ 108 | if (extend_heap(4) == NULL){ 109 | return -1; 110 | } 111 | return 0; 112 | } 113 | 114 | /* 115 | * Requires: 116 | * size of memory asked by the programmer. 117 | * 118 | * Effects: 119 | * Allocate a block with at least "size" bytes of payload, unless "size" is 120 | * zero. Returns the address of this block if the allocation was successful 121 | * and NULL otherwise. 122 | */ 123 | void *mm_malloc(size_t size) 124 | { 125 | size_t asize; /* Adjusted block size */ 126 | size_t extendsize; /* Amount to extend heap if no fit */ 127 | void *bp; 128 | 129 | /* Ignore spurious requests. */ 130 | if (size == 0) 131 | return (NULL); 132 | 133 | /* Adjust block size to include overhead and alignment reqs. */ 134 | if (size <= DSIZE) 135 | asize = 2 * DSIZE; 136 | else 137 | asize = DSIZE * ((size + DSIZE + (DSIZE - 1)) / DSIZE); 138 | 139 | /* Search the free list for a fit. */ 140 | if ((bp = find_fit(asize)) != NULL) { 141 | place(bp, asize); 142 | return (bp); 143 | } 144 | 145 | /* No fit found. Get more memory and place the block. */ 146 | extendsize = MAX(asize, CHUNKSIZE); 147 | if ((bp = extend_heap(extendsize / WSIZE)) == NULL) 148 | return (NULL); 149 | place(bp, asize); 150 | return (bp); 151 | } 152 | 153 | /* 154 | * Requires: 155 | * "bp" is either the address of an allocated block or NULL. 156 | * 157 | * Effects: 158 | * Free a block. 159 | */ 160 | void mm_free(void *bp){ 161 | size_t size; 162 | /* Ignore spurious requests. */ 163 | if (bp == NULL) 164 | return; 165 | /* Free and coalesce the block. */ 166 | size = GET_SIZE(HDRP(bp)); 167 | PUT(HDRP(bp), PACK(size, 0)); 168 | PUT(FTRP(bp), PACK(size, 0)); 169 | coalesce(bp); 170 | } 171 | 172 | /* 173 | * Requires: 174 | * "ptr" is either the address of an allocated block or NULL. 175 | * 176 | * Effects: 177 | * Reallocates the block "ptr" to a block with at least "size" bytes of 178 | * payload, unless "size" is zero. 179 | * If "size" is zero, frees the block "ptr" and returns NULL. 180 | * If the block "ptr" is already a block with at 181 | * least "size" bytes of payload, then "ptr" may optionally be returned. 182 | * Further if requested size is greater than the current block size at pointer bp 183 | * and we have the next block as empty with sum of current block size and next block (which happens to be empty) 184 | * then we dont need call malloc but just combine current block and next block to resize them so as to 185 | * satisfy the requested realloc size. 186 | * If nothing can be done then a new block is allocated (using malloc) and the contents of the old block 187 | * "ptr" are copied to that new block. Returns the address of this new 188 | * block if the allocation was successful and NULL otherwise. 189 | */ 190 | void *mm_realloc(void *bp, size_t size){ 191 | if((int)size < 0) 192 | return NULL; 193 | else if((int)size == 0){ 194 | mm_free(bp); 195 | return NULL; 196 | } 197 | else if(size > 0){ 198 | size_t oldsize = GET_SIZE(HDRP(bp)); 199 | size_t newsize = size + 2 * WSIZE; // 2 words for header and footer 200 | /*if newsize is less than oldsize then we just return bp */ 201 | if(newsize <= oldsize){ 202 | return bp; 203 | } 204 | /*if newsize is greater than oldsize */ 205 | else { 206 | size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLK(bp))); 207 | size_t csize; 208 | /* next block is free and the size of the two blocks is greater than or equal the new size */ 209 | /* then we only need to combine both the blocks */ 210 | if(!next_alloc && ((csize = oldsize + GET_SIZE( HDRP(NEXT_BLK(bp)) ))) >= newsize){ 211 | remove_from_free_list(NEXT_BLK(bp)); 212 | PUT(HDRP(bp), PACK(csize, 1)); 213 | PUT(FTRP(bp), PACK(csize, 1)); 214 | return bp; 215 | } 216 | else { 217 | void *new_ptr = mm_malloc(newsize); 218 | place(new_ptr, newsize); 219 | memcpy(new_ptr, bp, newsize); 220 | mm_free(bp); 221 | return new_ptr; 222 | } 223 | } 224 | }else 225 | return NULL; 226 | } 227 | 228 | 229 | /* 230 | * Requires: 231 | * "bp" is the address of a newly freed block. 232 | * 233 | * Effects: 234 | * Perform boundary tag coalescing. 235 | * Removes and inserts appropiate free block pointers to the explicit free list 236 | * Returns the address of the coalesced block. 237 | */ 238 | static void *coalesce(void *bp){ 239 | 240 | //if previous block is allocated or its size is zero then PREV_ALLOC will be set. 241 | size_t NEXT_ALLOC = GET_ALLOC( HDRP(NEXT_BLK(bp)) ); 242 | size_t PREV_ALLOC = GET_ALLOC( FTRP(PREV_BLK(bp)) ) || PREV_BLK(bp) == bp; 243 | size_t size = GET_SIZE(HDRP(bp)); 244 | 245 | /* Next block is only free */ 246 | if (PREV_ALLOC && !NEXT_ALLOC) { 247 | size += GET_SIZE( HDRP(NEXT_BLK(bp)) ); 248 | remove_from_free_list(NEXT_BLK(bp)); 249 | PUT(HDRP(bp), PACK(size, 0)); 250 | PUT(FTRP(bp), PACK(size, 0)); 251 | } 252 | /* Prev block is only free */ 253 | else if (!PREV_ALLOC && NEXT_ALLOC) { 254 | size += GET_SIZE( HDRP(PREV_BLK(bp)) ); 255 | bp = PREV_BLK(bp); 256 | remove_from_free_list(bp); 257 | PUT(HDRP(bp), PACK(size, 0)); 258 | PUT(FTRP(bp), PACK(size, 0)); 259 | } 260 | /* Both blocks are free */ 261 | else if (!PREV_ALLOC && !NEXT_ALLOC) { 262 | size += GET_SIZE( HDRP(PREV_BLK(bp)) ) + GET_SIZE( HDRP(NEXT_BLK(bp)) ); 263 | remove_from_free_list(PREV_BLK(bp)); 264 | remove_from_free_list(NEXT_BLK(bp)); 265 | bp = PREV_BLK(bp); 266 | PUT(HDRP(bp), PACK(size, 0)); 267 | PUT(FTRP(bp), PACK(size, 0)); 268 | }/* lastly insert bp into free list and return bp */ 269 | insert_in_free_list(bp); 270 | return bp; 271 | } 272 | 273 | /* 274 | * Requires: 275 | * None. 276 | * 277 | * Effects: 278 | * Extend the heap with a free block and return that block's address. 279 | */ 280 | 281 | static void *extend_heap(size_t words) { 282 | char *bp; 283 | size_t size; 284 | 285 | /* Allocate an even number of words to maintain alignment */ 286 | size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; 287 | //Since minimum block size given to us is 4 words (ie 16 bytes) 288 | if (size < 16){ 289 | size = 16; 290 | } 291 | /* call for more memory space */ 292 | if ((int)(bp = mem_sbrk(size)) == -1){ 293 | return NULL; 294 | } 295 | /* Initialize free block header/footer and the epilogue header */ 296 | PUT(HDRP(bp), PACK(size, 0)); /* free block header */ 297 | PUT(FTRP(bp), PACK(size, 0)); /* free block footer */ 298 | PUT(HDRP(NEXT_BLK(bp)), PACK(0, 1)); /* new epilogue header */ 299 | /* coalesce bp with next and previous blocks */ 300 | return coalesce(bp); 301 | } 302 | 303 | /* 304 | * Requires: 305 | * Size of memory to find. 306 | * Effects: 307 | * Finds a fit for a block with "asize" bytes from the free list. 308 | * Extends the heap in some special cases. 309 | * And Returns that block's address 310 | * or NULL if no suitable block was found. 311 | */ 312 | 313 | static void *find_fit(size_t asize){ 314 | void *bp; 315 | static int last_malloced_size = 0; 316 | static int repeat_counter = 0; 317 | if( last_malloced_size == (int)asize){ 318 | if(repeat_counter>30){ 319 | int extendsize = MAX(asize, 4 * WSIZE); 320 | bp = extend_heap(extendsize/4); 321 | return bp; 322 | } 323 | else 324 | repeat_counter++; 325 | } 326 | else 327 | repeat_counter = 0; 328 | for (bp = free_list_start; GET_ALLOC(HDRP(bp)) == 0; bp = GET_NEXT_PTR(bp) ){ 329 | if (asize <= (size_t)GET_SIZE(HDRP(bp)) ) { 330 | last_malloced_size = asize; 331 | return bp; 332 | } 333 | } 334 | return NULL; 335 | } 336 | 337 | /* 338 | * Requires: 339 | * "bp" is the address of a free block that is at least "asize" bytes. 340 | * Effects: 341 | * Place a block of "asize" bytes at the start of the free block "bp" and 342 | * split that block if the remainder would be at least the minimum block 343 | * size. 344 | */ 345 | static void place(void *bp, size_t asize){ 346 | size_t csize = GET_SIZE(HDRP(bp)); 347 | 348 | if ((csize - asize) >= 4 * WSIZE) { 349 | PUT(HDRP(bp), PACK(asize, 1)); 350 | PUT(FTRP(bp), PACK(asize, 1)); 351 | remove_from_free_list(bp); 352 | bp = NEXT_BLK(bp); 353 | PUT(HDRP(bp), PACK(csize-asize, 0)); 354 | PUT(FTRP(bp), PACK(csize-asize, 0)); 355 | coalesce(bp); 356 | } 357 | else { 358 | PUT(HDRP(bp), PACK(csize, 1)); 359 | PUT(FTRP(bp), PACK(csize, 1)); 360 | remove_from_free_list(bp); 361 | } 362 | } 363 | 364 | /*Inserts the free block pointer int the free_list*/ 365 | static void insert_in_free_list(void *bp){ 366 | SET_NEXT_PTR(bp, free_list_start); 367 | SET_PREV_PTR(free_list_start, bp); 368 | SET_PREV_PTR(bp, NULL); 369 | free_list_start = bp; 370 | } 371 | /*Removes the free block pointer int the free_list*/ 372 | static void remove_from_free_list(void *bp){ 373 | if (GET_PREV_PTR(bp)) 374 | SET_NEXT_PTR(GET_PREV_PTR(bp), GET_NEXT_PTR(bp)); 375 | else 376 | free_list_start = GET_NEXT_PTR(bp); 377 | SET_PREV_PTR(GET_NEXT_PTR(bp), GET_PREV_PTR(bp)); 378 | } 379 | 380 | 381 | /* 382 | * The remaining routines are heap consistency checker routines. 383 | */ 384 | 385 | /* 386 | * Requires: 387 | * "bp" is the address of a block. 388 | * 389 | * Effects: 390 | * Perform a minimal check on the block "bp". 391 | */ 392 | static void 393 | checkblock(void *bp) 394 | { 395 | 396 | if ((uintptr_t)bp % DSIZE) 397 | printf("Error: %p is not doubleword aligned\n", bp); 398 | if (GET(HDRP(bp)) != GET(FTRP(bp))) 399 | printf("Error: header does not match footer\n"); 400 | } 401 | 402 | /* 403 | * Requires: 404 | * None. 405 | * 406 | * Effects: 407 | * Perform a minimal check of the heap for consistency. 408 | */ 409 | void 410 | checkheap(bool verbose) 411 | { 412 | void *bp; 413 | 414 | if (verbose) 415 | printf("Heap (%p):\n", heap_listp); 416 | 417 | if (GET_SIZE(HDRP(heap_listp)) != DSIZE || 418 | !GET_ALLOC(HDRP(heap_listp))) 419 | printf("Bad prologue header\n"); 420 | checkblock(heap_listp); 421 | 422 | for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = (void *)NEXT_BLKP(bp)) { 423 | if (verbose) 424 | printblock(bp); 425 | checkblock(bp); 426 | } 427 | 428 | if (verbose) 429 | printblock(bp); 430 | if (GET_SIZE(HDRP(bp)) != 0 || !GET_ALLOC(HDRP(bp))) 431 | printf("Bad epilogue header\n"); 432 | } 433 | 434 | /* 435 | * Requires: 436 | * "bp" is the address of a block. 437 | * 438 | * Effects: 439 | * Print the block "bp". 440 | */ 441 | static void 442 | printblock(void *bp) 443 | { 444 | bool halloc, falloc; 445 | size_t hsize, fsize; 446 | 447 | checkheap(false); 448 | hsize = GET_SIZE(HDRP(bp)); 449 | halloc = GET_ALLOC(HDRP(bp)); 450 | fsize = GET_SIZE(FTRP(bp)); 451 | falloc = GET_ALLOC(FTRP(bp)); 452 | 453 | if (hsize == 0) { 454 | printf("%p: end of heap\n", bp); 455 | return; 456 | } 457 | 458 | printf("%p: header: [%zu:%c] footer: [%zu:%c]\n", bp, 459 | hsize, (halloc ? 'a' : 'f'), 460 | fsize, (falloc ? 'a' : 'f')); 461 | } 462 | 463 | 464 | /* 465 | * The last lines of this file configures the behavior of the "Tab" key in 466 | * emacs. Emacs has a rudimentary understanding of C syntax and style. In 467 | * particular, depressing the "Tab" key once at the start of a new line will 468 | * insert as many tabs and/or spaces as are needed for proper indentation. 469 | */ 470 | 471 | /* Local Variables: */ 472 | /* mode: c */ 473 | /* c-default-style: "bsd" */ 474 | /* c-basic-offset: 8 */ 475 | /* c-continued-statement-offset: 4 */ 476 | /* indent-tabs-mode: t */ 477 | /* End: */ 478 | -------------------------------------------------------------------------------- /mm.c~: -------------------------------------------------------------------------------- 1 | /* Blocks are aligned to double-word boundaries. This 2 | * yields 8-byte aligned blocks on a 32-bit processor, and 16-byte aligned 3 | * blocks on a 64-bit processor. However, 16-byte alignment is stricter 4 | * than necessary; the assignment only requires 8-byte alignment. The 5 | * minimum block size taken is 4 words. 6 | * This allocator uses the size of a pointer, e.g., sizeof(void *), to 7 | * define the size of a word. This allocator also uses the standard 8 | * type uintptr_t to define unsigned integers that are the same size 9 | * as a pointer, i.e., sizeof(uintptr_t) == sizeof(void *). 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "memlib.h" 18 | #include "mm.h" 19 | /********************************************************* 20 | * NOTE TO STUDENTS: Before you do anything else, please 21 | * provide your team information in the following struct. 22 | ********************************************************/ 23 | 24 | team_t team = { 25 | "Memory Allocator", 26 | "HARSH TRIVEDI ", 27 | "201201042", 28 | "KARAN TANKSHALI ", 29 | "201201043" 30 | }; 31 | 32 | //* Basic constants and macros: */ 33 | #define WSIZE sizeof(void *) /* Word and header/footer size (bytes) */ 34 | #define DSIZE (2 * WSIZE) /* Doubleword size (bytes) */ 35 | #define CHUNKSIZE (1 << 12) /* Extend heap by this amount (bytes) */ 36 | 37 | /*Max value of 2 values*/ 38 | #define MAX(x, y) ((x) > (y) ? (x) : (y)) 39 | 40 | /* Pack a size and allocated bit into a word */ 41 | #define PACK(size, alloc) ((size) | (alloc)) 42 | 43 | /* Read and write a word at address p. */ 44 | #define GET(p) (*(uintptr_t *)(p)) 45 | #define PUT(p, val) (*(uintptr_t *)(p) = (val)) 46 | 47 | /* Read the size and allocated fields from address p */ 48 | #define GET_SIZE(p) (GET(p) & ~(DSIZE - 1)) 49 | #define GET_ALLOC(p) (GET(p) & 0x1) 50 | 51 | 52 | /* Given block ptr bp, compute address of its header and footer */ 53 | #define HDRP(bp) ((void *)(bp) - WSIZE) 54 | #define FTRP(bp) ((void *)(bp) + GET_SIZE(HDRP(bp)) - DSIZE) 55 | 56 | /* Given block ptr bp, compute address of next and previous blocks */ 57 | #define NEXT_BLK(bp) ((void *)(bp) + GET_SIZE(HDRP(bp))) 58 | #define PREV_BLK(bp) ((void *)(bp) - GET_SIZE((void *)(bp) - DSIZE)) 59 | 60 | /* Given ptr in free list, get next and previous ptr in the list */ 61 | /* bp is address of the free block. Since minimum Block size is 16 bytes, 62 | we utilize to store the address of previous block pointer and next block pointer. 63 | */ 64 | #define GET_NEXT_PTR(bp) (*(char **)(bp + WSIZE)) 65 | #define GET_PREV_PTR(bp) (*(char **)(bp)) 66 | 67 | /* Puts pointers in the next and previous elements of free list */ 68 | #define SET_NEXT_PTR(bp, qp) (GET_NEXT_PTR(bp) = qp) 69 | #define SET_PREV_PTR(bp, qp) (GET_PREV_PTR(bp) = qp) 70 | 71 | /* Global declarations */ 72 | static char *heap_listp = 0; 73 | static char *free_list_start = 0; 74 | 75 | /* Function prototypes for internal helper routines */ 76 | static void *coalesce(void *bp); 77 | static void *extend_heap(size_t words); 78 | static void *find_fit(size_t asize); 79 | static void place(void *bp, size_t asize); 80 | 81 | /* Function prototypes for maintaining free list*/ 82 | static void insert_in_free_list(void *bp); 83 | static void remove_from_free_list(void *bp); 84 | 85 | /* Function prototypes for heap consistency checker routines: */ 86 | static void checkblock(void *bp); 87 | static void checkheap(bool verbose); 88 | static void printblock(void *bp); 89 | 90 | /** 91 | * Initialize the memory manager. 92 | * @param - void no parameter passed in 93 | * @return - int 0 for success or -1 for failure 94 | */ 95 | int mm_init(void) { 96 | 97 | /* Create the initial empty heap. */ 98 | if ((heap_listp = mem_sbrk(8*WSIZE)) == NULL) 99 | return -1; 100 | 101 | PUT(heap_listp, 0); /* Alignment padding */ 102 | PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); /* Prologue header */ 103 | PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1)); /* Prologue footer */ 104 | PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */ 105 | free_list_start = heap_listp + 2*WSIZE; 106 | 107 | /* Extend the empty heap with a free block of minimum possible block size */ 108 | if (extend_heap(4) == NULL){ 109 | return -1; 110 | } 111 | return 0; 112 | } 113 | 114 | /* 115 | * Requires: 116 | * size of memory asked by the programmer. 117 | * 118 | * Effects: 119 | * Allocate a block with at least "size" bytes of payload, unless "size" is 120 | * zero. Returns the address of this block if the allocation was successful 121 | * and NULL otherwise. 122 | */ 123 | void *mm_malloc(size_t size) 124 | { 125 | size_t asize; /* Adjusted block size */ 126 | size_t extendsize; /* Amount to extend heap if no fit */ 127 | void *bp; 128 | 129 | /* Ignore spurious requests. */ 130 | if (size == 0) 131 | return (NULL); 132 | 133 | /* Adjust block size to include overhead and alignment reqs. */ 134 | if (size <= DSIZE) 135 | asize = 2 * DSIZE; 136 | else 137 | asize = DSIZE * ((size + DSIZE + (DSIZE - 1)) / DSIZE); 138 | 139 | /* Search the free list for a fit. */ 140 | if ((bp = find_fit(asize)) != NULL) { 141 | place(bp, asize); 142 | return (bp); 143 | } 144 | 145 | /* No fit found. Get more memory and place the block. */ 146 | extendsize = MAX(asize, CHUNKSIZE); 147 | if ((bp = extend_heap(extendsize / WSIZE)) == NULL) 148 | return (NULL); 149 | place(bp, asize); 150 | return (bp); 151 | } 152 | 153 | /* 154 | * Requires: 155 | * "bp" is either the address of an allocated block or NULL. 156 | * 157 | * Effects: 158 | * Free a block. 159 | */ 160 | void mm_free(void *bp){ 161 | size_t size; 162 | /* Ignore spurious requests. */ 163 | if (bp == NULL) 164 | return; 165 | /* Free and coalesce the block. */ 166 | size = GET_SIZE(HDRP(bp)); 167 | PUT(HDRP(bp), PACK(size, 0)); 168 | PUT(FTRP(bp), PACK(size, 0)); 169 | coalesce(bp); 170 | } 171 | 172 | /* 173 | * Requires: 174 | * "ptr" is either the address of an allocated block or NULL. 175 | * 176 | * Effects: 177 | * Reallocates the block "ptr" to a block with at least "size" bytes of 178 | * payload, unless "size" is zero. 179 | * If "size" is zero, frees the block "ptr" and returns NULL. 180 | * If the block "ptr" is already a block with at 181 | * least "size" bytes of payload, then "ptr" may optionally be returned. 182 | * Further if requested size is greater than the current block size at pointer bp 183 | * and we have the next block as empty with sum of current block size and next block (which happens to be empty) 184 | * then we dont need call malloc but just combine current block and next block to resize them so as to 185 | * satisfy the requested realloc size. 186 | * If nothing can be done then a new block is allocated (using malloc) and the contents of the old block 187 | * "ptr" are copied to that new block. Returns the address of this new 188 | * block if the allocation was successful and NULL otherwise. 189 | */ 190 | void *mm_realloc(void *bp, size_t size){ 191 | if((int)size < 0) 192 | return NULL; 193 | else if((int)size == 0){ 194 | mm_free(bp); 195 | return NULL; 196 | } 197 | else if(size > 0){ 198 | size_t oldsize = GET_SIZE(HDRP(bp)); 199 | size_t newsize = size + 2 * WSIZE; // 2 words for header and footer 200 | /*if newsize is less than oldsize then we just return bp */ 201 | if(newsize <= oldsize){ 202 | return bp; 203 | } 204 | /*if newsize is greater than oldsize */ 205 | else { 206 | size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLK(bp))); 207 | size_t csize; 208 | /* next block is free and the size of the two blocks is greater than or equal the new size */ 209 | /* then we only need to combine both the blocks */ 210 | if(!next_alloc && ((csize = oldsize + GET_SIZE( HDRP(NEXT_BLK(bp)) ))) >= newsize){ 211 | remove_from_free_list(NEXT_BLK(bp)); 212 | PUT(HDRP(bp), PACK(csize, 1)); 213 | PUT(FTRP(bp), PACK(csize, 1)); 214 | return bp; 215 | } 216 | else { 217 | void *new_ptr = mm_malloc(newsize); 218 | place(new_ptr, newsize); 219 | memcpy(new_ptr, bp, newsize); 220 | mm_free(bp); 221 | return new_ptr; 222 | } 223 | } 224 | }else 225 | return NULL; 226 | } 227 | 228 | 229 | /* 230 | * Requires: 231 | * "bp" is the address of a newly freed block. 232 | * 233 | * Effects: 234 | * Perform boundary tag coalescing. 235 | * Removes and inserts appropiate free block pointers to the explicit free list 236 | * Returns the address of the coalesced block. 237 | */ 238 | static void *coalesce(void *bp){ 239 | 240 | //if previous block is allocated or its size is zero then PREV_ALLOC will be set. 241 | size_t NEXT_ALLOC = GET_ALLOC( HDRP(NEXT_BLK(bp)) ); 242 | size_t PREV_ALLOC = GET_ALLOC( FTRP(PREV_BLK(bp)) ) || PREV_BLK(bp) == bp; 243 | size_t size = GET_SIZE(HDRP(bp)); 244 | 245 | /* Next block is only free */ 246 | if (PREV_ALLOC && !NEXT_ALLOC) { 247 | size += GET_SIZE( HDRP(NEXT_BLK(bp)) ); 248 | remove_from_free_list(NEXT_BLK(bp)); 249 | PUT(HDRP(bp), PACK(size, 0)); 250 | PUT(FTRP(bp), PACK(size, 0)); 251 | } 252 | /* Prev block is only free */ 253 | else if (!PREV_ALLOC && NEXT_ALLOC) { 254 | size += GET_SIZE( HDRP(PREV_BLK(bp)) ); 255 | bp = PREV_BLK(bp); 256 | remove_from_free_list(bp); 257 | PUT(HDRP(bp), PACK(size, 0)); 258 | PUT(FTRP(bp), PACK(size, 0)); 259 | } 260 | /* Both blocks are free */ 261 | else if (!PREV_ALLOC && !NEXT_ALLOC) { 262 | size += GET_SIZE( HDRP(PREV_BLK(bp)) ) + GET_SIZE( HDRP(NEXT_BLK(bp)) ); 263 | remove_from_free_list(PREV_BLK(bp)); 264 | remove_from_free_list(NEXT_BLK(bp)); 265 | bp = PREV_BLK(bp); 266 | PUT(HDRP(bp), PACK(size, 0)); 267 | PUT(FTRP(bp), PACK(size, 0)); 268 | }/* lastly insert bp into free list and return bp */ 269 | insert_in_free_list(bp); 270 | return bp; 271 | } 272 | 273 | /* 274 | * Requires: 275 | * None. 276 | * 277 | * Effects: 278 | * Extend the heap with a free block and return that block's address. 279 | */ 280 | 281 | static void *extend_heap(size_t words) { 282 | char *bp; 283 | size_t size; 284 | 285 | /* Allocate an even number of words to maintain alignment */ 286 | size = (words % 2) ? (words+1) * WSIZE : words * WSIZE; 287 | //Since minimum block size given to us is 4 words (ie 16 bytes) 288 | if (size < 16){ 289 | size = 16; 290 | } 291 | /* call for more memory space */ 292 | if ((int)(bp = mem_sbrk(size)) == -1){ 293 | return NULL; 294 | } 295 | /* Initialize free block header/footer and the epilogue header */ 296 | PUT(HDRP(bp), PACK(size, 0)); /* free block header */ 297 | PUT(FTRP(bp), PACK(size, 0)); /* free block footer */ 298 | PUT(HDRP(NEXT_BLK(bp)), PACK(0, 1)); /* new epilogue header */ 299 | /* coalesce bp with next and previous blocks */ 300 | return coalesce(bp); 301 | } 302 | 303 | /* 304 | * Requires: 305 | * Size of memory to find. 306 | * Effects: 307 | * Finds a fit for a block with "asize" bytes from the free list. 308 | * Extends the heap in some special cases. 309 | * And Returns that block's address 310 | * or NULL if no suitable block was found. 311 | */ 312 | 313 | static void *find_fit(size_t asize){ 314 | void *bp; 315 | static int last_malloced_size = 0; 316 | static int repeat_counter = 0; 317 | if( last_malloced_size == (int)asize){ 318 | if(repeat_counter>30){ 319 | int extendsize = MAX(asize, 4 * WSIZE); 320 | bp = extend_heap(extendsize/4); 321 | return bp; 322 | } 323 | else 324 | repeat_counter++; 325 | } 326 | else 327 | repeat_counter = 0; 328 | for (bp = free_list_start; GET_ALLOC(HDRP(bp)) == 0; bp = GET_NEXT_PTR(bp) ){ 329 | if (asize <= (size_t)GET_SIZE(HDRP(bp)) ) { 330 | last_malloced_size = asize; 331 | return bp; 332 | } 333 | } 334 | return NULL; 335 | } 336 | 337 | /* 338 | * Requires: 339 | * "bp" is the address of a free block that is at least "asize" bytes. 340 | * Effects: 341 | * Place a block of "asize" bytes at the start of the free block "bp" and 342 | * split that block if the remainder would be at least the minimum block 343 | * size. 344 | */ 345 | static void place(void *bp, size_t asize){ 346 | size_t csize = GET_SIZE(HDRP(bp)); 347 | 348 | if ((csize - asize) >= 4 * WSIZE) { 349 | PUT(HDRP(bp), PACK(asize, 1)); 350 | PUT(FTRP(bp), PACK(asize, 1)); 351 | remove_from_free_list(bp); 352 | bp = NEXT_BLK(bp); 353 | PUT(HDRP(bp), PACK(csize-asize, 0)); 354 | PUT(FTRP(bp), PACK(csize-asize, 0)); 355 | coalesce(bp); 356 | } 357 | else { 358 | PUT(HDRP(bp), PACK(csize, 1)); 359 | PUT(FTRP(bp), PACK(csize, 1)); 360 | remove_from_free_list(bp); 361 | } 362 | } 363 | 364 | /*Inserts the free block pointer int the free_list*/ 365 | static void insert_in_free_list(void *bp){ 366 | SET_NEXT_PTR(bp, free_list_start); 367 | SET_PREV_PTR(free_list_start, bp); 368 | SET_PREV_PTR(bp, NULL); 369 | free_list_start = bp; 370 | } 371 | /*Removes the free block pointer int the free_list*/ 372 | static void remove_from_free_list(void *bp){ 373 | if (GET_PREV_PTR(bp)) 374 | SET_NEXT_PTR(GET_PREV_PTR(bp), GET_NEXT_PTR(bp)); 375 | else 376 | free_list_start = GET_NEXT_PTR(bp); 377 | SET_PREV_PTR(GET_NEXT_PTR(bp), GET_PREV_PTR(bp)); 378 | } 379 | 380 | 381 | /* 382 | * The remaining routines are heap consistency checker routines. 383 | */ 384 | 385 | /* 386 | * Requires: 387 | * "bp" is the address of a block. 388 | * 389 | * Effects: 390 | * Perform a minimal check on the block "bp". 391 | */ 392 | static void 393 | checkblock(void *bp) 394 | { 395 | 396 | if ((uintptr_t)bp % DSIZE) 397 | printf("Error: %p is not doubleword aligned\n", bp); 398 | if (GET(HDRP(bp)) != GET(FTRP(bp))) 399 | printf("Error: header does not match footer\n"); 400 | } 401 | 402 | /* 403 | * Requires: 404 | * None. 405 | * 406 | * Effects: 407 | * Perform a minimal check of the heap for consistency. 408 | */ 409 | void 410 | checkheap(bool verbose) 411 | { 412 | void *bp; 413 | 414 | if (verbose) 415 | printf("Heap (%p):\n", heap_listp); 416 | 417 | if (GET_SIZE(HDRP(heap_listp)) != DSIZE || 418 | !GET_ALLOC(HDRP(heap_listp))) 419 | printf("Bad prologue header\n"); 420 | checkblock(heap_listp); 421 | 422 | for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = (void *)NEXT_BLKP(bp)) { 423 | if (verbose) 424 | printblock(bp); 425 | checkblock(bp); 426 | } 427 | 428 | if (verbose) 429 | printblock(bp); 430 | if (GET_SIZE(HDRP(bp)) != 0 || !GET_ALLOC(HDRP(bp))) 431 | printf("Bad epilogue header\n"); 432 | } 433 | 434 | /* 435 | * Requires: 436 | * "bp" is the address of a block. 437 | * 438 | * Effects: 439 | * Print the block "bp". 440 | */ 441 | static void 442 | printblock(void *bp) 443 | { 444 | bool halloc, falloc; 445 | size_t hsize, fsize; 446 | 447 | checkheap(false); 448 | hsize = GET_SIZE(HDRP(bp)); 449 | halloc = GET_ALLOC(HDRP(bp)); 450 | fsize = GET_SIZE(FTRP(bp)); 451 | falloc = GET_ALLOC(FTRP(bp)); 452 | 453 | if (hsize == 0) { 454 | printf("%p: end of heap\n", bp); 455 | return; 456 | } 457 | 458 | printf("%p: header: [%zu:%c] footer: [%zu:%c]\n", bp, 459 | hsize, (halloc ? 'a' : 'f'), 460 | fsize, (falloc ? 'a' : 'f')); 461 | } 462 | 463 | 464 | /* 465 | * The last lines of this file configures the behavior of the "Tab" key in 466 | * emacs. Emacs has a rudimentary understanding of C syntax and style. In 467 | * particular, depressing the "Tab" key once at the start of a new line will 468 | * insert as many tabs and/or spaces as are needed for proper indentation. 469 | */ 470 | 471 | /* Local Variables: */ 472 | /* mode: c */ 473 | /* c-default-style: "bsd" */ 474 | /* c-basic-offset: 8 */ 475 | /* c-continued-statement-offset: 4 */ 476 | /* indent-tabs-mode: t */ 477 | /* End: */ 478 | -------------------------------------------------------------------------------- /mm.h: -------------------------------------------------------------------------------- 1 | /*- -*- mode: c; c-basic-offset: 4; -*- 2 | * 3 | * The public interface to the students' memory allocator. 4 | */ 5 | 6 | int mm_init(void); 7 | void *mm_malloc(size_t size); 8 | void mm_free(void *ptr); 9 | void *mm_realloc(void *ptr, size_t size); 10 | 11 | /* 12 | * Students work in teams of one or two. Teams enter their team name, personal 13 | * names and login IDs in a struct of this type in their mm.c file. 14 | */ 15 | typedef struct { 16 | char *teamname; /* ID1+ID2 or ID1 */ 17 | char *name1; /* Full name of first member. */ 18 | char *id1; /* Login ID of first member. */ 19 | char *name2; /* Full name of second member (if any). */ 20 | char *id2; /* Login ID of second member. */ 21 | } team_t; 22 | 23 | extern team_t team; 24 | -------------------------------------------------------------------------------- /mm.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HarshTrivedi/malloc/031275f125c81bec3eb56bff95a1ce72f3554307/mm.o -------------------------------------------------------------------------------- /short1-bal.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 2040 7 | f 1 8 | a 2 48 9 | a 3 4072 10 | f 3 11 | a 4 4072 12 | f 0 13 | f 2 14 | a 5 4072 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /short2-bal.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 4010 7 | a 2 48 8 | a 3 4072 9 | a 4 4072 10 | a 5 4072 11 | f 0 12 | f 1 13 | f 2 14 | f 3 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /traces/random2-bal.rep: -------------------------------------------------------------------------------- 1 | 38748551 2 | 2400 3 | 4800 4 | 1 5 | a 0 559 6 | a 1 1822 7 | a 2 19065 8 | a 3 14824 9 | a 4 9828 10 | a 5 10894 11 | a 6 1573 12 | a 7 12656 13 | a 8 21907 14 | a 9 1953 15 | a 10 9232 16 | a 11 6880 17 | a 12 14266 18 | a 13 4017 19 | a 14 21574 20 | a 15 28415 21 | a 16 28168 22 | a 17 28421 23 | a 18 66 24 | a 19 6251 25 | f 8 26 | a 20 14521 27 | a 21 8016 28 | a 22 14377 29 | a 23 26183 30 | a 24 30806 31 | a 25 30172 32 | a 26 13564 33 | a 27 15828 34 | a 28 18725 35 | a 29 27795 36 | a 30 2220 37 | a 31 19284 38 | a 32 29617 39 | a 33 21286 40 | a 34 1340 41 | a 35 6678 42 | a 36 32181 43 | a 37 2913 44 | a 38 19335 45 | a 39 21320 46 | a 40 4867 47 | a 41 28567 48 | a 42 28200 49 | a 43 19133 50 | a 44 32585 51 | a 45 17006 52 | a 46 14781 53 | a 47 27985 54 | a 48 12660 55 | a 49 14847 56 | a 50 1469 57 | a 51 27181 58 | a 52 22864 59 | a 53 15846 60 | a 54 20596 61 | a 55 20903 62 | a 56 13250 63 | a 57 1393 64 | a 58 3963 65 | a 59 31976 66 | a 60 29188 67 | a 61 6184 68 | a 62 18492 69 | a 63 26037 70 | a 64 27470 71 | a 65 19833 72 | a 66 32716 73 | a 67 26883 74 | a 68 22746 75 | a 69 19283 76 | a 70 15435 77 | a 71 27614 78 | a 72 15083 79 | a 73 10868 80 | a 74 13979 81 | a 75 14900 82 | a 76 27875 83 | a 77 28760 84 | a 78 10117 85 | a 79 7767 86 | a 80 10840 87 | f 78 88 | a 81 11586 89 | a 82 2180 90 | a 83 937 91 | a 84 27433 92 | a 85 22777 93 | a 86 21840 94 | a 87 7916 95 | a 88 24170 96 | a 89 25804 97 | a 90 7124 98 | a 91 20591 99 | a 92 31988 100 | a 93 25616 101 | a 94 13861 102 | a 95 26690 103 | a 96 12681 104 | a 97 13809 105 | a 98 20806 106 | a 99 2660 107 | a 100 324 108 | a 101 3474 109 | a 102 30275 110 | a 103 15407 111 | a 104 14342 112 | a 105 11487 113 | a 106 30308 114 | a 107 9449 115 | a 108 7480 116 | a 109 7657 117 | a 110 17216 118 | a 111 18321 119 | a 112 19244 120 | a 113 19397 121 | a 114 19258 122 | a 115 13910 123 | a 116 9406 124 | f 34 125 | a 117 8331 126 | a 118 21826 127 | a 119 809 128 | a 120 1367 129 | a 121 28950 130 | a 122 21400 131 | a 123 588 132 | a 124 21799 133 | a 125 2493 134 | a 126 27279 135 | a 127 1713 136 | a 128 16303 137 | a 129 15317 138 | a 130 4373 139 | a 131 16628 140 | a 132 18791 141 | a 133 1881 142 | a 134 32036 143 | a 135 366 144 | a 136 13368 145 | a 137 29576 146 | a 138 9815 147 | a 139 20848 148 | a 140 4466 149 | a 141 27032 150 | a 142 6401 151 | a 143 23710 152 | a 144 13661 153 | a 145 25660 154 | a 146 4853 155 | a 147 23068 156 | a 148 1223 157 | a 149 26679 158 | a 150 23878 159 | a 151 2591 160 | f 86 161 | a 152 22861 162 | a 153 12511 163 | a 154 3179 164 | a 155 11893 165 | a 156 15005 166 | a 157 30459 167 | a 158 13606 168 | a 159 31308 169 | a 160 13008 170 | a 161 17980 171 | a 162 15168 172 | a 163 31800 173 | a 164 19861 174 | a 165 14436 175 | a 166 32167 176 | a 167 461 177 | a 168 11245 178 | a 169 9215 179 | a 170 21309 180 | a 171 15711 181 | a 172 3479 182 | a 173 27711 183 | a 174 6654 184 | a 175 17141 185 | a 176 20603 186 | a 177 11507 187 | a 178 7442 188 | a 179 21826 189 | a 180 5418 190 | a 181 31320 191 | a 182 24418 192 | a 183 28280 193 | a 184 11063 194 | a 185 27597 195 | a 186 7405 196 | a 187 26068 197 | a 188 25288 198 | a 189 21011 199 | a 190 24609 200 | a 191 5529 201 | a 192 6223 202 | a 193 7009 203 | a 194 4562 204 | a 195 26085 205 | f 127 206 | a 196 21446 207 | f 4 208 | a 197 3961 209 | a 198 26546 210 | a 199 32691 211 | a 200 13176 212 | a 201 15088 213 | f 158 214 | f 101 215 | a 202 15635 216 | a 203 16656 217 | a 204 10031 218 | a 205 22289 219 | a 206 1029 220 | a 207 30634 221 | a 208 1029 222 | a 209 8471 223 | a 210 19693 224 | a 211 6448 225 | a 212 7023 226 | a 213 11343 227 | a 214 1960 228 | f 22 229 | a 215 18087 230 | a 216 6173 231 | a 217 9366 232 | a 218 11387 233 | f 38 234 | a 219 31462 235 | a 220 30378 236 | a 221 3229 237 | a 222 4223 238 | a 223 3834 239 | f 186 240 | a 224 10238 241 | a 225 8786 242 | a 226 29919 243 | a 227 31685 244 | f 222 245 | a 228 12747 246 | f 51 247 | a 229 23698 248 | a 230 31609 249 | a 231 25924 250 | a 232 6018 251 | a 233 14476 252 | f 200 253 | a 234 9812 254 | a 235 16049 255 | a 236 3998 256 | a 237 10842 257 | a 238 13916 258 | a 239 5027 259 | a 240 19313 260 | a 241 841 261 | a 242 11475 262 | a 243 26337 263 | f 183 264 | a 244 12185 265 | f 111 266 | a 245 13436 267 | a 246 11657 268 | a 247 18358 269 | f 71 270 | a 248 22802 271 | a 249 23045 272 | a 250 17052 273 | a 251 20413 274 | a 252 26274 275 | f 87 276 | a 253 21276 277 | a 254 24248 278 | a 255 3745 279 | a 256 30063 280 | a 257 21399 281 | a 258 2662 282 | f 227 283 | a 259 10043 284 | a 260 12330 285 | a 261 1503 286 | a 262 3199 287 | f 205 288 | a 263 18348 289 | a 264 15980 290 | a 265 13012 291 | a 266 1630 292 | f 189 293 | f 255 294 | a 267 19978 295 | f 195 296 | a 268 23855 297 | a 269 15546 298 | a 270 25005 299 | a 271 10401 300 | a 272 16388 301 | a 273 3712 302 | a 274 3970 303 | a 275 28574 304 | a 276 17149 305 | a 277 15628 306 | a 278 14164 307 | a 279 7184 308 | f 240 309 | a 280 5905 310 | a 281 31217 311 | a 282 27597 312 | a 283 32180 313 | a 284 19726 314 | a 285 19077 315 | a 286 3157 316 | f 201 317 | a 287 17021 318 | a 288 7709 319 | a 289 5819 320 | a 290 27064 321 | a 291 20039 322 | a 292 7323 323 | a 293 30264 324 | a 294 5620 325 | a 295 23303 326 | a 296 10509 327 | a 297 7250 328 | a 298 10513 329 | a 299 1596 330 | a 300 22796 331 | a 301 2751 332 | a 302 11997 333 | a 303 6417 334 | f 258 335 | a 304 6464 336 | f 119 337 | a 305 15968 338 | a 306 2223 339 | a 307 23613 340 | a 308 31596 341 | a 309 16388 342 | f 80 343 | a 310 30797 344 | a 311 4734 345 | f 113 346 | a 312 14838 347 | a 313 25627 348 | a 314 4146 349 | a 315 1796 350 | f 242 351 | a 316 11937 352 | a 317 7304 353 | a 318 18818 354 | f 138 355 | a 319 19646 356 | a 320 13123 357 | a 321 13115 358 | a 322 6918 359 | a 323 20447 360 | a 324 10612 361 | a 325 12538 362 | a 326 10983 363 | f 211 364 | a 327 21121 365 | a 328 19789 366 | a 329 21497 367 | a 330 22718 368 | a 331 9817 369 | a 332 24248 370 | a 333 1947 371 | a 334 16235 372 | a 335 30713 373 | a 336 17916 374 | a 337 18458 375 | a 338 21558 376 | a 339 16745 377 | a 340 2078 378 | a 341 19588 379 | a 342 21479 380 | f 306 381 | a 343 16916 382 | a 344 12447 383 | f 297 384 | a 345 25626 385 | a 346 18713 386 | a 347 24384 387 | a 348 162 388 | f 160 389 | a 349 4763 390 | a 350 11263 391 | a 351 13286 392 | a 352 17879 393 | a 353 18181 394 | f 123 395 | f 323 396 | a 354 966 397 | a 355 28491 398 | a 356 30720 399 | a 357 11949 400 | a 358 16845 401 | f 64 402 | a 359 17742 403 | a 360 678 404 | a 361 6795 405 | a 362 27560 406 | a 363 24927 407 | a 364 8742 408 | a 365 11027 409 | f 305 410 | a 366 22872 411 | a 367 26659 412 | a 368 29485 413 | a 369 11662 414 | a 370 10636 415 | a 371 31564 416 | a 372 31250 417 | a 373 32116 418 | a 374 15712 419 | a 375 10929 420 | a 376 24974 421 | a 377 1657 422 | a 378 2546 423 | a 379 25137 424 | a 380 6421 425 | a 381 13809 426 | a 382 5656 427 | a 383 24300 428 | f 379 429 | a 384 31991 430 | f 292 431 | f 307 432 | a 385 6622 433 | a 386 20024 434 | a 387 29944 435 | a 388 18571 436 | a 389 4101 437 | a 390 14918 438 | a 391 19250 439 | a 392 10896 440 | f 214 441 | a 393 9710 442 | f 31 443 | a 394 11409 444 | a 395 19639 445 | a 396 20737 446 | a 397 1513 447 | a 398 13530 448 | a 399 17455 449 | a 400 13176 450 | a 401 24166 451 | a 402 16251 452 | a 403 11659 453 | a 404 23514 454 | a 405 31963 455 | a 406 22589 456 | f 283 457 | a 407 15721 458 | a 408 853 459 | a 409 25135 460 | a 410 8091 461 | a 411 7275 462 | a 412 6176 463 | f 404 464 | a 413 13747 465 | a 414 31576 466 | a 415 5400 467 | a 416 20369 468 | a 417 18832 469 | a 418 2576 470 | a 419 6173 471 | a 420 22934 472 | a 421 17495 473 | f 342 474 | f 73 475 | f 286 476 | a 422 25423 477 | a 423 1063 478 | a 424 27205 479 | f 215 480 | a 425 4064 481 | a 426 20702 482 | a 427 15175 483 | a 428 5578 484 | a 429 1465 485 | a 430 32630 486 | a 431 18754 487 | a 432 25632 488 | a 433 16113 489 | a 434 30413 490 | a 435 16379 491 | a 436 15309 492 | f 217 493 | a 437 20234 494 | a 438 32101 495 | a 439 16163 496 | f 147 497 | a 440 12601 498 | a 441 7424 499 | a 442 23439 500 | f 63 501 | f 209 502 | a 443 18778 503 | a 444 21171 504 | a 445 22247 505 | a 446 24179 506 | f 321 507 | a 447 8772 508 | a 448 8312 509 | a 449 26755 510 | a 450 14945 511 | a 451 31246 512 | a 452 11483 513 | a 453 7600 514 | f 103 515 | f 299 516 | a 454 32309 517 | a 455 5920 518 | a 456 11665 519 | a 457 20244 520 | a 458 21096 521 | f 139 522 | a 459 17243 523 | a 460 21709 524 | a 461 20958 525 | a 462 3230 526 | a 463 14574 527 | a 464 4304 528 | f 422 529 | a 465 875 530 | a 466 30953 531 | a 467 19614 532 | f 107 533 | a 468 21110 534 | f 289 535 | a 469 30286 536 | a 470 3010 537 | a 471 944 538 | a 472 4942 539 | a 473 26449 540 | a 474 19722 541 | a 475 26113 542 | a 476 15929 543 | a 477 11134 544 | a 478 2118 545 | a 479 24241 546 | a 480 5121 547 | a 481 17063 548 | a 482 22719 549 | f 433 550 | a 483 16605 551 | a 484 24664 552 | a 485 22261 553 | a 486 22525 554 | a 487 3562 555 | a 488 9737 556 | a 489 10854 557 | a 490 20805 558 | a 491 31447 559 | a 492 31813 560 | a 493 24036 561 | f 152 562 | a 494 13253 563 | a 495 3349 564 | a 496 24911 565 | a 497 11438 566 | a 498 22964 567 | a 499 13254 568 | f 333 569 | a 500 8957 570 | a 501 25975 571 | f 245 572 | f 476 573 | a 502 14198 574 | a 503 13899 575 | a 504 19656 576 | f 56 577 | a 505 1153 578 | a 506 7245 579 | a 507 2817 580 | a 508 12287 581 | a 509 9363 582 | a 510 27059 583 | f 156 584 | a 511 17409 585 | a 512 26427 586 | a 513 17011 587 | f 177 588 | a 514 1246 589 | a 515 18323 590 | a 516 6504 591 | a 517 23772 592 | a 518 21885 593 | f 30 594 | f 220 595 | a 519 16242 596 | a 520 1858 597 | a 521 9923 598 | a 522 14921 599 | a 523 903 600 | f 25 601 | a 524 1191 602 | f 329 603 | a 525 28175 604 | f 343 605 | f 367 606 | a 526 4253 607 | a 527 26103 608 | a 528 6846 609 | a 529 27218 610 | a 530 6590 611 | a 531 15803 612 | a 532 20425 613 | f 185 614 | a 533 20788 615 | a 534 29703 616 | a 535 7314 617 | a 536 21942 618 | f 96 619 | a 537 4180 620 | a 538 10132 621 | a 539 1461 622 | a 540 13544 623 | a 541 4423 624 | f 462 625 | a 542 18871 626 | a 543 7203 627 | f 92 628 | a 544 21434 629 | f 104 630 | f 136 631 | a 545 20117 632 | a 546 25527 633 | f 399 634 | a 547 27938 635 | a 548 11122 636 | f 207 637 | a 549 14645 638 | f 449 639 | a 550 11413 640 | a 551 12980 641 | a 552 24569 642 | a 553 26334 643 | f 52 644 | a 554 13884 645 | a 555 25761 646 | f 336 647 | f 277 648 | a 556 21742 649 | a 557 18138 650 | a 558 19097 651 | f 509 652 | a 559 28588 653 | f 263 654 | a 560 12588 655 | a 561 25687 656 | a 562 11623 657 | a 563 245 658 | f 2 659 | a 564 13708 660 | f 390 661 | a 565 8559 662 | a 566 7560 663 | a 567 2882 664 | a 568 12740 665 | f 557 666 | a 569 17692 667 | a 570 4344 668 | a 571 26284 669 | a 572 22115 670 | a 573 23215 671 | a 574 720 672 | a 575 10781 673 | a 576 10565 674 | a 577 26248 675 | f 506 676 | a 578 5952 677 | a 579 21687 678 | a 580 8125 679 | a 581 17365 680 | a 582 1900 681 | a 583 32695 682 | f 423 683 | a 584 10932 684 | a 585 15784 685 | f 182 686 | a 586 25688 687 | f 447 688 | a 587 32674 689 | a 588 1155 690 | a 589 12017 691 | a 590 28494 692 | f 142 693 | a 591 13743 694 | a 592 4936 695 | f 174 696 | f 208 697 | a 593 7350 698 | a 594 13989 699 | f 575 700 | a 595 18644 701 | f 558 702 | f 234 703 | a 596 15910 704 | a 597 21549 705 | a 598 21527 706 | a 599 28650 707 | a 600 6473 708 | a 601 25871 709 | a 602 22167 710 | a 603 28589 711 | a 604 16318 712 | a 605 22887 713 | f 437 714 | a 606 6602 715 | a 607 26884 716 | a 608 16368 717 | f 334 718 | a 609 12555 719 | a 610 15803 720 | a 611 24493 721 | a 612 29921 722 | a 613 17704 723 | a 614 24420 724 | a 615 8085 725 | a 616 720 726 | f 400 727 | a 617 17341 728 | a 618 7992 729 | a 619 1875 730 | f 458 731 | a 620 29358 732 | a 621 3719 733 | f 150 734 | f 197 735 | f 605 736 | f 451 737 | a 622 15619 738 | a 623 1527 739 | a 624 11070 740 | a 625 29608 741 | a 626 20172 742 | a 627 26980 743 | a 628 18390 744 | a 629 8931 745 | a 630 22862 746 | a 631 24864 747 | a 632 2034 748 | f 47 749 | a 633 12262 750 | f 12 751 | a 634 20685 752 | f 463 753 | a 635 18353 754 | a 636 2382 755 | a 637 27288 756 | a 638 12469 757 | f 308 758 | f 347 759 | a 639 18750 760 | a 640 7076 761 | a 641 28272 762 | a 642 10475 763 | a 643 4229 764 | f 72 765 | f 639 766 | a 644 13208 767 | a 645 2128 768 | f 411 769 | f 337 770 | a 646 12314 771 | a 647 13929 772 | a 648 19469 773 | f 356 774 | a 649 20307 775 | a 650 15805 776 | f 542 777 | a 651 16060 778 | f 618 779 | a 652 24026 780 | a 653 31425 781 | a 654 17587 782 | a 655 2328 783 | a 656 28265 784 | a 657 4991 785 | a 658 29308 786 | a 659 13888 787 | f 369 788 | a 660 13922 789 | a 661 19403 790 | a 662 5984 791 | a 663 15956 792 | a 664 31666 793 | a 665 26670 794 | a 666 1542 795 | a 667 1280 796 | a 668 21191 797 | a 669 14011 798 | f 428 799 | f 394 800 | a 670 20030 801 | a 671 28267 802 | a 672 9515 803 | a 673 30506 804 | a 674 32497 805 | a 675 22724 806 | a 676 32634 807 | a 677 12043 808 | f 562 809 | a 678 3886 810 | f 256 811 | a 679 19336 812 | a 680 32350 813 | a 681 19692 814 | a 682 2628 815 | f 313 816 | a 683 23609 817 | a 684 18349 818 | f 620 819 | a 685 20215 820 | f 432 821 | f 665 822 | a 686 25937 823 | a 687 13847 824 | a 688 25207 825 | a 689 22478 826 | a 690 27735 827 | a 691 6361 828 | a 692 9113 829 | a 693 952 830 | a 694 22318 831 | f 603 832 | f 663 833 | a 695 8011 834 | a 696 27623 835 | f 676 836 | f 435 837 | a 697 23860 838 | f 667 839 | a 698 9292 840 | a 699 16046 841 | a 700 5103 842 | f 683 843 | a 701 29322 844 | a 702 11546 845 | a 703 14619 846 | f 175 847 | a 704 27060 848 | a 705 11275 849 | a 706 4576 850 | f 670 851 | a 707 26927 852 | a 708 23319 853 | a 709 8462 854 | a 710 13496 855 | a 711 22902 856 | a 712 28154 857 | f 97 858 | f 284 859 | a 713 16125 860 | a 714 13743 861 | f 162 862 | f 587 863 | a 715 13735 864 | f 98 865 | a 716 3573 866 | f 606 867 | a 717 6913 868 | a 718 27583 869 | f 248 870 | a 719 28780 871 | a 720 29391 872 | a 721 22550 873 | f 312 874 | f 164 875 | a 722 2373 876 | a 723 5737 877 | a 724 23503 878 | a 725 24692 879 | a 726 13749 880 | f 505 881 | f 532 882 | a 727 18358 883 | a 728 15784 884 | a 729 23041 885 | a 730 1637 886 | a 731 20888 887 | a 732 19595 888 | f 503 889 | f 362 890 | a 733 13184 891 | a 734 2739 892 | a 735 13888 893 | f 415 894 | f 77 895 | a 736 24460 896 | a 737 7316 897 | f 674 898 | f 425 899 | a 738 8048 900 | a 739 15011 901 | a 740 15779 902 | a 741 21545 903 | a 742 5146 904 | a 743 11165 905 | a 744 4902 906 | a 745 18889 907 | a 746 24901 908 | a 747 8475 909 | f 395 910 | a 748 25802 911 | a 749 19716 912 | a 750 4487 913 | a 751 22426 914 | a 752 9499 915 | a 753 6861 916 | a 754 28163 917 | a 755 234 918 | f 355 919 | f 143 920 | a 756 31553 921 | a 757 9144 922 | f 655 923 | a 758 18593 924 | a 759 14570 925 | a 760 32185 926 | f 85 927 | a 761 20231 928 | a 762 2690 929 | a 763 19013 930 | a 764 647 931 | a 765 5430 932 | a 766 134 933 | f 690 934 | a 767 25107 935 | a 768 12746 936 | a 769 8182 937 | a 770 7351 938 | a 771 28525 939 | a 772 29728 940 | a 773 12497 941 | f 529 942 | a 774 6923 943 | a 775 1862 944 | a 776 31387 945 | f 692 946 | f 477 947 | a 777 31825 948 | a 778 10337 949 | f 257 950 | a 779 24422 951 | a 780 18774 952 | a 781 14825 953 | a 782 14080 954 | a 783 28273 955 | a 784 21686 956 | a 785 9475 957 | a 786 28508 958 | a 787 20472 959 | a 788 18619 960 | a 789 14333 961 | a 790 2274 962 | f 454 963 | a 791 18037 964 | a 792 1797 965 | a 793 4964 966 | a 794 4282 967 | a 795 2444 968 | a 796 10395 969 | a 797 4416 970 | a 798 27552 971 | a 799 23141 972 | f 32 973 | a 800 12599 974 | a 801 2135 975 | f 628 976 | a 802 18899 977 | a 803 9560 978 | a 804 14632 979 | a 805 25823 980 | a 806 11422 981 | f 592 982 | f 686 983 | a 807 13252 984 | f 83 985 | a 808 24880 986 | a 809 21760 987 | f 392 988 | a 810 4906 989 | a 811 10887 990 | a 812 3817 991 | f 717 992 | a 813 18987 993 | a 814 6393 994 | a 815 25504 995 | f 282 996 | a 816 28462 997 | a 817 2133 998 | a 818 13208 999 | a 819 14314 1000 | a 820 16467 1001 | f 560 1002 | a 821 15482 1003 | a 822 32352 1004 | a 823 18264 1005 | a 824 20447 1006 | a 825 3867 1007 | a 826 20709 1008 | f 678 1009 | a 827 30842 1010 | a 828 8283 1011 | a 829 15493 1012 | f 290 1013 | f 384 1014 | a 830 21216 1015 | a 831 20883 1016 | a 832 17628 1017 | f 774 1018 | a 833 7348 1019 | a 834 30443 1020 | a 835 32261 1021 | f 95 1022 | a 836 403 1023 | a 837 9098 1024 | f 553 1025 | a 838 12745 1026 | f 533 1027 | a 839 25284 1028 | f 722 1029 | f 594 1030 | a 840 30858 1031 | a 841 17652 1032 | a 842 3404 1033 | a 843 1908 1034 | a 844 3871 1035 | a 845 9797 1036 | a 846 27413 1037 | a 847 32333 1038 | a 848 11930 1039 | f 235 1040 | f 785 1041 | a 849 7854 1042 | a 850 13880 1043 | a 851 28398 1044 | a 852 23336 1045 | a 853 13464 1046 | a 854 13895 1047 | a 855 11016 1048 | a 856 17331 1049 | f 849 1050 | a 857 1836 1051 | a 858 9091 1052 | f 341 1053 | f 567 1054 | f 499 1055 | a 859 25615 1056 | a 860 17329 1057 | a 861 30307 1058 | a 862 13731 1059 | a 863 2189 1060 | a 864 4888 1061 | a 865 11407 1062 | f 598 1063 | a 866 1683 1064 | f 518 1065 | f 125 1066 | a 867 5291 1067 | f 254 1068 | a 868 20505 1069 | f 755 1070 | f 179 1071 | f 524 1072 | f 848 1073 | f 448 1074 | a 869 14428 1075 | a 870 30576 1076 | a 871 18596 1077 | a 872 32080 1078 | a 873 1212 1079 | a 874 20505 1080 | a 875 3183 1081 | a 876 11009 1082 | a 877 15151 1083 | a 878 2749 1084 | a 879 22940 1085 | a 880 23005 1086 | a 881 16630 1087 | f 830 1088 | f 633 1089 | a 882 18570 1090 | f 626 1091 | a 883 13573 1092 | a 884 30095 1093 | a 885 32465 1094 | a 886 24590 1095 | f 769 1096 | a 887 14658 1097 | a 888 1534 1098 | a 889 913 1099 | f 480 1100 | a 890 7506 1101 | f 622 1102 | f 376 1103 | f 706 1104 | a 891 18863 1105 | a 892 31221 1106 | f 190 1107 | a 893 21238 1108 | a 894 21053 1109 | a 895 3341 1110 | a 896 32645 1111 | a 897 22736 1112 | f 380 1113 | a 898 8633 1114 | f 431 1115 | a 899 20383 1116 | a 900 4396 1117 | f 636 1118 | a 901 6442 1119 | f 623 1120 | a 902 6212 1121 | f 339 1122 | a 903 3709 1123 | a 904 7654 1124 | a 905 26718 1125 | a 906 6893 1126 | a 907 18664 1127 | a 908 9101 1128 | f 632 1129 | f 466 1130 | a 909 9643 1131 | a 910 8836 1132 | f 737 1133 | a 911 32106 1134 | a 912 26273 1135 | f 656 1136 | a 913 27407 1137 | a 914 12912 1138 | f 497 1139 | a 915 23600 1140 | a 916 27105 1141 | f 525 1142 | a 917 4734 1143 | f 766 1144 | f 640 1145 | f 792 1146 | f 398 1147 | f 479 1148 | a 918 5491 1149 | a 919 28639 1150 | a 920 5648 1151 | a 921 12998 1152 | f 407 1153 | a 922 14734 1154 | a 923 4101 1155 | f 756 1156 | f 716 1157 | a 924 1468 1158 | f 5 1159 | a 925 3019 1160 | f 641 1161 | a 926 7443 1162 | f 42 1163 | f 410 1164 | a 927 1346 1165 | f 492 1166 | a 928 25756 1167 | f 335 1168 | f 886 1169 | f 522 1170 | a 929 16077 1171 | a 930 21730 1172 | a 931 30152 1173 | a 932 22519 1174 | a 933 27943 1175 | a 934 1094 1176 | a 935 30173 1177 | a 936 21894 1178 | a 937 7987 1179 | a 938 16069 1180 | a 939 30995 1181 | a 940 17630 1182 | a 941 24906 1183 | a 942 30333 1184 | f 699 1185 | a 943 11136 1186 | f 176 1187 | f 46 1188 | a 944 19546 1189 | f 426 1190 | a 945 10478 1191 | a 946 1969 1192 | f 840 1193 | f 298 1194 | a 947 13884 1195 | a 948 15213 1196 | a 949 7461 1197 | a 950 9755 1198 | f 393 1199 | a 951 20861 1200 | a 952 20460 1201 | a 953 24490 1202 | a 954 24963 1203 | a 955 21929 1204 | a 956 27510 1205 | f 872 1206 | a 957 32407 1207 | a 958 23275 1208 | a 959 20498 1209 | f 544 1210 | a 960 15716 1211 | f 114 1212 | a 961 12238 1213 | a 962 17883 1214 | a 963 5467 1215 | a 964 7414 1216 | a 965 18977 1217 | f 349 1218 | f 929 1219 | a 966 2872 1220 | f 21 1221 | a 967 29308 1222 | a 968 26965 1223 | f 627 1224 | a 969 18942 1225 | a 970 27535 1226 | f 327 1227 | f 796 1228 | a 971 11828 1229 | a 972 11081 1230 | a 973 25101 1231 | a 974 22965 1232 | a 975 30628 1233 | a 976 2812 1234 | f 713 1235 | a 977 24934 1236 | a 978 11744 1237 | a 979 18025 1238 | a 980 32396 1239 | f 116 1240 | a 981 21499 1241 | a 982 6118 1242 | f 274 1243 | f 856 1244 | f 902 1245 | f 921 1246 | a 983 20088 1247 | a 984 13222 1248 | f 951 1249 | f 724 1250 | a 985 31082 1251 | a 986 9249 1252 | a 987 7965 1253 | a 988 30721 1254 | f 28 1255 | a 989 32525 1256 | f 35 1257 | a 990 28464 1258 | f 866 1259 | a 991 13669 1260 | a 992 11996 1261 | a 993 13579 1262 | a 994 19137 1263 | a 995 19410 1264 | f 178 1265 | a 996 32557 1266 | a 997 22010 1267 | a 998 15950 1268 | a 999 26755 1269 | a 1000 8184 1270 | a 1001 10718 1271 | a 1002 5815 1272 | a 1003 19266 1273 | a 1004 3052 1274 | a 1005 28780 1275 | a 1006 17126 1276 | a 1007 5864 1277 | f 338 1278 | a 1008 20947 1279 | f 883 1280 | a 1009 28870 1281 | f 472 1282 | a 1010 23889 1283 | f 973 1284 | a 1011 20575 1285 | a 1012 17602 1286 | f 219 1287 | a 1013 30008 1288 | a 1014 7896 1289 | f 275 1290 | f 1010 1291 | f 962 1292 | f 958 1293 | f 576 1294 | a 1015 30825 1295 | a 1016 28322 1296 | a 1017 17146 1297 | a 1018 6023 1298 | a 1019 26276 1299 | f 563 1300 | a 1020 16903 1301 | a 1021 1719 1302 | a 1022 7178 1303 | a 1023 28899 1304 | f 365 1305 | a 1024 15299 1306 | f 957 1307 | a 1025 26315 1308 | f 117 1309 | a 1026 15542 1310 | a 1027 15088 1311 | f 471 1312 | f 57 1313 | a 1028 15557 1314 | f 251 1315 | a 1029 31493 1316 | a 1030 9075 1317 | a 1031 23742 1318 | a 1032 9444 1319 | f 812 1320 | a 1033 14891 1321 | f 1002 1322 | a 1034 10241 1323 | f 767 1324 | a 1035 12496 1325 | a 1036 10904 1326 | f 709 1327 | f 508 1328 | f 389 1329 | a 1037 27367 1330 | a 1038 18360 1331 | a 1039 31851 1332 | f 531 1333 | f 614 1334 | f 29 1335 | a 1040 23470 1336 | a 1041 9482 1337 | f 751 1338 | a 1042 19659 1339 | a 1043 8305 1340 | f 409 1341 | f 612 1342 | f 93 1343 | a 1044 6722 1344 | a 1045 27555 1345 | f 157 1346 | a 1046 6363 1347 | a 1047 2277 1348 | a 1048 11934 1349 | a 1049 12386 1350 | a 1050 28554 1351 | a 1051 28837 1352 | a 1052 14105 1353 | a 1053 2964 1354 | a 1054 24969 1355 | a 1055 29404 1356 | a 1056 29280 1357 | f 960 1358 | f 247 1359 | a 1057 7744 1360 | a 1058 11725 1361 | a 1059 12070 1362 | a 1060 6469 1363 | a 1061 20801 1364 | f 18 1365 | a 1062 3044 1366 | a 1063 15913 1367 | f 995 1368 | f 536 1369 | a 1064 2925 1370 | a 1065 13286 1371 | a 1066 28409 1372 | a 1067 13829 1373 | a 1068 7885 1374 | a 1069 14002 1375 | f 14 1376 | f 829 1377 | a 1070 12913 1378 | f 708 1379 | f 648 1380 | a 1071 31356 1381 | f 991 1382 | f 33 1383 | a 1072 23484 1384 | f 79 1385 | a 1073 32572 1386 | a 1074 6894 1387 | a 1075 30207 1388 | a 1076 27360 1389 | a 1077 13257 1390 | f 659 1391 | f 600 1392 | a 1078 32484 1393 | f 304 1394 | a 1079 6526 1395 | a 1080 25643 1396 | f 126 1397 | a 1081 28270 1398 | f 496 1399 | a 1082 2596 1400 | f 619 1401 | f 406 1402 | a 1083 6981 1403 | a 1084 31235 1404 | a 1085 27565 1405 | f 370 1406 | a 1086 3617 1407 | a 1087 27747 1408 | a 1088 2542 1409 | f 352 1410 | a 1089 15343 1411 | a 1090 7049 1412 | f 658 1413 | f 652 1414 | f 482 1415 | a 1091 9011 1416 | f 184 1417 | a 1092 3377 1418 | a 1093 10094 1419 | f 121 1420 | a 1094 24925 1421 | a 1095 6302 1422 | a 1096 23380 1423 | f 964 1424 | a 1097 20567 1425 | f 950 1426 | f 1043 1427 | a 1098 20131 1428 | f 938 1429 | a 1099 31266 1430 | f 818 1431 | a 1100 1801 1432 | a 1101 276 1433 | a 1102 29855 1434 | a 1103 25286 1435 | a 1104 81 1436 | a 1105 3981 1437 | a 1106 22725 1438 | a 1107 27441 1439 | a 1108 17238 1440 | a 1109 22442 1441 | f 679 1442 | a 1110 1200 1443 | a 1111 10114 1444 | a 1112 17944 1445 | a 1113 3796 1446 | a 1114 17095 1447 | a 1115 16411 1448 | f 1018 1449 | f 504 1450 | f 697 1451 | a 1116 31362 1452 | a 1117 20713 1453 | a 1118 11391 1454 | a 1119 1136 1455 | a 1120 3289 1456 | a 1121 18441 1457 | f 599 1458 | a 1122 10148 1459 | f 519 1460 | a 1123 6666 1461 | f 371 1462 | a 1124 28535 1463 | a 1125 2305 1464 | f 974 1465 | f 873 1466 | f 330 1467 | f 625 1468 | a 1126 12968 1469 | a 1127 19148 1470 | f 1045 1471 | a 1128 22872 1472 | a 1129 332 1473 | a 1130 17647 1474 | a 1131 24674 1475 | f 443 1476 | f 167 1477 | a 1132 608 1478 | a 1133 14734 1479 | f 629 1480 | f 387 1481 | a 1134 17192 1482 | a 1135 690 1483 | f 651 1484 | a 1136 18715 1485 | a 1137 7150 1486 | f 48 1487 | a 1138 28131 1488 | f 810 1489 | a 1139 3186 1490 | f 732 1491 | f 507 1492 | a 1140 29592 1493 | f 548 1494 | a 1141 29332 1495 | f 898 1496 | a 1142 13301 1497 | a 1143 14769 1498 | f 287 1499 | f 760 1500 | a 1144 361 1501 | f 473 1502 | a 1145 30397 1503 | f 791 1504 | a 1146 31180 1505 | a 1147 31724 1506 | a 1148 18342 1507 | a 1149 9804 1508 | a 1150 92 1509 | a 1151 21632 1510 | f 937 1511 | a 1152 28245 1512 | a 1153 10241 1513 | a 1154 28298 1514 | f 1148 1515 | a 1155 24013 1516 | f 1087 1517 | a 1156 12547 1518 | a 1157 8499 1519 | f 315 1520 | f 229 1521 | a 1158 10393 1522 | a 1159 2651 1523 | f 955 1524 | f 582 1525 | a 1160 8831 1526 | a 1161 28040 1527 | f 541 1528 | a 1162 27326 1529 | a 1163 9440 1530 | f 789 1531 | f 900 1532 | a 1164 10007 1533 | a 1165 11751 1534 | f 923 1535 | a 1166 10130 1536 | f 843 1537 | a 1167 28723 1538 | a 1168 18902 1539 | a 1169 5494 1540 | f 373 1541 | a 1170 31910 1542 | a 1171 15726 1543 | a 1172 2059 1544 | f 1012 1545 | a 1173 12443 1546 | a 1174 30495 1547 | a 1175 2420 1548 | a 1176 10072 1549 | a 1177 28908 1550 | a 1178 1376 1551 | f 1098 1552 | a 1179 28415 1553 | f 266 1554 | a 1180 5944 1555 | a 1181 1469 1556 | f 1131 1557 | a 1182 17279 1558 | f 1005 1559 | a 1183 1422 1560 | f 552 1561 | a 1184 11710 1562 | f 1058 1563 | f 372 1564 | a 1185 12809 1565 | f 168 1566 | a 1186 25435 1567 | f 58 1568 | f 1084 1569 | a 1187 24257 1570 | a 1188 21309 1571 | f 140 1572 | a 1189 3061 1573 | a 1190 26909 1574 | a 1191 30140 1575 | a 1192 31102 1576 | f 918 1577 | a 1193 21468 1578 | a 1194 6813 1579 | f 194 1580 | a 1195 8341 1581 | f 238 1582 | f 779 1583 | f 878 1584 | a 1196 451 1585 | f 942 1586 | a 1197 16943 1587 | a 1198 4297 1588 | a 1199 19353 1589 | a 1200 22438 1590 | a 1201 3439 1591 | a 1202 2312 1592 | f 1104 1593 | a 1203 24497 1594 | a 1204 15882 1595 | a 1205 39 1596 | a 1206 26917 1597 | a 1207 25955 1598 | a 1208 28948 1599 | f 729 1600 | a 1209 28294 1601 | f 1116 1602 | f 844 1603 | f 438 1604 | a 1210 21602 1605 | a 1211 2125 1606 | a 1212 29763 1607 | a 1213 6114 1608 | a 1214 3547 1609 | f 908 1610 | a 1215 8705 1611 | a 1216 18924 1612 | a 1217 28983 1613 | a 1218 195 1614 | f 574 1615 | a 1219 7465 1616 | f 225 1617 | f 196 1618 | a 1220 32045 1619 | f 743 1620 | f 1100 1621 | a 1221 27104 1622 | a 1222 4838 1623 | a 1223 30379 1624 | f 556 1625 | a 1224 15804 1626 | f 854 1627 | a 1225 11651 1628 | f 24 1629 | a 1226 5953 1630 | f 198 1631 | a 1227 16256 1632 | f 954 1633 | a 1228 28595 1634 | f 252 1635 | a 1229 10250 1636 | f 928 1637 | f 344 1638 | f 740 1639 | f 896 1640 | a 1230 2842 1641 | a 1231 18265 1642 | f 966 1643 | a 1232 13689 1644 | f 689 1645 | a 1233 5154 1646 | a 1234 9995 1647 | a 1235 29572 1648 | f 210 1649 | a 1236 5194 1650 | a 1237 4145 1651 | f 440 1652 | a 1238 22760 1653 | a 1239 1374 1654 | f 516 1655 | a 1240 32439 1656 | a 1241 11595 1657 | a 1242 3500 1658 | f 1003 1659 | a 1243 29434 1660 | f 44 1661 | a 1244 17709 1662 | a 1245 7047 1663 | a 1246 5372 1664 | f 514 1665 | f 1069 1666 | f 783 1667 | f 571 1668 | f 419 1669 | a 1247 3865 1670 | a 1248 3263 1671 | f 232 1672 | a 1249 5568 1673 | a 1250 11330 1674 | f 947 1675 | a 1251 2540 1676 | f 291 1677 | f 82 1678 | a 1252 32673 1679 | f 809 1680 | f 903 1681 | a 1253 16169 1682 | f 646 1683 | a 1254 152 1684 | a 1255 15710 1685 | f 1105 1686 | a 1256 27820 1687 | f 68 1688 | f 172 1689 | f 249 1690 | a 1257 6105 1691 | f 281 1692 | a 1258 31966 1693 | a 1259 23648 1694 | f 831 1695 | a 1260 16355 1696 | f 631 1697 | a 1261 2041 1698 | f 1259 1699 | a 1262 9146 1700 | f 888 1701 | f 131 1702 | a 1263 30045 1703 | a 1264 7195 1704 | a 1265 19141 1705 | a 1266 26850 1706 | f 89 1707 | a 1267 12389 1708 | f 987 1709 | a 1268 23286 1710 | f 534 1711 | a 1269 16842 1712 | a 1270 13764 1713 | a 1271 22958 1714 | a 1272 28437 1715 | f 10 1716 | f 133 1717 | a 1273 17264 1718 | a 1274 19625 1719 | a 1275 13379 1720 | f 1193 1721 | a 1276 24312 1722 | f 416 1723 | f 1254 1724 | f 778 1725 | f 611 1726 | f 1152 1727 | f 1092 1728 | a 1277 24998 1729 | a 1278 17244 1730 | a 1279 27576 1731 | a 1280 30566 1732 | a 1281 28575 1733 | f 296 1734 | a 1282 30116 1735 | a 1283 30471 1736 | f 1275 1737 | a 1284 11976 1738 | a 1285 30268 1739 | a 1286 13413 1740 | f 586 1741 | f 802 1742 | a 1287 7028 1743 | a 1288 3605 1744 | f 470 1745 | f 649 1746 | f 402 1747 | f 596 1748 | f 1154 1749 | f 1117 1750 | a 1289 12612 1751 | a 1290 30677 1752 | f 331 1753 | a 1291 19961 1754 | f 946 1755 | a 1292 14653 1756 | a 1293 7055 1757 | f 642 1758 | f 1065 1759 | a 1294 17239 1760 | f 1172 1761 | a 1295 21849 1762 | f 1245 1763 | a 1296 26196 1764 | a 1297 11321 1765 | a 1298 1471 1766 | f 1132 1767 | f 726 1768 | a 1299 16715 1769 | a 1300 28164 1770 | f 884 1771 | f 1140 1772 | a 1301 15235 1773 | a 1302 6905 1774 | f 704 1775 | f 457 1776 | f 920 1777 | f 1166 1778 | f 385 1779 | f 808 1780 | a 1303 23834 1781 | a 1304 32500 1782 | f 203 1783 | a 1305 26531 1784 | a 1306 4445 1785 | f 374 1786 | f 1051 1787 | a 1307 24045 1788 | a 1308 18761 1789 | a 1309 21689 1790 | a 1310 18853 1791 | f 983 1792 | a 1311 16559 1793 | f 1211 1794 | a 1312 17497 1795 | a 1313 16202 1796 | a 1314 14263 1797 | a 1315 29473 1798 | f 875 1799 | f 11 1800 | a 1316 13702 1801 | a 1317 27676 1802 | a 1318 3734 1803 | a 1319 17308 1804 | a 1320 7521 1805 | a 1321 1643 1806 | a 1322 4502 1807 | a 1323 22175 1808 | a 1324 8698 1809 | f 528 1810 | a 1325 21741 1811 | f 826 1812 | f 1277 1813 | f 554 1814 | f 707 1815 | a 1326 11256 1816 | a 1327 2127 1817 | f 589 1818 | f 765 1819 | f 1023 1820 | a 1328 295 1821 | a 1329 12727 1822 | f 520 1823 | a 1330 18843 1824 | f 15 1825 | a 1331 28460 1826 | a 1332 27963 1827 | f 643 1828 | f 1206 1829 | f 535 1830 | a 1333 25749 1831 | f 1113 1832 | f 677 1833 | a 1334 19526 1834 | f 936 1835 | f 762 1836 | a 1335 27696 1837 | a 1336 19512 1838 | a 1337 23972 1839 | a 1338 18973 1840 | f 805 1841 | f 817 1842 | f 1011 1843 | f 368 1844 | f 720 1845 | a 1339 5505 1846 | a 1340 12894 1847 | a 1341 5058 1848 | f 91 1849 | a 1342 22065 1850 | a 1343 30391 1851 | a 1344 21260 1852 | a 1345 3560 1853 | a 1346 27097 1854 | f 786 1855 | f 537 1856 | a 1347 2195 1857 | a 1348 31236 1858 | f 673 1859 | a 1349 30831 1860 | f 634 1861 | a 1350 19503 1862 | a 1351 5990 1863 | f 833 1864 | a 1352 32475 1865 | a 1353 24006 1866 | a 1354 28165 1867 | a 1355 8406 1868 | a 1356 12980 1869 | f 1149 1870 | a 1357 6653 1871 | a 1358 10534 1872 | f 319 1873 | a 1359 13275 1874 | f 1000 1875 | f 346 1876 | a 1360 19381 1877 | a 1361 29377 1878 | a 1362 8968 1879 | a 1363 14577 1880 | f 1239 1881 | a 1364 22358 1882 | a 1365 28495 1883 | f 270 1884 | a 1366 9505 1885 | f 1001 1886 | a 1367 9103 1887 | f 1327 1888 | f 1007 1889 | f 1291 1890 | a 1368 19699 1891 | f 691 1892 | a 1369 28478 1893 | a 1370 14608 1894 | a 1371 32593 1895 | a 1372 769 1896 | a 1373 3905 1897 | a 1374 30217 1898 | f 824 1899 | f 1062 1900 | a 1375 22030 1901 | f 1035 1902 | a 1376 7465 1903 | f 1229 1904 | a 1377 24546 1905 | f 262 1906 | f 40 1907 | f 1348 1908 | a 1378 24225 1909 | a 1379 5934 1910 | a 1380 22610 1911 | f 1168 1912 | f 1252 1913 | f 545 1914 | a 1381 10961 1915 | a 1382 11925 1916 | a 1383 22317 1917 | f 66 1918 | a 1384 2199 1919 | f 969 1920 | f 780 1921 | a 1385 7322 1922 | a 1386 30724 1923 | f 1347 1924 | f 1376 1925 | a 1387 15180 1926 | a 1388 13976 1927 | a 1389 8490 1928 | f 1381 1929 | f 569 1930 | a 1390 28456 1931 | f 1020 1932 | f 358 1933 | f 1279 1934 | a 1391 590 1935 | a 1392 5099 1936 | a 1393 4656 1937 | f 1190 1938 | a 1394 15167 1939 | a 1395 27458 1940 | a 1396 383 1941 | a 1397 24673 1942 | f 1135 1943 | f 1026 1944 | f 137 1945 | a 1398 3793 1946 | f 486 1947 | a 1399 20083 1948 | a 1400 20383 1949 | a 1401 18402 1950 | f 694 1951 | a 1402 19909 1952 | f 490 1953 | a 1403 21153 1954 | f 654 1955 | f 481 1956 | f 1004 1957 | a 1404 22308 1958 | f 267 1959 | a 1405 17358 1960 | f 540 1961 | f 1324 1962 | f 749 1963 | f 1301 1964 | a 1406 10415 1965 | a 1407 29774 1966 | f 565 1967 | a 1408 9137 1968 | f 1086 1969 | f 450 1970 | a 1409 1873 1971 | f 502 1972 | a 1410 2941 1973 | a 1411 31747 1974 | a 1412 12834 1975 | a 1413 14866 1976 | f 188 1977 | a 1414 21297 1978 | a 1415 15034 1979 | f 427 1980 | f 1379 1981 | a 1416 22189 1982 | a 1417 19253 1983 | a 1418 30214 1984 | a 1419 3397 1985 | a 1420 27743 1986 | f 403 1987 | a 1421 25902 1988 | f 838 1989 | f 1223 1990 | a 1422 3988 1991 | f 610 1992 | a 1423 75 1993 | f 285 1994 | f 224 1995 | a 1424 30559 1996 | a 1425 19155 1997 | f 723 1998 | a 1426 27533 1999 | a 1427 30943 2000 | a 1428 11060 2001 | f 1044 2002 | a 1429 31327 2003 | f 887 2004 | f 357 2005 | a 1430 18258 2006 | f 647 2007 | f 145 2008 | a 1431 31444 2009 | f 485 2010 | a 1432 16962 2011 | a 1433 5399 2012 | a 1434 19829 2013 | f 790 2014 | f 1356 2015 | a 1435 6503 2016 | a 1436 22758 2017 | f 1079 2018 | a 1437 30245 2019 | a 1438 3509 2020 | a 1439 31895 2021 | a 1440 32118 2022 | f 868 2023 | a 1441 6451 2024 | f 511 2025 | a 1442 30874 2026 | a 1443 12185 2027 | a 1444 21317 2028 | f 193 2029 | f 273 2030 | a 1445 19403 2031 | a 1446 27219 2032 | a 1447 10739 2033 | a 1448 5888 2034 | f 1178 2035 | f 1360 2036 | f 527 2037 | f 546 2038 | f 187 2039 | f 59 2040 | a 1449 24666 2041 | f 453 2042 | f 110 2043 | f 429 2044 | a 1450 14136 2045 | f 828 2046 | a 1451 864 2047 | f 170 2048 | f 446 2049 | a 1452 17801 2050 | a 1453 18124 2051 | f 637 2052 | a 1454 939 2053 | a 1455 15593 2054 | a 1456 4512 2055 | f 1073 2056 | f 977 2057 | f 363 2058 | f 775 2059 | a 1457 28473 2060 | f 1112 2061 | f 1009 2062 | f 1386 2063 | a 1458 13768 2064 | a 1459 15573 2065 | a 1460 27032 2066 | f 244 2067 | a 1461 32027 2068 | a 1462 14249 2069 | a 1463 11227 2070 | a 1464 4658 2071 | a 1465 1311 2072 | f 999 2073 | f 181 2074 | f 630 2075 | f 325 2076 | f 1364 2077 | f 1150 2078 | f 1210 2079 | f 515 2080 | f 1242 2081 | f 1274 2082 | a 1466 17730 2083 | a 1467 27417 2084 | f 782 2085 | f 512 2086 | f 41 2087 | a 1468 31556 2088 | a 1469 21240 2089 | f 1345 2090 | a 1470 26544 2091 | a 1471 30906 2092 | f 418 2093 | f 1215 2094 | f 718 2095 | f 128 2096 | a 1472 27692 2097 | a 1473 24651 2098 | f 493 2099 | a 1474 10323 2100 | a 1475 16242 2101 | f 1039 2102 | a 1476 11286 2103 | f 931 2104 | a 1477 4775 2105 | a 1478 26981 2106 | a 1479 17175 2107 | f 20 2108 | f 1202 2109 | a 1480 29442 2110 | a 1481 8349 2111 | f 967 2112 | f 858 2113 | a 1482 18039 2114 | a 1483 14475 2115 | a 1484 26474 2116 | a 1485 18979 2117 | f 768 2118 | f 668 2119 | f 835 2120 | a 1486 30068 2121 | a 1487 30987 2122 | a 1488 14684 2123 | a 1489 11069 2124 | a 1490 13792 2125 | a 1491 8949 2126 | f 703 2127 | a 1492 10328 2128 | a 1493 28042 2129 | a 1494 20177 2130 | a 1495 14986 2131 | f 1126 2132 | a 1496 29353 2133 | f 1375 2134 | a 1497 5139 2135 | f 1470 2136 | a 1498 9635 2137 | a 1499 28141 2138 | a 1500 26380 2139 | a 1501 3412 2140 | a 1502 26280 2141 | a 1503 21304 2142 | a 1504 28063 2143 | f 776 2144 | a 1505 3836 2145 | a 1506 4778 2146 | a 1507 6582 2147 | a 1508 8612 2148 | a 1509 31760 2149 | a 1510 23757 2150 | a 1511 5286 2151 | f 986 2152 | a 1512 7342 2153 | f 417 2154 | a 1513 9029 2155 | f 26 2156 | a 1514 19761 2157 | f 555 2158 | a 1515 1048 2159 | f 1027 2160 | a 1516 28009 2161 | f 580 2162 | f 1297 2163 | a 1517 17062 2164 | f 328 2165 | a 1518 32036 2166 | a 1519 9925 2167 | a 1520 28131 2168 | a 1521 13060 2169 | a 1522 18874 2170 | a 1523 5691 2171 | a 1524 8334 2172 | f 1250 2173 | a 1525 6284 2174 | f 616 2175 | f 1400 2176 | f 1303 2177 | a 1526 20678 2178 | f 725 2179 | a 1527 4919 2180 | a 1528 11423 2181 | a 1529 30314 2182 | f 784 2183 | f 1063 2184 | a 1530 293 2185 | a 1531 5036 2186 | f 1361 2187 | a 1532 958 2188 | a 1533 26574 2189 | f 1089 2190 | a 1534 26341 2191 | f 498 2192 | a 1535 29021 2193 | a 1536 30411 2194 | a 1537 31120 2195 | f 1408 2196 | a 1538 2836 2197 | f 1094 2198 | f 1306 2199 | a 1539 6255 2200 | a 1540 30112 2201 | a 1541 26594 2202 | f 861 2203 | a 1542 11541 2204 | f 122 2205 | f 1076 2206 | a 1543 4686 2207 | a 1544 2855 2208 | f 1378 2209 | a 1545 31303 2210 | a 1546 5735 2211 | a 1547 30864 2212 | a 1548 15598 2213 | f 1171 2214 | f 1195 2215 | a 1549 5003 2216 | a 1550 8022 2217 | f 763 2218 | a 1551 10961 2219 | f 1265 2220 | a 1552 18064 2221 | f 1302 2222 | f 882 2223 | f 1182 2224 | f 827 2225 | a 1553 26897 2226 | a 1554 16653 2227 | f 1530 2228 | f 1369 2229 | f 294 2230 | f 1444 2231 | f 871 2232 | a 1555 26398 2233 | f 943 2234 | a 1556 413 2235 | a 1557 4563 2236 | a 1558 31318 2237 | a 1559 11837 2238 | a 1560 2110 2239 | a 1561 31612 2240 | f 1424 2241 | f 268 2242 | f 1414 2243 | f 949 2244 | f 1495 2245 | f 889 2246 | f 17 2247 | f 1491 2248 | a 1562 16874 2249 | f 1130 2250 | f 280 2251 | f 721 2252 | f 1187 2253 | a 1563 3068 2254 | f 69 2255 | a 1564 25419 2256 | f 1115 2257 | a 1565 10447 2258 | f 489 2259 | a 1566 32090 2260 | f 430 2261 | a 1567 23062 2262 | f 1434 2263 | a 1568 8800 2264 | f 989 2265 | a 1569 2158 2266 | a 1570 29317 2267 | a 1571 6145 2268 | f 1419 2269 | a 1572 28752 2270 | f 1468 2271 | a 1573 8091 2272 | a 1574 10831 2273 | f 19 2274 | a 1575 31608 2275 | f 1141 2276 | f 869 2277 | f 1446 2278 | f 510 2279 | f 1067 2280 | a 1576 6627 2281 | a 1577 16567 2282 | f 998 2283 | a 1578 29705 2284 | f 669 2285 | f 1520 2286 | f 1129 2287 | f 353 2288 | f 804 2289 | a 1579 22225 2290 | f 1111 2291 | f 867 2292 | f 1060 2293 | f 1499 2294 | f 1552 2295 | a 1580 21571 2296 | a 1581 4960 2297 | f 870 2298 | a 1582 419 2299 | f 1536 2300 | f 731 2301 | a 1583 6867 2302 | a 1584 31857 2303 | f 682 2304 | a 1585 17072 2305 | f 853 2306 | f 581 2307 | a 1586 498 2308 | f 539 2309 | f 1456 2310 | a 1587 32271 2311 | f 455 2312 | a 1588 21636 2313 | a 1589 31817 2314 | f 1569 2315 | a 1590 11340 2316 | a 1591 23746 2317 | a 1592 30662 2318 | a 1593 28214 2319 | f 1435 2320 | f 1331 2321 | f 1267 2322 | a 1594 26815 2323 | a 1595 23313 2324 | f 579 2325 | a 1596 5894 2326 | a 1597 26138 2327 | a 1598 13607 2328 | f 396 2329 | a 1599 14694 2330 | f 1462 2331 | a 1600 28297 2332 | a 1601 10157 2333 | f 191 2334 | f 688 2335 | a 1602 20839 2336 | f 1537 2337 | f 877 2338 | f 956 2339 | f 1370 2340 | a 1603 24281 2341 | f 1102 2342 | f 1426 2343 | a 1604 18249 2344 | f 391 2345 | f 1209 2346 | a 1605 31671 2347 | f 271 2348 | f 935 2349 | a 1606 23122 2350 | a 1607 24876 2351 | f 859 2352 | a 1608 15471 2353 | f 880 2354 | a 1609 20060 2355 | a 1610 14334 2356 | f 134 2357 | a 1611 4274 2358 | a 1612 25020 2359 | a 1613 14753 2360 | a 1614 11142 2361 | a 1615 24110 2362 | a 1616 31826 2363 | f 1054 2364 | a 1617 11641 2365 | a 1618 23613 2366 | f 1167 2367 | a 1619 20695 2368 | f 1398 2369 | f 526 2370 | f 7 2371 | f 952 2372 | a 1620 10691 2373 | a 1621 2185 2374 | a 1622 11674 2375 | a 1623 8585 2376 | f 1506 2377 | a 1624 30400 2378 | f 401 2379 | a 1625 5721 2380 | a 1626 31898 2381 | a 1627 3526 2382 | f 90 2383 | a 1628 31860 2384 | a 1629 12738 2385 | f 383 2386 | a 1630 18221 2387 | f 360 2388 | f 1118 2389 | a 1631 27389 2390 | a 1632 22896 2391 | a 1633 6292 2392 | a 1634 18903 2393 | f 1602 2394 | a 1635 8377 2395 | a 1636 5196 2396 | f 939 2397 | a 1637 9257 2398 | a 1638 486 2399 | a 1639 20667 2400 | a 1640 29318 2401 | f 1595 2402 | f 1620 2403 | f 213 2404 | f 1417 2405 | a 1641 14820 2406 | a 1642 24942 2407 | f 381 2408 | a 1643 21570 2409 | f 925 2410 | f 141 2411 | f 1053 2412 | f 1489 2413 | f 750 2414 | f 1467 2415 | a 1644 29573 2416 | f 1371 2417 | a 1645 3316 2418 | f 975 2419 | f 1341 2420 | f 228 2421 | a 1646 12912 2422 | a 1647 28632 2423 | a 1648 14957 2424 | a 1649 3757 2425 | f 657 2426 | a 1650 16559 2427 | f 1648 2428 | a 1651 25649 2429 | a 1652 5943 2430 | f 1200 2431 | a 1653 28233 2432 | f 1284 2433 | f 1430 2434 | f 1235 2435 | a 1654 1466 2436 | f 1413 2437 | f 1143 2438 | a 1655 3575 2439 | a 1656 1187 2440 | f 910 2441 | a 1657 597 2442 | a 1658 7101 2443 | f 1385 2444 | a 1659 279 2445 | f 803 2446 | f 421 2447 | f 1008 2448 | f 1234 2449 | f 1107 2450 | a 1660 13336 2451 | f 1565 2452 | a 1661 25322 2453 | a 1662 27668 2454 | f 105 2455 | a 1663 3464 2456 | a 1664 31615 2457 | f 930 2458 | f 1222 2459 | f 1157 2460 | f 1505 2461 | f 1519 2462 | f 1651 2463 | a 1665 13803 2464 | f 61 2465 | a 1666 11842 2466 | f 1546 2467 | a 1667 4044 2468 | a 1668 23061 2469 | f 6 2470 | a 1669 12328 2471 | a 1670 24711 2472 | f 1184 2473 | f 1528 2474 | f 218 2475 | f 547 2476 | f 1463 2477 | a 1671 19611 2478 | f 1014 2479 | a 1672 27148 2480 | a 1673 16885 2481 | f 467 2482 | f 469 2483 | a 1674 8413 2484 | a 1675 23953 2485 | f 1365 2486 | f 350 2487 | a 1676 20202 2488 | a 1677 21326 2489 | a 1678 19817 2490 | a 1679 2392 2491 | f 1541 2492 | a 1680 25083 2493 | f 1576 2494 | f 736 2495 | a 1681 3609 2496 | a 1682 28041 2497 | f 231 2498 | a 1683 31026 2499 | a 1684 31842 2500 | f 444 2501 | f 1575 2502 | a 1685 29507 2503 | a 1686 1834 2504 | f 1220 2505 | a 1687 262 2506 | a 1688 30105 2507 | f 1682 2508 | a 1689 8935 2509 | a 1690 541 2510 | f 1581 2511 | f 1393 2512 | f 1207 2513 | a 1691 10673 2514 | f 1217 2515 | f 906 2516 | a 1692 1490 2517 | f 799 2518 | f 1059 2519 | f 1185 2520 | a 1693 28210 2521 | f 1481 2522 | f 115 2523 | f 1458 2524 | f 1340 2525 | f 129 2526 | a 1694 14138 2527 | a 1695 338 2528 | a 1696 9246 2529 | f 1307 2530 | f 1562 2531 | a 1697 25980 2532 | f 662 2533 | a 1698 4382 2534 | f 1325 2535 | a 1699 32307 2536 | f 276 2537 | a 1700 5540 2538 | f 787 2539 | f 1548 2540 | f 1082 2541 | a 1701 29094 2542 | f 1158 2543 | f 260 2544 | a 1702 19151 2545 | a 1703 32689 2546 | f 1352 2547 | a 1704 13212 2548 | f 578 2549 | f 1263 2550 | a 1705 27565 2551 | a 1706 23875 2552 | f 912 2553 | f 474 2554 | f 1028 2555 | a 1707 646 2556 | f 1336 2557 | a 1708 16123 2558 | f 99 2559 | a 1709 10925 2560 | a 1710 3039 2561 | a 1711 8439 2562 | a 1712 14534 2563 | f 212 2564 | a 1713 31080 2565 | f 303 2566 | f 1588 2567 | f 645 2568 | f 23 2569 | f 94 2570 | a 1714 6698 2571 | f 1249 2572 | a 1715 13609 2573 | f 820 2574 | f 1611 2575 | f 88 2576 | f 1316 2577 | f 441 2578 | f 857 2579 | f 1661 2580 | a 1716 27820 2581 | a 1717 8532 2582 | a 1718 13871 2583 | f 1635 2584 | a 1719 25157 2585 | a 1720 17468 2586 | a 1721 14413 2587 | f 764 2588 | a 1722 3063 2589 | f 1498 2590 | f 1321 2591 | a 1723 18959 2592 | a 1724 9855 2593 | f 1270 2594 | a 1725 17201 2595 | f 1522 2596 | a 1726 19297 2597 | f 617 2598 | a 1727 19101 2599 | f 1634 2600 | f 961 2601 | a 1728 10414 2602 | f 1465 2603 | a 1729 23680 2604 | f 1568 2605 | f 1366 2606 | f 1720 2607 | a 1730 18641 2608 | f 1572 2609 | f 741 2610 | f 1208 2611 | f 1726 2612 | a 1731 15955 2613 | a 1732 20006 2614 | f 1712 2615 | a 1733 5025 2616 | f 1521 2617 | f 1120 2618 | a 1734 15876 2619 | a 1735 450 2620 | f 445 2621 | f 735 2622 | a 1736 32590 2623 | f 55 2624 | a 1737 6983 2625 | f 754 2626 | a 1738 1097 2627 | a 1739 15945 2628 | f 1404 2629 | f 1380 2630 | a 1740 17908 2631 | a 1741 4136 2632 | a 1742 24385 2633 | a 1743 32442 2634 | f 1599 2635 | f 1312 2636 | a 1744 2449 2637 | a 1745 31083 2638 | f 265 2639 | f 821 2640 | f 461 2641 | f 1038 2642 | f 933 2643 | a 1746 13283 2644 | f 1501 2645 | a 1747 30269 2646 | a 1748 6848 2647 | a 1749 27155 2648 | a 1750 22659 2649 | f 1025 2650 | a 1751 24316 2651 | f 1532 2652 | f 1305 2653 | f 1137 2654 | a 1752 8800 2655 | f 1313 2656 | f 1503 2657 | f 850 2658 | f 1041 2659 | f 1407 2660 | a 1753 25723 2661 | f 1442 2662 | f 1295 2663 | a 1754 10508 2664 | a 1755 18655 2665 | f 851 2666 | f 1258 2667 | f 841 2668 | f 1494 2669 | f 996 2670 | f 1151 2671 | f 1551 2672 | f 1592 2673 | a 1756 10156 2674 | f 675 2675 | f 710 2676 | f 753 2677 | f 37 2678 | a 1757 29805 2679 | a 1758 4989 2680 | a 1759 20571 2681 | a 1760 20717 2682 | a 1761 23631 2683 | a 1762 3758 2684 | f 521 2685 | f 1177 2686 | a 1763 7956 2687 | f 944 2688 | f 865 2689 | f 1064 2690 | f 852 2691 | f 523 2692 | f 1083 2693 | a 1764 28656 2694 | f 1248 2695 | f 1538 2696 | a 1765 19634 2697 | a 1766 8407 2698 | f 243 2699 | f 1766 2700 | f 1474 2701 | a 1767 28478 2702 | a 1768 26618 2703 | f 456 2704 | f 302 2705 | f 1226 2706 | f 825 2707 | f 1736 2708 | f 1181 2709 | f 1545 2710 | f 671 2711 | a 1769 9504 2712 | a 1770 11656 2713 | a 1771 11759 2714 | f 1357 2715 | f 1090 2716 | a 1772 13641 2717 | f 1542 2718 | f 1377 2719 | f 815 2720 | f 487 2721 | a 1773 3274 2722 | f 1733 2723 | f 604 2724 | f 1203 2725 | f 452 2726 | a 1774 11434 2727 | f 1247 2728 | f 1230 2729 | f 1750 2730 | a 1775 16090 2731 | f 1646 2732 | f 1355 2733 | a 1776 1590 2734 | f 1354 2735 | f 1280 2736 | a 1777 24718 2737 | f 16 2738 | f 602 2739 | f 1587 2740 | f 149 2741 | a 1778 13592 2742 | f 1699 2743 | a 1779 8438 2744 | a 1780 19105 2745 | f 130 2746 | a 1781 3484 2747 | f 1410 2748 | a 1782 32755 2749 | a 1783 27905 2750 | a 1784 29207 2751 | f 1589 2752 | f 1237 2753 | f 1629 2754 | a 1785 10495 2755 | f 693 2756 | a 1786 13793 2757 | f 1623 2758 | a 1787 6596 2759 | a 1788 7533 2760 | a 1789 18783 2761 | a 1790 27167 2762 | f 1288 2763 | f 1308 2764 | f 132 2765 | f 549 2766 | f 1748 2767 | f 1286 2768 | f 1346 2769 | a 1791 28251 2770 | f 1669 2771 | a 1792 9646 2772 | f 899 2773 | a 1793 30925 2774 | f 1662 2775 | f 1652 2776 | f 1473 2777 | f 1627 2778 | a 1794 3439 2779 | a 1795 5535 2780 | f 0 2781 | f 464 2782 | a 1796 17792 2783 | f 1294 2784 | a 1797 11846 2785 | a 1798 1245 2786 | f 1144 2787 | f 1310 2788 | f 1164 2789 | f 1751 2790 | f 1194 2791 | a 1799 11643 2792 | a 1800 21351 2793 | a 1801 12902 2794 | f 1314 2795 | f 1334 2796 | f 530 2797 | f 566 2798 | a 1802 23402 2799 | f 62 2800 | a 1803 2224 2801 | f 1624 2802 | a 1804 16176 2803 | f 1278 2804 | f 684 2805 | a 1805 2069 2806 | f 1580 2807 | f 715 2808 | a 1806 18315 2809 | f 1429 2810 | f 696 2811 | f 278 2812 | a 1807 17766 2813 | f 316 2814 | a 1808 26787 2815 | f 1645 2816 | f 1257 2817 | a 1809 31907 2818 | a 1810 26205 2819 | a 1811 13124 2820 | f 1732 2821 | f 1556 2822 | f 1358 2823 | a 1812 2623 2824 | a 1813 26192 2825 | f 1466 2826 | f 1423 2827 | f 1228 2828 | a 1814 8262 2829 | a 1815 31830 2830 | a 1816 3920 2831 | a 1817 22055 2832 | a 1818 5659 2833 | a 1819 11453 2834 | f 1460 2835 | a 1820 8071 2836 | f 1367 2837 | f 166 2838 | f 1042 2839 | f 1579 2840 | f 1390 2841 | a 1821 58 2842 | a 1822 6937 2843 | f 1654 2844 | a 1823 17717 2845 | f 1626 2846 | f 719 2847 | a 1824 30984 2848 | a 1825 10376 2849 | f 813 2850 | f 1418 2851 | f 1256 2852 | f 894 2853 | a 1826 23252 2854 | f 351 2855 | f 1272 2856 | f 1452 2857 | f 264 2858 | f 75 2859 | f 609 2860 | f 941 2861 | a 1827 16009 2862 | f 1372 2863 | a 1828 22223 2864 | f 934 2865 | f 206 2866 | f 1037 2867 | f 359 2868 | a 1829 24498 2869 | f 1401 2870 | a 1830 27652 2871 | f 1451 2872 | f 893 2873 | a 1831 10807 2874 | a 1832 4632 2875 | a 1833 18287 2876 | f 161 2877 | f 1213 2878 | f 1483 2879 | f 1787 2880 | f 1586 2881 | f 1734 2882 | a 1834 13032 2883 | f 1244 2884 | f 1668 2885 | a 1835 20809 2886 | f 382 2887 | f 144 2888 | f 159 2889 | f 1269 2890 | f 1583 2891 | f 1574 2892 | a 1836 20356 2893 | a 1837 31347 2894 | f 1812 2895 | f 250 2896 | f 823 2897 | f 27 2898 | f 901 2899 | a 1838 5807 2900 | a 1839 14376 2901 | a 1840 30487 2902 | a 1841 32013 2903 | a 1842 27500 2904 | f 1335 2905 | a 1843 342 2906 | f 253 2907 | a 1844 25437 2908 | f 1640 2909 | f 561 2910 | f 1685 2911 | a 1845 2995 2912 | f 309 2913 | f 1218 2914 | a 1846 32173 2915 | f 1428 2916 | f 1827 2917 | a 1847 29358 2918 | a 1848 25051 2919 | f 772 2920 | a 1849 5064 2921 | a 1850 8044 2922 | f 1728 2923 | a 1851 354 2924 | f 1816 2925 | f 1227 2926 | a 1852 5123 2927 | a 1853 14981 2928 | f 916 2929 | f 354 2930 | f 795 2931 | f 863 2932 | f 1186 2933 | a 1854 18071 2934 | a 1855 3339 2935 | f 907 2936 | f 118 2937 | f 1088 2938 | f 672 2939 | f 1758 2940 | f 584 2941 | a 1856 25358 2942 | a 1857 8556 2943 | a 1858 19349 2944 | a 1859 14813 2945 | a 1860 287 2946 | a 1861 14234 2947 | f 1695 2948 | f 819 2949 | a 1862 25621 2950 | a 1863 4920 2951 | a 1864 32521 2952 | a 1865 5885 2953 | f 1507 2954 | a 1866 25729 2955 | f 638 2956 | a 1867 20110 2957 | a 1868 4464 2958 | a 1869 31537 2959 | a 1870 1718 2960 | f 1411 2961 | f 1066 2962 | f 874 2963 | a 1871 2183 2964 | a 1872 30782 2965 | a 1873 29219 2966 | f 1271 2967 | a 1874 2526 2968 | a 1875 23452 2969 | f 70 2970 | a 1876 32214 2971 | f 414 2972 | a 1877 1932 2973 | a 1878 20042 2974 | f 1445 2975 | a 1879 24497 2976 | f 102 2977 | f 1613 2978 | f 348 2979 | f 1746 2980 | f 1464 2981 | f 570 2982 | f 1477 2983 | a 1880 6997 2984 | a 1881 28087 2985 | a 1882 24851 2986 | f 1080 2987 | f 965 2988 | f 816 2989 | a 1883 12121 2990 | f 845 2991 | a 1884 10300 2992 | f 1780 2993 | f 1665 2994 | f 1653 2995 | f 1710 2996 | f 1609 2997 | f 65 2998 | f 1796 2999 | f 1866 3000 | f 650 3001 | f 1703 3002 | a 1885 10155 3003 | f 959 3004 | f 932 3005 | f 1461 3006 | f 836 3007 | f 1147 3008 | a 1886 15461 3009 | f 1825 3010 | a 1887 2890 3011 | f 1713 3012 | f 1667 3013 | f 1547 3014 | f 1605 3015 | a 1888 18712 3016 | a 1889 2042 3017 | a 1890 17704 3018 | f 1707 3019 | f 1674 3020 | a 1891 18999 3021 | a 1892 16276 3022 | f 1876 3023 | a 1893 10558 3024 | f 173 3025 | a 1894 23919 3026 | f 1604 3027 | a 1895 16030 3028 | a 1896 16443 3029 | a 1897 16881 3030 | f 1318 3031 | f 1139 3032 | f 1006 3033 | f 434 3034 | f 1744 3035 | f 1719 3036 | f 1897 3037 | f 1727 3038 | f 1416 3039 | a 1898 3373 3040 | f 1621 3041 | a 1899 20908 3042 | f 1478 3043 | f 1704 3044 | f 1425 3045 | f 54 3046 | a 1900 15650 3047 | f 1328 3048 | a 1901 5092 3049 | a 1902 23092 3050 | a 1903 13665 3051 | f 1389 3052 | f 233 3053 | f 1788 3054 | f 811 3055 | f 1849 3056 | f 311 3057 | f 1204 3058 | a 1904 1543 3059 | f 1283 3060 | a 1905 25619 3061 | f 924 3062 | f 1399 3063 | a 1906 4350 3064 | a 1907 990 3065 | f 1680 3066 | f 1077 3067 | a 1908 27551 3068 | f 1081 3069 | a 1909 24393 3070 | f 1770 3071 | a 1910 25488 3072 | f 1438 3073 | f 842 3074 | f 1191 3075 | a 1911 1781 3076 | f 1675 3077 | f 885 3078 | a 1912 19712 3079 | a 1913 17572 3080 | f 1123 3081 | a 1914 13902 3082 | f 1479 3083 | f 585 3084 | a 1915 30012 3085 | a 1916 27728 3086 | f 1794 3087 | a 1917 29363 3088 | a 1918 135 3089 | a 1919 13672 3090 | f 192 3091 | f 1797 3092 | f 661 3093 | f 773 3094 | f 295 3095 | a 1920 31406 3096 | f 895 3097 | a 1921 17840 3098 | a 1922 32672 3099 | f 794 3100 | a 1923 14914 3101 | a 1924 28398 3102 | f 293 3103 | a 1925 23824 3104 | a 1926 30945 3105 | f 911 3106 | a 1927 12073 3107 | f 1615 3108 | f 588 3109 | f 971 3110 | f 1630 3111 | f 1516 3112 | a 1928 7937 3113 | a 1929 1550 3114 | f 1109 3115 | f 272 3116 | f 1127 3117 | a 1930 213 3118 | a 1931 23588 3119 | a 1932 6642 3120 | f 978 3121 | a 1933 23306 3122 | f 1916 3123 | a 1934 4486 3124 | f 288 3125 | a 1935 8186 3126 | a 1936 16157 3127 | f 1842 3128 | a 1937 8836 3129 | a 1938 9177 3130 | f 551 3131 | f 1138 3132 | f 1197 3133 | f 1175 3134 | f 1641 3135 | a 1939 10940 3136 | a 1940 461 3137 | f 1072 3138 | f 1543 3139 | f 1690 3140 | f 1924 3141 | f 1810 3142 | a 1941 1897 3143 | a 1942 12722 3144 | a 1943 20173 3145 | f 1774 3146 | f 1814 3147 | a 1944 19469 3148 | a 1945 26625 3149 | a 1946 17418 3150 | a 1947 14430 3151 | f 1273 3152 | a 1948 23221 3153 | f 728 3154 | f 1122 3155 | f 1443 3156 | f 1323 3157 | a 1949 17554 3158 | f 1717 3159 | f 1559 3160 | f 1875 3161 | a 1950 28102 3162 | a 1951 21859 3163 | a 1952 2626 3164 | a 1953 28007 3165 | f 1848 3166 | a 1954 4006 3167 | f 1455 3168 | a 1955 31025 3169 | f 897 3170 | a 1956 19064 3171 | f 860 3172 | f 1714 3173 | a 1957 2183 3174 | f 1253 3175 | a 1958 10330 3176 | a 1959 27002 3177 | a 1960 3734 3178 | f 112 3179 | f 1260 3180 | f 1740 3181 | f 1956 3182 | a 1961 10544 3183 | f 326 3184 | f 1633 3185 | a 1962 17822 3186 | f 538 3187 | f 1631 3188 | f 1264 3189 | a 1963 10377 3190 | f 45 3191 | a 1964 1082 3192 | a 1965 22309 3193 | f 1525 3194 | f 1577 3195 | f 1201 3196 | f 1614 3197 | f 49 3198 | f 1119 3199 | f 1597 3200 | f 236 3201 | a 1966 18564 3202 | f 1095 3203 | f 1500 3204 | a 1967 17240 3205 | f 733 3206 | f 905 3207 | f 1926 3208 | f 1585 3209 | f 1449 3210 | f 1019 3211 | f 1403 3212 | a 1968 31145 3213 | f 1029 3214 | a 1969 27741 3215 | f 1180 3216 | f 1819 3217 | f 1396 3218 | f 1431 3219 | f 1742 3220 | a 1970 28181 3221 | a 1971 31607 3222 | a 1972 29638 3223 | f 1831 3224 | f 1863 3225 | f 745 3226 | f 1809 3227 | a 1973 8135 3228 | f 1836 3229 | f 680 3230 | f 246 3231 | a 1974 19013 3232 | f 1050 3233 | f 1071 3234 | f 1655 3235 | a 1975 16340 3236 | a 1976 1992 3237 | f 1243 3238 | f 1776 3239 | a 1977 3663 3240 | f 1743 3241 | a 1978 30770 3242 | f 771 3243 | f 36 3244 | a 1979 25213 3245 | f 1724 3246 | a 1980 21218 3247 | f 1792 3248 | f 1943 3249 | f 1898 3250 | a 1981 26105 3251 | f 216 3252 | a 1982 14305 3253 | f 1016 3254 | a 1983 23844 3255 | a 1984 21344 3256 | a 1985 18311 3257 | f 1612 3258 | f 465 3259 | a 1986 22101 3260 | f 1030 3261 | f 163 3262 | a 1987 7640 3263 | f 318 3264 | f 1730 3265 | a 1988 20495 3266 | f 1980 3267 | f 1625 3268 | f 1600 3269 | f 1879 3270 | f 1057 3271 | f 1198 3272 | f 1982 3273 | a 1989 32432 3274 | f 1663 3275 | f 613 3276 | f 204 3277 | f 1962 3278 | f 39 3279 | f 963 3280 | f 744 3281 | f 1359 3282 | f 43 3283 | f 1785 3284 | f 1920 3285 | a 1990 1874 3286 | a 1991 24229 3287 | a 1992 10209 3288 | f 742 3289 | f 1607 3290 | a 1993 19697 3291 | a 1994 1839 3292 | f 1394 3293 | a 1995 11292 3294 | a 1996 9239 3295 | f 1459 3296 | f 169 3297 | f 909 3298 | f 572 3299 | f 1276 3300 | f 573 3301 | f 1941 3302 | f 1415 3303 | a 1997 20403 3304 | a 1998 28532 3305 | a 1999 7617 3306 | f 1909 3307 | f 1106 3308 | f 439 3309 | f 559 3310 | f 1124 3311 | a 2000 15376 3312 | a 2001 23945 3313 | a 2002 6456 3314 | a 2003 12247 3315 | a 2004 32081 3316 | f 1490 3317 | f 1874 3318 | a 2005 25469 3319 | f 1165 3320 | f 1859 3321 | f 1933 3322 | a 2006 28587 3323 | f 1099 3324 | a 2007 1305 3325 | a 2008 29133 3326 | f 979 3327 | f 1236 3328 | f 793 3329 | f 1735 3330 | f 1601 3331 | f 459 3332 | a 2009 26590 3333 | a 2010 26519 3334 | f 1110 3335 | f 1828 3336 | a 2011 17583 3337 | f 1861 3338 | a 2012 19927 3339 | a 2013 8057 3340 | f 301 3341 | f 1991 3342 | f 1447 3343 | f 1681 3344 | f 1930 3345 | f 700 3346 | f 9 3347 | f 1070 3348 | f 1337 3349 | a 2014 8660 3350 | a 2015 8504 3351 | f 1691 3352 | f 60 3353 | f 1033 3354 | f 1578 3355 | a 2016 26368 3356 | f 1940 3357 | a 2017 30762 3358 | a 2018 16145 3359 | f 386 3360 | a 2019 14096 3361 | f 153 3362 | f 1718 3363 | f 1903 3364 | f 1657 3365 | f 1793 3366 | f 314 3367 | f 1905 3368 | f 1999 3369 | a 2020 30426 3370 | f 702 3371 | a 2021 18020 3372 | f 1509 3373 | f 1582 3374 | f 1055 3375 | a 2022 5557 3376 | a 2023 7868 3377 | a 2024 4950 3378 | f 1832 3379 | a 2025 7397 3380 | f 1677 3381 | f 1074 3382 | a 2026 19161 3383 | f 1779 3384 | f 124 3385 | f 1995 3386 | f 1808 3387 | a 2027 14189 3388 | a 2028 27800 3389 | a 2029 14925 3390 | f 1664 3391 | f 1935 3392 | a 2030 21807 3393 | f 1760 3394 | f 1833 3395 | f 1550 3396 | f 984 3397 | f 366 3398 | f 1961 3399 | a 2031 10409 3400 | a 2032 6103 3401 | a 2033 28263 3402 | f 739 3403 | a 2034 22656 3404 | f 862 3405 | f 1708 3406 | a 2035 5416 3407 | a 2036 20965 3408 | f 202 3409 | a 2037 18476 3410 | a 2038 6722 3411 | f 948 3412 | a 2039 17331 3413 | f 801 3414 | f 1895 3415 | f 1511 3416 | f 1309 3417 | a 2040 12298 3418 | f 1893 3419 | f 681 3420 | f 1570 3421 | a 2041 474 3422 | f 1504 3423 | f 2028 3424 | f 982 3425 | f 1174 3426 | a 2042 2147 3427 | f 1929 3428 | a 2043 32226 3429 | f 1697 3430 | f 1492 3431 | f 1299 3432 | f 1022 3433 | f 1388 3434 | f 1342 3435 | f 1508 3436 | a 2044 8531 3437 | a 2045 10807 3438 | f 624 3439 | a 2046 7963 3440 | f 1221 3441 | f 375 3442 | f 1344 3443 | a 2047 2132 3444 | a 2048 8801 3445 | a 2049 24108 3446 | a 2050 16228 3447 | f 1133 3448 | a 2051 6460 3449 | a 2052 9361 3450 | a 2053 21786 3451 | a 2054 14329 3452 | f 1650 3453 | f 914 3454 | f 635 3455 | f 1671 3456 | f 687 3457 | f 1013 3458 | f 1883 3459 | f 1453 3460 | f 1233 3461 | f 1683 3462 | a 2055 14311 3463 | f 1845 3464 | f 1846 3465 | f 1298 3466 | f 1939 3467 | f 1329 3468 | f 597 3469 | f 1383 3470 | f 1904 3471 | f 324 3472 | a 2056 29183 3473 | a 2057 722 3474 | f 1988 3475 | f 837 3476 | f 980 3477 | a 2058 28501 3478 | f 1304 3479 | a 2059 24216 3480 | f 1716 3481 | f 748 3482 | f 1392 3483 | a 2060 15648 3484 | f 1031 3485 | a 2061 17540 3486 | f 1952 3487 | a 2062 1857 3488 | f 1103 3489 | a 2063 21751 3490 | f 1752 3491 | f 1281 3492 | f 1865 3493 | a 2064 13036 3494 | f 1300 3495 | f 864 3496 | a 2065 24513 3497 | f 1756 3498 | a 2066 27168 3499 | a 2067 1233 3500 | a 2068 10221 3501 | a 2069 1122 3502 | f 2050 3503 | f 1108 3504 | f 1857 3505 | a 2070 18565 3506 | a 2071 22520 3507 | a 2072 1597 3508 | f 1701 3509 | f 1293 3510 | f 1837 3511 | f 797 3512 | f 1666 3513 | a 2073 20712 3514 | f 1647 3515 | a 2074 21978 3516 | f 1068 3517 | a 2075 10128 3518 | f 1889 3519 | a 2076 31519 3520 | a 2077 29941 3521 | a 2078 12261 3522 | f 1497 3523 | f 1777 3524 | a 2079 7553 3525 | f 1907 3526 | f 1709 3527 | f 259 3528 | a 2080 21282 3529 | f 1955 3530 | f 1693 3531 | a 2081 28489 3532 | f 1315 3533 | f 1440 3534 | f 1268 3535 | a 2082 14014 3536 | f 881 3537 | f 1448 3538 | f 1093 3539 | f 994 3540 | f 1782 3541 | f 981 3542 | a 2083 30643 3543 | f 1343 3544 | f 2054 3545 | f 2070 3546 | f 1739 3547 | a 2084 17508 3548 | f 727 3549 | a 2085 28344 3550 | a 2086 12187 3551 | f 1406 3552 | a 2087 13924 3553 | f 2083 3554 | a 2088 29066 3555 | f 1804 3556 | a 2089 7921 3557 | a 2090 5372 3558 | f 1829 3559 | f 1672 3560 | a 2091 11947 3561 | a 2092 25462 3562 | f 1698 3563 | a 2093 7229 3564 | f 2016 3565 | f 1638 3566 | f 1953 3567 | a 2094 930 3568 | f 1979 3569 | f 2036 3570 | f 1169 3571 | f 1906 3572 | a 2095 5730 3573 | f 1330 3574 | f 2061 3575 | f 1518 3576 | a 2096 31743 3577 | f 1183 3578 | f 1515 3579 | f 666 3580 | f 1146 3581 | a 2097 28099 3582 | f 904 3583 | f 1983 3584 | a 2098 6964 3585 | a 2099 9196 3586 | f 2071 3587 | f 705 3588 | f 968 3589 | a 2100 29222 3590 | a 2101 25529 3591 | a 2102 31717 3592 | f 1560 3593 | a 2103 30819 3594 | f 1196 3595 | a 2104 13473 3596 | f 1266 3597 | f 500 3598 | f 1975 3599 | a 2105 20928 3600 | f 1101 3601 | a 2106 8180 3602 | a 2107 12225 3603 | f 2062 3604 | a 2108 18101 3605 | f 2017 3606 | f 1160 3607 | f 1964 3608 | f 1540 3609 | a 2109 20441 3610 | f 1931 3611 | f 1488 3612 | a 2110 19779 3613 | f 1427 3614 | a 2111 6616 3615 | f 1539 3616 | f 1523 3617 | f 1821 3618 | f 1729 3619 | a 2112 16163 3620 | f 577 3621 | a 2113 1026 3622 | f 1768 3623 | f 917 3624 | f 834 3625 | f 345 3626 | f 151 3627 | f 1557 3628 | a 2114 4492 3629 | a 2115 903 3630 | f 1761 3631 | a 2116 29370 3632 | a 2117 16680 3633 | f 1531 3634 | f 2060 3635 | f 2009 3636 | f 2049 3637 | f 1936 3638 | f 1763 3639 | f 1687 3640 | a 2118 14827 3641 | f 2084 3642 | f 2025 3643 | f 846 3644 | f 1485 3645 | f 3 3646 | f 1353 3647 | f 2068 3648 | f 269 3649 | f 1238 3650 | f 1618 3651 | a 2119 25669 3652 | a 2120 24601 3653 | a 2121 20200 3654 | f 915 3655 | a 2122 4848 3656 | a 2123 17295 3657 | f 180 3658 | f 2032 3659 | f 1855 3660 | a 2124 27429 3661 | f 1161 3662 | f 84 3663 | f 2089 3664 | f 1639 3665 | f 2021 3666 | f 2094 3667 | f 2104 3668 | f 1232 3669 | f 1192 3670 | a 2125 5779 3671 | f 1134 3672 | f 2006 3673 | a 2126 23025 3674 | a 2127 26405 3675 | f 1061 3676 | f 2038 3677 | f 1811 3678 | f 1870 3679 | f 798 3680 | f 1420 3681 | f 1706 3682 | f 1820 3683 | f 408 3684 | f 1436 3685 | a 2128 1110 3686 | f 1391 3687 | f 1405 3688 | f 1762 3689 | f 1219 3690 | a 2129 29990 3691 | f 2098 3692 | f 1786 3693 | a 2130 2834 3694 | a 2131 30332 3695 | f 2130 3696 | f 1871 3697 | f 1806 3698 | f 1384 3699 | f 1493 3700 | f 759 3701 | f 2000 3702 | a 2132 22751 3703 | a 2133 1783 3704 | f 1784 3705 | f 1899 3706 | f 1224 3707 | a 2134 28383 3708 | a 2135 3457 3709 | a 2136 22711 3710 | a 2137 3795 3711 | f 608 3712 | f 1862 3713 | a 2138 15683 3714 | a 2139 8045 3715 | a 2140 24237 3716 | a 2141 2694 3717 | f 1603 3718 | f 1915 3719 | a 2142 14661 3720 | a 2143 7632 3721 | f 761 3722 | f 2007 3723 | f 2033 3724 | a 2144 3721 3725 | f 2096 3726 | f 1887 3727 | a 2145 19154 3728 | f 1773 3729 | f 590 3730 | a 2146 8535 3731 | a 2147 323 3732 | a 2148 3066 3733 | f 1155 3734 | a 2149 23363 3735 | f 1858 3736 | f 2101 3737 | f 583 3738 | a 2150 25992 3739 | f 2079 3740 | f 1024 3741 | f 2008 3742 | f 1996 3743 | a 2151 27667 3744 | f 420 3745 | a 2152 10796 3746 | f 2027 3747 | a 2153 30841 3748 | f 1658 3749 | a 2154 12194 3750 | f 1689 3751 | f 517 3752 | f 1885 3753 | f 1 3754 | a 2155 5458 3755 | a 2156 3852 3756 | f 2092 3757 | a 2157 2452 3758 | f 653 3759 | f 876 3760 | f 660 3761 | a 2158 31863 3762 | a 2159 4963 3763 | a 2160 32442 3764 | f 317 3765 | f 2147 3766 | f 2151 3767 | f 1594 3768 | f 50 3769 | f 564 3770 | f 601 3771 | f 2011 3772 | a 2161 1929 3773 | a 2162 2527 3774 | f 1472 3775 | f 2131 3776 | a 2163 22426 3777 | f 1872 3778 | f 1450 3779 | a 2164 3712 3780 | f 1913 3781 | f 468 3782 | f 1702 3783 | f 1332 3784 | f 2106 3785 | f 1802 3786 | f 1764 3787 | a 2165 30911 3788 | f 2019 3789 | f 1292 3790 | f 1339 3791 | f 781 3792 | f 1590 3793 | f 1402 3794 | f 279 3795 | f 2066 3796 | a 2166 25883 3797 | f 1803 3798 | a 2167 26424 3799 | f 361 3800 | f 664 3801 | f 2164 3802 | f 2111 3803 | f 1395 3804 | f 1526 3805 | f 1884 3806 | f 81 3807 | a 2168 1939 3808 | f 1176 3809 | f 300 3810 | f 2031 3811 | f 2034 3812 | f 13 3813 | f 74 3814 | f 1854 3815 | f 165 3816 | a 2169 8799 3817 | f 1320 3818 | f 1844 3819 | f 2030 3820 | a 2170 1701 3821 | a 2171 26176 3822 | f 1179 3823 | a 2172 11493 3824 | f 2114 3825 | f 1700 3826 | f 340 3827 | a 2173 16363 3828 | f 1791 3829 | a 2174 1041 3830 | f 879 3831 | f 970 3832 | f 2105 3833 | a 2175 15214 3834 | f 1240 3835 | f 2128 3836 | a 2176 2749 3837 | a 2177 9577 3838 | f 890 3839 | f 106 3840 | a 2178 15538 3841 | f 1749 3842 | a 2179 5815 3843 | f 2178 3844 | f 2141 3845 | f 1815 3846 | f 2160 3847 | f 926 3848 | f 100 3849 | f 1852 3850 | f 120 3851 | f 1949 3852 | f 109 3853 | a 2180 173 3854 | a 2181 8763 3855 | f 1798 3856 | f 1839 3857 | f 621 3858 | f 1471 3859 | a 2182 715 3860 | f 800 3861 | f 2022 3862 | f 1725 3863 | f 1212 3864 | a 2183 10969 3865 | f 513 3866 | f 1910 3867 | a 2184 6836 3868 | f 1660 3869 | f 1977 3870 | f 1188 3871 | f 591 3872 | f 2183 3873 | f 922 3874 | f 2165 3875 | a 2185 12910 3876 | f 990 3877 | a 2186 16427 3878 | a 2187 10689 3879 | f 1632 3880 | a 2188 15362 3881 | f 2099 3882 | f 2171 3883 | a 2189 15522 3884 | f 483 3885 | f 1954 3886 | f 2055 3887 | f 2029 3888 | a 2190 15652 3889 | f 1566 3890 | a 2191 15037 3891 | f 2177 3892 | f 1319 3893 | a 2192 17452 3894 | f 1946 3895 | f 1938 3896 | a 2193 18180 3897 | f 2064 3898 | f 2176 3899 | f 2103 3900 | f 1783 3901 | f 2063 3902 | f 1513 3903 | f 1017 3904 | f 1036 3905 | a 2194 4696 3906 | a 2195 21164 3907 | f 1287 3908 | a 2196 16324 3909 | f 747 3910 | f 491 3911 | a 2197 30579 3912 | f 1767 3913 | a 2198 14820 3914 | f 1969 3915 | f 1838 3916 | f 2072 3917 | f 758 3918 | f 1772 3919 | f 2118 3920 | a 2199 18264 3921 | f 1738 3922 | f 1864 3923 | f 1290 3924 | f 2077 3925 | a 2200 6611 3926 | a 2201 16522 3927 | a 2202 11672 3928 | f 1351 3929 | f 424 3930 | a 2203 18104 3931 | f 1877 3932 | f 1759 3933 | f 607 3934 | f 2169 3935 | f 1911 3936 | f 237 3937 | f 2146 3938 | f 1136 3939 | f 1015 3940 | a 2204 117 3941 | f 241 3942 | f 2052 3943 | f 1387 3944 | f 2203 3945 | a 2205 12714 3946 | f 2187 3947 | a 2206 551 3948 | f 1214 3949 | f 1847 3950 | f 1692 3951 | f 2139 3952 | f 1644 3953 | f 1659 3954 | f 1338 3955 | f 1476 3956 | a 2207 2866 3957 | f 1673 3958 | a 2208 22291 3959 | f 1769 3960 | a 2209 16089 3961 | f 2086 3962 | f 1454 3963 | f 1948 3964 | f 1873 3965 | f 1745 3966 | a 2210 8682 3967 | a 2211 22464 3968 | f 1985 3969 | f 405 3970 | f 2102 3971 | f 1617 3972 | f 568 3973 | f 2097 3974 | a 2212 24853 3975 | f 171 3976 | a 2213 9397 3977 | f 1934 3978 | f 1251 3979 | a 2214 665 3980 | a 2215 31689 3981 | f 1892 3982 | f 1799 3983 | f 2053 3984 | f 199 3985 | f 2116 3986 | f 1512 3987 | f 1688 3988 | f 2112 3989 | f 2148 3990 | f 1950 3991 | f 1622 3992 | f 1778 3993 | f 1986 3994 | f 2044 3995 | a 2216 22307 3996 | f 2039 3997 | f 1981 3998 | f 1989 3999 | a 2217 17093 4000 | f 1159 4001 | f 2076 4002 | a 2218 9610 4003 | a 2219 4902 4004 | f 332 4005 | f 1643 4006 | a 2220 32615 4007 | a 2221 25263 4008 | f 940 4009 | f 1145 4010 | f 1901 4011 | f 135 4012 | a 2222 19939 4013 | f 2065 4014 | f 1869 4015 | f 1437 4016 | f 1549 4017 | f 1723 4018 | f 2023 4019 | f 1957 4020 | f 1642 4021 | f 1722 4022 | a 2223 17300 4023 | f 822 4024 | f 1840 4025 | f 1818 4026 | f 1553 4027 | f 1944 4028 | a 2224 10675 4029 | a 2225 24635 4030 | f 1896 4031 | a 2226 5696 4032 | f 2046 4033 | f 2205 4034 | f 1432 4035 | f 1813 4036 | a 2227 27000 4037 | f 2140 4038 | f 223 4039 | f 475 4040 | a 2228 22447 4041 | a 2229 20517 4042 | f 2045 4043 | f 2213 4044 | a 2230 12496 4045 | f 919 4046 | f 2133 4047 | a 2231 29058 4048 | a 2232 4271 4049 | a 2233 24169 4050 | a 2234 14395 4051 | f 1591 4052 | a 2235 4389 4053 | a 2236 4115 4054 | a 2237 14947 4055 | a 2238 7255 4056 | f 2236 4057 | f 2172 4058 | f 1990 4059 | f 1610 4060 | f 1789 4061 | f 2192 4062 | f 1900 4063 | f 1350 4064 | a 2239 26406 4065 | f 927 4066 | a 2240 31037 4067 | f 2225 4068 | f 2138 4069 | f 1246 4070 | f 2134 4071 | a 2241 15937 4072 | f 993 4073 | f 1362 4074 | f 2069 4075 | f 2051 4076 | f 310 4077 | f 2067 4078 | f 2199 4079 | a 2242 16102 4080 | f 1851 4081 | f 1947 4082 | f 442 4083 | a 2243 23122 4084 | f 495 4085 | f 1765 4086 | f 1421 4087 | f 1409 4088 | f 892 4089 | f 2242 4090 | f 2152 4091 | f 1747 4092 | f 1636 4093 | f 1925 4094 | f 2208 4095 | f 2195 4096 | f 752 4097 | a 2244 25335 4098 | a 2245 16768 4099 | f 2115 4100 | a 2246 22043 4101 | f 2010 4102 | f 1606 4103 | a 2247 14874 4104 | f 1439 4105 | a 2248 1093 4106 | a 2249 31654 4107 | f 1928 4108 | f 1382 4109 | f 2204 4110 | a 2250 19776 4111 | f 1830 4112 | f 1656 4113 | a 2251 941 4114 | f 1881 4115 | a 2252 24149 4116 | f 1972 4117 | a 2253 6948 4118 | f 2253 4119 | f 1412 4120 | f 1781 4121 | f 1114 4122 | a 2254 18241 4123 | a 2255 2057 4124 | f 593 4125 | f 2113 4126 | f 2013 4127 | f 2078 4128 | f 1927 4129 | f 695 4130 | f 1737 4131 | f 1880 4132 | f 2156 4133 | f 2080 4134 | f 2107 4135 | f 1363 4136 | f 2179 4137 | f 2142 4138 | f 2026 4139 | f 1843 4140 | f 1085 4141 | f 2202 4142 | f 1965 4143 | f 2173 4144 | f 1968 4145 | f 230 4146 | f 1684 4147 | f 2090 4148 | a 2256 31584 4149 | f 2185 4150 | f 1976 4151 | f 1922 4152 | f 1225 4153 | f 1231 4154 | f 1959 4155 | f 1616 4156 | f 2126 4157 | a 2257 23938 4158 | a 2258 29057 4159 | f 2088 4160 | a 2259 21264 4161 | a 2260 11688 4162 | a 2261 8785 4163 | f 2222 4164 | f 1475 4165 | f 2157 4166 | f 2014 4167 | a 2262 17554 4168 | a 2263 15960 4169 | f 2238 4170 | f 2004 4171 | f 972 4172 | f 2182 4173 | a 2264 186 4174 | f 2018 4175 | f 2207 4176 | a 2265 31950 4177 | f 1790 4178 | f 2124 4179 | f 2252 4180 | f 2256 4181 | f 1262 4182 | f 1564 4183 | f 2095 4184 | a 2266 20349 4185 | a 2267 4301 4186 | f 1484 4187 | f 2239 4188 | f 436 4189 | f 1993 4190 | f 847 4191 | a 2268 14129 4192 | a 2269 27604 4193 | a 2270 30708 4194 | f 2262 4195 | a 2271 12399 4196 | f 1753 4197 | f 1046 4198 | f 1052 4199 | f 2193 4200 | a 2272 10774 4201 | f 2219 4202 | f 1649 4203 | f 1535 4204 | f 1921 4205 | f 1711 4206 | f 1502 4207 | f 1162 4208 | f 2081 4209 | f 1289 4210 | a 2273 14042 4211 | f 2037 4212 | f 1322 4213 | f 550 4214 | f 1817 4215 | f 1573 4216 | f 1469 4217 | f 2149 4218 | f 1608 4219 | a 2274 2753 4220 | f 1967 4221 | f 488 4222 | a 2275 3342 4223 | f 1441 4224 | f 1311 4225 | f 1891 4226 | f 1255 4227 | f 1951 4228 | f 1890 4229 | f 1721 4230 | f 67 4231 | a 2276 30811 4232 | a 2277 24797 4233 | a 2278 18216 4234 | a 2279 31904 4235 | f 1571 4236 | a 2280 23683 4237 | a 2281 5225 4238 | f 2117 4239 | a 2282 78 4240 | a 2283 15065 4241 | f 1163 4242 | f 2220 4243 | f 412 4244 | f 644 4245 | f 2047 4246 | f 2108 4247 | a 2284 12174 4248 | f 1807 4249 | a 2285 18320 4250 | f 1715 4251 | f 2227 4252 | f 1373 4253 | a 2286 17122 4254 | f 1826 4255 | a 2287 10990 4256 | f 1422 4257 | a 2288 9490 4258 | f 2271 4259 | f 1156 4260 | f 1917 4261 | a 2289 13412 4262 | f 1261 4263 | a 2290 32254 4264 | f 1868 4265 | f 2137 4266 | f 2231 4267 | f 1878 4268 | f 1048 4269 | f 2260 4270 | f 698 4271 | f 1963 4272 | f 2243 4273 | f 2240 4274 | f 1992 4275 | f 1482 4276 | f 2237 4277 | a 2291 21179 4278 | f 2280 4279 | a 2292 22197 4280 | f 2287 4281 | f 1040 4282 | a 2293 17041 4283 | f 1153 4284 | f 1754 4285 | a 2294 4371 4286 | f 2234 4287 | f 2129 4288 | f 2093 4289 | a 2295 22384 4290 | a 2296 16223 4291 | a 2297 24720 4292 | f 1593 4293 | f 2221 4294 | f 2196 4295 | a 2298 26686 4296 | f 1317 4297 | a 2299 30353 4298 | f 322 4299 | f 2136 4300 | f 2159 4301 | f 2058 4302 | f 1533 4303 | f 2056 4304 | f 2057 4305 | f 2299 4306 | f 1923 4307 | f 2015 4308 | f 1510 4309 | a 2300 19557 4310 | f 1021 4311 | f 2216 4312 | f 832 4313 | a 2301 24626 4314 | f 2258 4315 | f 1835 4316 | f 2295 4317 | a 2302 9984 4318 | f 2122 4319 | f 1757 4320 | a 2303 30332 4321 | f 1853 4322 | f 746 4323 | a 2304 5900 4324 | f 2300 4325 | a 2305 12737 4326 | f 108 4327 | f 2286 4328 | a 2306 906 4329 | a 2307 3944 4330 | f 261 4331 | f 2158 4332 | f 377 4333 | f 615 4334 | a 2308 4767 4335 | a 2309 19123 4336 | f 2161 4337 | f 146 4338 | f 2308 4339 | f 226 4340 | f 2283 4341 | f 2144 4342 | a 2310 3080 4343 | a 2311 28450 4344 | a 2312 24348 4345 | f 2091 4346 | f 2278 4347 | f 2197 4348 | f 2180 4349 | f 2189 4350 | f 2153 4351 | a 2313 3159 4352 | f 1696 4353 | f 2297 4354 | f 1886 4355 | f 1034 4356 | a 2314 10748 4357 | f 1945 4358 | f 2059 4359 | f 1121 4360 | f 76 4361 | f 2127 4362 | f 757 4363 | f 2048 4364 | f 2145 4365 | f 770 4366 | a 2315 3755 4367 | a 2316 21479 4368 | f 1823 4369 | f 2167 4370 | a 2317 27871 4371 | f 1997 4372 | f 2247 4373 | f 460 4374 | a 2318 14745 4375 | f 1517 4376 | f 1567 4377 | f 2302 4378 | f 1563 4379 | f 807 4380 | f 985 4381 | a 2319 30970 4382 | f 2311 4383 | f 855 4384 | f 1860 4385 | f 2001 4386 | f 2120 4387 | a 2320 8515 4388 | f 1834 4389 | f 2043 4390 | f 2020 4391 | f 2257 4392 | f 2296 4393 | f 1199 4394 | f 2184 4395 | f 148 4396 | a 2321 14231 4397 | f 1486 4398 | f 2082 4399 | f 2162 4400 | f 2110 4401 | f 1096 4402 | f 2265 4403 | f 1998 4404 | a 2322 19381 4405 | a 2323 30713 4406 | f 397 4407 | f 1078 4408 | f 1994 4409 | f 1731 4410 | f 945 4411 | f 1841 4412 | a 2324 31273 4413 | f 2230 4414 | f 2109 4415 | a 2325 23752 4416 | f 913 4417 | a 2326 20329 4418 | f 701 4419 | f 2223 4420 | f 2168 4421 | a 2327 14728 4422 | f 2292 4423 | a 2328 15704 4424 | f 1801 4425 | f 2282 4426 | a 2329 14247 4427 | f 1805 4428 | a 2330 12314 4429 | f 2215 4430 | f 1075 4431 | f 2277 4432 | f 730 4433 | f 2279 4434 | f 992 4435 | f 1867 4436 | a 2331 2493 4437 | f 2288 4438 | f 2143 4439 | a 2332 6105 4440 | f 1368 4441 | f 364 4442 | f 1755 4443 | f 1908 4444 | a 2333 22298 4445 | f 2274 4446 | f 2190 4447 | a 2334 57 4448 | f 1128 4449 | f 1824 4450 | a 2335 12006 4451 | f 2125 4452 | f 1771 4453 | f 2232 4454 | f 1216 4455 | f 1554 4456 | f 2254 4457 | f 2228 4458 | f 1333 4459 | f 2166 4460 | f 685 4461 | f 1971 4462 | a 2336 2268 4463 | f 2329 4464 | f 1942 4465 | a 2337 964 4466 | f 1960 4467 | f 2012 4468 | f 2316 4469 | f 2289 4470 | f 2313 4471 | f 1973 4472 | f 2314 4473 | f 2248 4474 | f 2132 4475 | f 2087 4476 | f 1173 4477 | f 2210 4478 | f 1282 4479 | f 2294 4480 | f 320 4481 | f 1558 4482 | f 2200 4483 | a 2338 15950 4484 | f 1584 4485 | f 1097 4486 | f 154 4487 | f 2323 4488 | a 2339 7035 4489 | a 2340 20087 4490 | a 2341 19031 4491 | f 2005 4492 | f 1822 4493 | f 1527 4494 | a 2342 2718 4495 | a 2343 11668 4496 | f 2322 4497 | a 2344 22190 4498 | a 2345 13467 4499 | f 953 4500 | a 2346 15423 4501 | f 2341 4502 | f 1678 4503 | f 1397 4504 | f 1544 4505 | f 1032 4506 | a 2347 10902 4507 | f 2041 4508 | a 2348 8570 4509 | a 2349 30169 4510 | f 1637 4511 | f 501 4512 | f 1205 4513 | f 2338 4514 | f 2218 4515 | a 2350 9104 4516 | a 2351 17085 4517 | f 1932 4518 | f 2326 4519 | f 711 4520 | f 806 4521 | f 2249 4522 | f 378 4523 | f 1800 4524 | f 2340 4525 | f 2074 4526 | a 2352 11633 4527 | f 997 4528 | f 2085 4529 | f 1888 4530 | f 1912 4531 | f 1296 4532 | a 2353 28485 4533 | f 1524 4534 | f 1694 4535 | f 891 4536 | f 53 4537 | f 1349 4538 | f 2042 4539 | f 1984 4540 | f 2307 4541 | f 1850 4542 | f 1628 4543 | f 2317 4544 | a 2354 15031 4545 | f 1598 4546 | f 2121 4547 | f 2217 4548 | f 2259 4549 | f 2174 4550 | f 239 4551 | f 1534 4552 | f 2291 4553 | f 2337 4554 | f 2324 4555 | a 2355 10138 4556 | a 2356 19469 4557 | f 2075 4558 | f 388 4559 | f 777 4560 | a 2357 2592 4561 | f 2194 4562 | f 2135 4563 | f 2229 4564 | f 2266 4565 | f 1987 4566 | f 413 4567 | f 1561 4568 | f 2188 4569 | f 2211 4570 | f 738 4571 | f 2306 4572 | a 2358 24867 4573 | f 2305 4574 | f 2035 4575 | f 2250 4576 | f 1285 4577 | f 976 4578 | f 2351 4579 | f 1374 4580 | f 1775 4581 | f 2264 4582 | a 2359 2405 4583 | a 2360 16840 4584 | f 2214 4585 | f 2352 4586 | f 2002 4587 | a 2361 4413 4588 | f 2267 4589 | f 2336 4590 | f 2344 4591 | f 2348 4592 | f 2361 4593 | f 1056 4594 | f 2350 4595 | f 543 4596 | f 1882 4597 | a 2362 4899 4598 | a 2363 22946 4599 | f 2201 4600 | a 2364 26712 4601 | f 1142 4602 | f 1856 4603 | f 221 4604 | a 2365 4957 4605 | a 2366 2185 4606 | f 2163 4607 | f 2224 4608 | f 2362 4609 | f 1170 4610 | f 2339 4611 | a 2367 28981 4612 | f 1049 4613 | a 2368 5921 4614 | f 1919 4615 | f 2359 4616 | f 1795 4617 | f 1914 4618 | a 2369 18136 4619 | f 2268 4620 | f 2321 4621 | a 2370 3249 4622 | f 2356 4623 | f 2272 4624 | f 2073 4625 | f 2275 4626 | f 814 4627 | f 2368 4628 | f 2290 4629 | a 2371 26009 4630 | f 714 4631 | f 2304 4632 | a 2372 4400 4633 | f 2100 4634 | f 2319 4635 | f 2245 4636 | f 2226 4637 | f 2335 4638 | a 2373 5968 4639 | a 2374 4910 4640 | f 1974 4641 | f 2040 4642 | f 2358 4643 | f 2342 4644 | a 2375 26591 4645 | f 595 4646 | f 2301 4647 | f 2327 4648 | f 478 4649 | f 2276 4650 | f 155 4651 | f 2235 4652 | f 1619 4653 | f 2233 4654 | f 2263 4655 | f 1670 4656 | f 2330 4657 | f 788 4658 | f 2123 4659 | f 2367 4660 | f 2354 4661 | f 2371 4662 | f 2374 4663 | f 494 4664 | a 2376 19435 4665 | a 2377 20334 4666 | f 2024 4667 | f 2325 4668 | f 2293 4669 | a 2378 4725 4670 | f 2298 4671 | f 1091 4672 | a 2379 28005 4673 | a 2380 17735 4674 | f 2241 4675 | f 2170 4676 | f 2366 4677 | f 2353 4678 | f 2373 4679 | f 1241 4680 | f 2376 4681 | f 2349 4682 | f 2261 4683 | f 2347 4684 | f 2334 4685 | f 988 4686 | a 2381 13829 4687 | f 2303 4688 | a 2382 12323 4689 | a 2383 29368 4690 | f 2198 4691 | f 712 4692 | f 2309 4693 | f 2312 4694 | f 1918 4695 | f 2315 4696 | f 2119 4697 | f 2155 4698 | f 1894 4699 | f 1529 4700 | a 2384 9546 4701 | a 2385 27354 4702 | f 2369 4703 | f 734 4704 | f 2191 4705 | f 2269 4706 | f 1741 4707 | f 1978 4708 | f 2355 4709 | f 1596 4710 | f 1676 4711 | f 1496 4712 | f 1457 4713 | f 2346 4714 | a 2386 6738 4715 | f 2372 4716 | f 2154 4717 | a 2387 29016 4718 | f 1902 4719 | f 2186 4720 | f 1679 4721 | f 2318 4722 | f 2385 4723 | f 2333 4724 | f 1326 4725 | f 2379 4726 | f 1966 4727 | f 1433 4728 | f 2328 4729 | f 2175 4730 | f 1480 4731 | f 1705 4732 | f 1686 4733 | a 2388 29947 4734 | f 2378 4735 | a 2389 31606 4736 | f 2380 4737 | f 2388 4738 | f 2332 4739 | a 2390 31421 4740 | f 1047 4741 | a 2391 14020 4742 | f 2255 4743 | f 2384 4744 | f 2370 4745 | f 2357 4746 | f 2345 4747 | f 1514 4748 | f 2246 4749 | f 2365 4750 | f 2331 4751 | f 2270 4752 | f 2363 4753 | f 2386 4754 | f 1555 4755 | f 1189 4756 | f 1125 4757 | f 2310 4758 | a 2392 3251 4759 | f 2320 4760 | a 2393 3553 4761 | f 2393 4762 | f 484 4763 | f 2364 4764 | f 1970 4765 | f 2382 4766 | f 1937 4767 | f 2273 4768 | f 2212 4769 | f 2285 4770 | f 2206 4771 | f 2251 4772 | a 2394 4199 4773 | f 2150 4774 | f 2383 4775 | f 2209 4776 | f 2343 4777 | f 2387 4778 | f 1487 4779 | f 2360 4780 | f 2375 4781 | f 2381 4782 | a 2395 29964 4783 | a 2396 8510 4784 | f 1958 4785 | f 2389 4786 | f 2377 4787 | f 2181 4788 | f 2244 4789 | a 2397 6384 4790 | f 839 4791 | f 2281 4792 | f 2397 4793 | f 2392 4794 | f 2394 4795 | f 2390 4796 | f 2395 4797 | f 2284 4798 | f 2396 4799 | f 2003 4800 | a 2398 26178 4801 | f 2398 4802 | f 2391 4803 | a 2399 14432 4804 | f 2399 4805 | -------------------------------------------------------------------------------- /traces/short1-bal.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 2040 7 | f 1 8 | a 2 48 9 | a 3 4072 10 | f 3 11 | a 4 4072 12 | f 0 13 | f 2 14 | a 5 4072 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /traces/short2-bal.rep: -------------------------------------------------------------------------------- 1 | 20000 2 | 6 3 | 12 4 | 1 5 | a 0 2040 6 | a 1 4010 7 | a 2 48 8 | a 3 4072 9 | a 4 4072 10 | a 5 4072 11 | f 0 12 | f 1 13 | f 2 14 | f 3 15 | f 4 16 | f 5 17 | -------------------------------------------------------------------------------- /writeup.txt: -------------------------------------------------------------------------------- 1 | Harsh Trivedi (id: 201201042) 2 | Karan Tankshali (id: 201201043) 3 | 4 | COMP 221 Project 5: Malloc Dynamic Memory Allocator 5 | 10th Marth, 2014 6 | 7 | DESCRIPTION 8 | 9 | The solution adopted by us is of using an explicit free list to maintain the list of pointers to free blocks. This enhances speed wise performace of allocator as compared to implicit free list, since allocator does not need to traverse the allocated blocks while finding appropiate size of free memory. This improved throughput to great extent. To improve memory allocation (util) , some changes have been made in reallocation strategy. Finally to improve performance a little more, some changes have been made in find fit function so as to prevent very long traversals sometimes. 10 | 11 | DESIGN 12 | 13 | In all there are 3 main features that has been added to allocator (changed from default allocator given to us) 14 | 15 | 1. Implemented explicit free list to maintain the list of pointers to free blocks. 16 | 17 | DataStructure used of free list is Doubly Linked List. 18 | Programmer accesses only that memory which is allocated. Ie (the allocated blocks) So free blocks can be effieciently to store other important information. Since minimum block size given is 4 words , no free block can be less than 4 words. With this fact, we can easiliy store 2 pointers in free blocks (which requires only 2 words). First pointer will point to the free block (in heap) previous to the current free block (in which we are storing pointers) and the second will point to the free block next to the current free block. 19 | 20 | Any free block in heap will be of following format. 21 | ---------------------------------------------------------------------------------- 22 | | Prev Free Block ptr (1 word) | Next Free Block ptr(1 word) | ... | 23 | ---------------------------------------------------------------------------------- 24 | Hence if I have a pointer bp to a free block then i can access next and previous free blocks using macros: 25 | #define GET_NEXT_PTR(bp) (*(char **)(bp + WSIZE)) 26 | #define GET_PREV_PTR(bp) (*(char **)(bp)) 27 | And to set previous and next pointer we have used: 28 | #define SET_NEXT_PTR(bp, qp) (GET_NEXT_PTR(bp) = qp) 29 | #define SET_PREV_PTR(bp, qp) (GET_PREV_PTR(bp) = qp) 30 | Further two functions : 31 | void insert_in_free_list(void *bp) 32 | remove_from_free_list(void *bp) 33 | have been implemented using above macros so as to maintain free list. 34 | 35 | 36 | 2. Changed realloc function so as to improve the dropping performance in realloc-bal.rep and realloc2-bal.rep 37 | 38 | The default realloc function was inefficient due to the reason that it would always call malloc again so find memory of new size and copy all contents to it, even when it is not necessary. 39 | To fix this, we have added a condition in realloc. 40 | Eg, for scenario where realloc asks for newsize of space and current size of block is oldsize and newsize is greater than oldsize. Ie (block needs to expand) then, it should first check if the next block is free or not. In case next block is free and sum total of both block (this block and next block) is greater than the oldsize then we can only change the size of current block, fix header, footer and we are done. No need to copy contents anywhere. Contents of old block are still intact and safe. 41 | For example, 42 | ------------------------------------------------------------------------------- 43 | | Current Block (oldsize =8 words)| Next Block (8 word) (free) | 44 | ------------------------------------------------------------------------------- 45 | Now if current block is requested by programmer to extend to 16 words then no need to call malloc again and copy contents. 46 | Just combine two blocks while taking care of extra space remaining: 47 | ------------------------------------------------------------------------------- 48 | | Current Block (newsize =16 words) | 49 | ------------------------------------------------------------------------------- 50 | 51 | 3. Preventing dropping performance due to repetitive same sized malloc calls. 52 | 53 | We have a test file called binary-bal.rep in which same malloc requests are made many many of times in a row. Implementing first fit algorithm using explicit list reduces time- efficiency. To prevent from this condition, we can use the following scheme: 54 | If it is realized that many times (say > 30 times) same malloc size request has been made 55 | then instead of traversing the full free list , when we know it is going to take long, we can just extend the heap by the requested amount. However care has to be taken so as to prevent many extend_heap calls to make program run out of memory. 56 | 57 | Extra points about the program: 58 | 59 | ->Headers and Footer have been kept as such in the program. It has the following structure: 60 | 31 3 2 1 0 61 | ----------------------------------- 62 | | s s s s ... s s s 0 0 a/f 63 | ----------------------------------- 64 | -> Coalescing scheme is immediate coalescing using boundary tag coalescing. 65 | -> Searching through free list executes first fit algorithm. 66 | 67 | 68 | TESTING STRATEGY 69 | 70 | Tracefiles solely has been used for testing purpose. In initial phase, short1-bal.rep and short2-bal.rep were useful for checking basic working of the code and removing segmentation fault! Later, once the code ran properly (without any segmentation fault) in all test files, individual test files which had poor performance were checked, and appropiate change in code was made to improve it. At times, gdg have been a useful tool. 71 | Since overall performance yeilded well (around 90 in my machine) , we assumed that the testing was adequate. 72 | 73 | 74 | -------------------------------------------------------------------------------- /writeup.txt~: -------------------------------------------------------------------------------- 1 | Harsh Trivedi (id: 201201042) 2 | Karan Tankshali (id: 201201043) 3 | 4 | COMP 221 Project 5: Malloc Dynamic Memory Allocator 5 | 10th Marth, 2014 6 | 7 | DESCRIPTION 8 | 9 | The solution adopted by us is of using an explicit free list to maintain the list of pointers to free blocks. This enhances speed wise performace of allocator as compared to implicit free list, since allocator does not need to traverse the allocated blocks while finding appropiate size of free memory. This improved throughput to great extent. To improve memory allocation (util) , some changes have been made in reallocation strategy. Finally to improve performance a little more, some changes have been made in find fit function so as to prevent very long traversals sometimes. 10 | 11 | DESIGN 12 | 13 | In all there are 3 main features that has been added to allocator (changed from default allocator given to us) 14 | 15 | 1. Implemented explicit free list to maintain the list of pointers to free blocks. 16 | 17 | DataStructure used of free list is Doubly Linked List. 18 | Programmer accesses only that memory which is allocated. Ie (the allocated blocks) So free blocks can be effieciently to store other important information. Since minimum block size given is 4 words , no free block can be less than 4 words. With this fact, we can easiliy store 2 pointers in free blocks (which requires only 2 words). First pointer will point to the free block (in heap) previous to the current free block (in which we are storing pointers) and the second will point to the free block next to the current free block. 19 | 20 | Any free block in heap will be of following format. 21 | ---------------------------------------------------------------------------------- 22 | | Prev Free Block ptr (1 word) | Next Free Block ptr(1 word) | ... | 23 | ---------------------------------------------------------------------------------- 24 | Hence if I have a pointer bp to a free block then i can access next and previous free blocks using macros: 25 | #define GET_NEXT_PTR(bp) (*(char **)(bp + WSIZE)) 26 | #define GET_PREV_PTR(bp) (*(char **)(bp)) 27 | And to set previous and next pointer we have used: 28 | #define SET_NEXT_PTR(bp, qp) (GET_NEXT_PTR(bp) = qp) 29 | #define SET_PREV_PTR(bp, qp) (GET_PREV_PTR(bp) = qp) 30 | Further two functions : 31 | void insert_in_free_list(void *bp) 32 | remove_from_free_list(void *bp) 33 | have been implemented using above macros so as to maintain free list. 34 | 35 | 36 | 2. Changed realloc function so as to improve the dropping performance in realloc-bal.rep and realloc2-bal.rep 37 | 38 | The default realloc function was inefficient due to the reason that it would always call malloc again so find memory of new size and copy all contents to it, even when it is not necessary. 39 | To fix this, we have added a condition in realloc. 40 | Eg, for scenario where realloc asks for newsize of space and current size of block is oldsize and newsize is greater than oldsize. Ie (block needs to expand) then, it should first check if the next block is free or not. In case next block is free and sum total of both block (this block and next block) is greater than the oldsize then we can only change the size of current block, fix header, footer and we are done. No need to copy contents anywhere. Contents of old block are still intact and safe. 41 | For example, 42 | ------------------------------------------------------------------------------- 43 | | Current Block (oldsize =8 words)| Next Block (8 word) (free) | 44 | ------------------------------------------------------------------------------- 45 | Now if current block is requested by programmer to extend to 16 words then no need to call malloc again and copy contents. 46 | Just combine two blocks while taking care of extra space remaining: 47 | ------------------------------------------------------------------------------- 48 | | Current Block (newsize =16 words) | 49 | ------------------------------------------------------------------------------- 50 | 51 | 3. Preventing dropping performance due to repetitive same sized malloc calls. 52 | 53 | We have a test file called binary-bal.rep in which same malloc requests are made many many of times in a row. Implementing first fit algorithm using explicit list reduces time- efficiency. To prevent from this condition, we can use the following scheme: 54 | If it is realized that many times (say > 30 times) same malloc size request has been made 55 | then instead of traversing the full free list , when we know it is going to take long, we can just extend the heap by the requested amount. However care has to be taken so as to prevent many extend_heap calls to make program run out of memory. 56 | 57 | Extra points about the program: 58 | 59 | ->Headers and Footer have been kept as such in the program. It has the following structure: 60 | 31 3 2 1 0 61 | ----------------------------------- 62 | | s s s s ... s s s 0 0 a/f 63 | ----------------------------------- 64 | -> Coalescing scheme is immediate coalescing using boundary tag coalescing. 65 | -> Searching through free list executes first fit algorithm. 66 | 67 | 68 | TESTING STRATEGY 69 | 70 | Tracefiles solely has been used for testing purpose. In initial phase, short1-bal.rep and short2-bal.rep were useful for checking basic working of the code and removing segmentation fault! Later, once the code ran properly (without any segmentation fault) in all test files, individual test files which had poor performance were checked, and appropiate change in code was made to improve it. At times, gdg have been a useful tool. 71 | Since overall performance yeilded well (around 90 in my machine) , we assumed that the testing was adequate. 72 | 73 | 74 | --------------------------------------------------------------------------------