/** * @brief TEST_CASE - Sanity test of some key skiplist APIs using integers. */ static int simple( void ) { unsigned int i; skiplist_node_t *iter; skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; if( skiplist_contains( skiplist, 10, NULL ) ) return -1; if( !skiplist_remove( skiplist, 10 ) ) return -1; for( i = 0; i < 10; ++i ) { if( skiplist_insert( skiplist, i ) ) return -1; if( !skiplist_contains( skiplist, i, NULL ) ) return -1; } for( i = 0; i < 100; ++i ) { unsigned int value = rand(); if( skiplist_insert( skiplist, value ) ) return -1; if( !skiplist_contains( skiplist, value, NULL ) ) return -1; } for( i = 5; i < 10; ++i ) if( skiplist_remove( skiplist, i ) ) return -1; for( iter = skiplist_begin( skiplist ); iter != skiplist_end(); iter = skiplist_next( iter ) ) { uintptr_t value = skiplist_node_value( iter, NULL ); if( value >= 5 && value < 10 ) return -1; } for( i = 0; i < skiplist_size( skiplist, NULL ); ++i ) skiplist_at_index( skiplist, i, NULL ); if( skiplist_fprintf_filename( "simple.dot", skiplist ) ) return -1; skiplist_destroy( skiplist ); return 0; }
/** * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_fprintf. */ static int abuse_skiplist_fprintf( void ) { skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; skiplist_fprintf( NULL, skiplist ); skiplist_fprintf( stdout, NULL ); skiplist_destroy( skiplist ); return 0; }
int main(int argc, char **argv) { ut_init(basename(argv[0])); ut_testing("skiplist_create(6, 50, libhl_cmp_keys_int32, free)"); skiplist_t *skl = skiplist_create(6, 50, libhl_cmp_keys_int32, free); if (skl) ut_success(); else ut_failure("Can't create a new binomial heap"); ut_testing("skiplist_insert(0..99)"); int i; for (i = 0; i < 100; i++) { char *val = malloc(4); snprintf(val, 4, "%d", i); skiplist_insert(skl, &i, sizeof(i), val); } ut_validate_int(skiplist_count(skl), 100); int test_key = 50; ut_testing("skiplist_search(50) = \"50\""); char *val = skiplist_search(skl, &test_key, sizeof(int)); ut_validate_string(val, "50"); ut_testing("skiplist_remove(50, &old_value)"); val = NULL; int rc = skiplist_remove(skl, &test_key, sizeof(int), (void **)&val); ut_validate_int(rc, 0); ut_testing("old_value is \"50\""); ut_validate_string(val, "50"); free(val); ut_testing("skiplist_search(50) = NULL"); val = skiplist_search(skl, &test_key, sizeof(int)); ut_validate_string(val, NULL); skiplist_destroy(skl); ut_summary(); return ut_failed; }
/** * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_next. */ static int abuse_skiplist_next( void ) { skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; if( skiplist_insert( skiplist, 1 ) ) return -1; if( skiplist_next( NULL ) ) return -1; skiplist_destroy( skiplist ); return 0; }
/** * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_fprintf_filename. */ static int abuse_skiplist_fprintf_filename( void ) { skiplist_t *skiplist; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 5, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; if( !skiplist_fprintf_filename( NULL, skiplist ) ) return -1; if( !skiplist_fprintf_filename( "valid_filname.txt", NULL ) ) return -1; skiplist_destroy( skiplist ); return 0; }
/** * @brief TEST_CASE - Measures insertion trade off between number of elements in the list and number of links per node. */ static int link_trade_off_insert( void ) { #define MAX_LINKS (SKIPLIST_MAX_LINKS) #define INSERTIONS_LOG2 (16) struct timespec stamps[INSERTIONS_LOG2 + 2]; FILE *fp; unsigned int links; unsigned int i; const char *seperator; fp = fopen( "link_trade_off_insert.gplot", "w" ); if( !fp ) return -1; fprintf(fp, "set term qt\n"); fprintf(fp, "set key off\n"); fprintf(fp, "set logscale\n"); fprintf(fp, "set grid xtics ytics mxtics mytics\n"); fprintf(fp, "set style textbox opaque noborder\n"); fprintf(fp, "set title \"Average Insertion Time for Skiplists with Varying Link Counts\"\n"); fprintf(fp, "set xlabel \"Number of Elements in the Skiplist\"\n"); fprintf(fp, "set ylabel \"Average Time for One Insertion (ns)\"\n"); fprintf(fp, "plot " ); seperator = ""; for( i = 0; i < MAX_LINKS; ++i ) { fprintf(fp, "%s\"link_trade_off_insert_%u.dat\" using 1:2 with lines lt -1," "\"\" using 1:2:($0*0+%u) with labels center boxed notitle", seperator, i + 1, i + 1); seperator = ",\\\n\t"; } fprintf(fp, "\n"); fprintf(fp, "pause -1\n"); fclose( fp ); for( links = MAX_LINKS; links > 0; --links ) { skiplist_t *skiplist; char filename[64]; unsigned int next; sprintf( filename, "link_trade_off_insert_%u.dat", links ); fp = fopen( filename, "w" ); if( !fp ) return -1; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, links, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; next = 0; for( i = 0; i < (1 << INSERTIONS_LOG2); ++i ) { /* Sample at powers of 2. */ if( (i & (i - 1)) == 0 ) { time_stamp( &stamps[next] ); /* Stop trying if it's taking too long. */ if( next && time_diff_ns( &stamps[next - 1], &stamps[next] ) > 300000000LLU ) break; ++next; } if( skiplist_insert( skiplist, rand() ) ) return -1; } time_stamp( &stamps[next] ); ++next; skiplist_destroy( skiplist ); for( i = 1; i < next; ++i ) { const unsigned int node_count = 1 << (i - 1); fprintf(fp, "%u\t%f\n", node_count, time_diff_ns( &stamps[0], &stamps[i] ) / (double)node_count ); } fclose( fp ); } #undef MAX_LINKS #undef INSERTIONS_LOG2 return 0; }
/** * @brief TEST_CASE - Measures lookup trade off between number of elements in the list and number of links per node. */ static int link_trade_off_lookup( void ) { #define MAX_LINKS (SKIPLIST_MAX_LINKS) #define INSERTIONS_LOG2 (16) unsigned int i; FILE *fp; const char *seperator; fp = fopen( "link_trade_off_lookup.gplot", "w" ); if( !fp ) return -1; fprintf(fp, "set term qt\n"); fprintf(fp, "set key off\n"); fprintf(fp, "set logscale\n"); fprintf(fp, "set grid xtics ytics mxtics mytics\n"); fprintf(fp, "set style textbox opaque noborder\n"); fprintf(fp, "set title \"Average Lookup Time for Skiplists with Varying Link Counts\"\n"); fprintf(fp, "set xlabel \"Number of Elements in the Skiplist\"\n"); fprintf(fp, "set ylabel \"Average Time for One Lookup (ns)\"\n"); fprintf(fp, "plot " ); seperator = ""; for( i = 0; i < MAX_LINKS; ++i ) { fprintf(fp, "%s\"link_trade_off_lookup.dat\" using 1:%u with lines lt -1," "\"\" using 1:%u:($0*0+%u) with labels center boxed notitle", seperator, i + 2, i + 2, i + 1); seperator = ",\\\n\t"; } fprintf(fp, "\n"); fprintf(fp, "pause -1\n"); fclose( fp ); fp = fopen( "link_trade_off_lookup.dat", "w" ); if( !fp ) return -1; for( i = 1; i < (1 << INSERTIONS_LOG2); i <<= 1 ) { unsigned int links; fprintf( fp, "%u", i ); for( links = 1; links <= MAX_LINKS; ++links ) { unsigned int j; skiplist_t *skiplist; struct timespec start, end; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, links, int_compare, int_fprintf, NULL ); if( !skiplist ) return -1; for( j = 0; j < i; ++j ) if( skiplist_insert( skiplist, j ) ) return -1; time_stamp( &start ); for( j = 0; j < i; ++j ) if( !skiplist_contains( skiplist, j, NULL ) ) return -1; time_stamp( &end ); fprintf( fp, "\t%f", time_diff_ns( &start, &end ) / (double)i ); skiplist_destroy( skiplist ); } fprintf( fp, "\n" ); } fclose( fp ); #undef MAX_LINKS #undef INSERTIONS_LOG2 return 0; }
/** * @brief TEST_CASE - Confirms incorrect inputs are handled gracefully for skiplist_destroy. */ static int abuse_skiplist_destroy( void ) { /* Can't do much but check NULL doesn't cause a crash. */ skiplist_destroy( NULL ); return 0; }
/** * @brief TEST_CASE - Sanity test of some key skiplist APIs using a pointer to data items. */ static int pointers( void ) { skiplist_t *skiplist; const coord_t coords[] = { /* Simple in order insertion. */ {5,5}, {7,5}, /* Duplicate x with increasing y. */ {5,6}, {5,8}, /* Duplicate x with decreasing y. */ {7,4}, {7,0}, /* Decreasing x. */ {4,5}, {3,5}, /* Increasing x. */ {9,0}, {10,0}, /* Duplicate values. */ {9,0}, {5,5}, /* Zero. */ {0,0}, /* Huge. */ {UINT_MAX,UINT_MAX} }; unsigned int i; skiplist_node_t *iter; coord_t tmp; skiplist = skiplist_create( SKIPLIST_PROPERTY_NONE, 8, coord_compare, coord_fprintf, NULL ); if( !skiplist ) return -1; for( i = 0; i < sizeof(coords) / sizeof(coords[0]); ++i ) if( skiplist_insert( skiplist, (uintptr_t) &coords[i] ) ) return -1; /* Output skiplist for debugging purposes. */ if( skiplist_fprintf_filename( "pointers.dot", skiplist ) ) return -1; /* Confirm skiplist is in the correct order. */ tmp.x = 0; tmp.y = 0; for( iter = skiplist_begin( skiplist ); iter != skiplist_end(); iter = skiplist_next( iter ) ) { coord_t *cur = (coord_t *)skiplist_node_value( iter, NULL ); if( cur->x < tmp.x ) return -1; if( cur->x == tmp.x && cur->y < tmp.y ) return -1; tmp = *cur; } /* Confirm the skiplist contains what we expect. */ for( i = 0; i < sizeof(coords) / sizeof(coords[0]); ++i ) if( !skiplist_contains( skiplist, (uintptr_t) &coords[i], NULL ) ) return -1; /* If we use a different pointer to point to the same values the skiplist should skill contain it. */ tmp = coords[0]; if( !skiplist_contains( skiplist, (uintptr_t) &tmp, NULL ) ) return -1; /* Free resources. */ skiplist_destroy( skiplist ); return 0; }
static int __init skiplist_init(void) { int i; struct timeval start, end; struct skiplist *list; struct skipnode *node; int res = 0; int *key = kmalloc(N * sizeof(int), GFP_KERNEL); if (key == NULL) { printk("-ENOMEM\n"); return -1; } printk("Starting initialization...\n"); list = skiplist_create(); if (list == NULL) { printk("-ENOMEM\n"); return -1; } printk("Started initialization...\n"); printk("Test start!\n"); /* Test 01 */ printk("Test 01: adding and search %d nodes testing!\n", N); printk("Add %d nodes...\n", N); do_gettimeofday(&start); for (i = 0; i < N; i++) { int value = key[i] = i; skiplist_insert(list, key[i], value); } do_gettimeofday(&end); printk("time span:% ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000); #ifdef SKIPLIST_DEBUG skiplist_dump(list); #endif /* Search test */ printk("Now search %d node...\n", N); do_gettimeofday(&start); for (i = 0; i < N; i++) { struct skipnode *node = skiplist_search(list, key[i]); if (node != NULL) { #ifdef SKIPLIST_DEBUG printk("key:%d value:%d\n", node->key, node->value); #endif } else { printk("Not found:%d\n", key[i]); res = 1; break; } } do_gettimeofday(&end); printk("time span:% ldms\n", (end.tv_sec - start.tv_sec)*1000 + (end.tv_usec - start.tv_usec)/1000); if (res) { printk("Test 01: failed!\n"); goto out_clean; } else { printk("Test 01: success!\n"); } /* Test 02 */ printk("Test 02: search single node (%d/2) testing!\n", N); node = skiplist_search(list, N/2); if (node && node->value == N/2) { printk("Test 02: Success!\n"); } else { printk("Test 02: Failed!\n"); res = 1; goto out_clean; } /* Test 03 */ printk("Test 03: remove single node (%d/2) testing!\n", N); skiplist_remove(list, N/2); node = skiplist_search(list, N/2); if (!node) { printk("Test 03: Success!\n"); } else { printk("Test 03: Failed (key:%d)!\n", node->key); res = 1; goto out_clean; } /* Test 04 */ printk("Test 04: search single node equal or great than (%d/2) testing!\n", N); printk("Test 04: case 1: no equal node (%d/2) \n", N); node = skiplist_search_first_eq_big(list, N/2); if (!node || node->value != (N/2 + 1)) { printk("Test 04: Failed!\n"); res = 1; goto out_clean; } printk("Test 04: case 2: has equal node (%d/2 + 1) \n", N); node = skiplist_search_first_eq_big(list, N/2 + 1); if (node && node->value == (N/2 + 1)) { printk("Test 04: Success!\n"); } else { printk("Test 04: Failed!\n"); res = 1; goto out_clean; } /* Test 05 */ res = 0; printk("Test 05: remove all nodes\n"); for (i = 0; i < N; i++) { skiplist_remove(list, key[i]); } for (i = 0; i < N; i++) { node = skiplist_search(list, key[i]); if (node) { res = 1; break; } } if (res) printk("Test 05: Failed!\n"); else printk("Test 05: Success!\n"); #ifdef SKIPLIST_DEBUG skiplist_dump(list); #endif printk("End of Test.\n"); out_clean: skiplist_destroy(list); return 0; }
int main(int argc, char *argv[]) { int i; int tmp; int index1; int index2; int result; log_init(); if (argc > 1) { if (strcasecmp(argv[1], "multi") == 0 || strcmp(argv[1], "1") == 0) { skiplist_type = SKIPLIST_TYPE_MULTI; } } printf("skiplist type: %s\n", skiplist_type == SKIPLIST_TYPE_FLAT ? "flat" : "multi"); numbers = (int *)malloc(sizeof(int) * COUNT); srand(time(NULL)); for (i=0; i<COUNT; i++) { numbers[i] = i + 1; } for (i=0; i<COUNT; i++) { index1 = LAST_INDEX * (int64_t)rand() / (int64_t)RAND_MAX; index2 = LAST_INDEX * (int64_t)rand() / (int64_t)RAND_MAX; if (index1 == index2) { continue; } tmp = numbers[index1]; numbers[index1] = numbers[index2]; numbers[index2] = tmp; } fast_mblock_manager_init(); result = skiplist_init_ex(&sl, LEVEL_COUNT, compare_func, free_test_func, MIN_ALLOC_ONCE, skiplist_type); if (result != 0) { return result; } test_insert(); printf("\n"); fast_mblock_manager_stat_print(false); test_delete(); printf("\n"); assert(instance_count == 0); test_insert(); printf("\n"); skiplist_destroy(&sl); assert(instance_count == 0); test_stable_sort(); printf("pass OK\n"); return 0; }
static int test_stable_sort() { #define RECORDS 32 int i; int result; int index1; int index2; int delete_count; int total_delete_count; Skiplist sl; SkiplistIterator iterator; Record records[RECORDS]; Record *record; Record target; void *value; instance_count = 0; result = skiplist_init_ex(&sl, 12, compare_record, free_test_func, 128, skiplist_type); if (result != 0) { return result; } for (i=0; i<RECORDS; i++) { records[i].line = i + 1; records[i].key = i + 1; } for (i=0; i<RECORDS/4; i++) { index1 = (RECORDS - 1) * (int64_t)rand() / (int64_t)RAND_MAX; index2 = RECORDS - 1 - index1; if (index1 != index2) { records[index1].key = records[index2].key; } } for (i=0; i<RECORDS; i++) { if ((result=skiplist_insert(&sl, records + i)) != 0) { return result; } instance_count++; } assert(instance_count == RECORDS); for (i=0; i<RECORDS; i++) { value = skiplist_find(&sl, records + i); assert(value != NULL && ((Record *)value)->key == records[i].key); } i = 0; skiplist_iterator(&sl, &iterator); while ((value=skiplist_next(&iterator)) != NULL) { i++; record = (Record *)value; printf("%d => #%d\n", record->key, record->line); } assert(i==RECORDS); target.key = 10; target.line = 0; if (skiplist_find_all(&sl, &target, &iterator) == 0) { printf("found key: %d\n", target.key); } i = 0; while ((value=skiplist_next(&iterator)) != NULL) { i++; record = (Record *)value; printf("%d => #%d\n", record->key, record->line); } printf("found record count: %d\n", i); total_delete_count = 0; for (i=0; i<RECORDS; i++) { if ((result=skiplist_delete_all(&sl, records + i, &delete_count)) == 0) { total_delete_count += delete_count; } assert((result == 0 && delete_count > 0) || (result != 0 && delete_count == 0)); } assert(total_delete_count == RECORDS); assert(instance_count == 0); i = 0; skiplist_iterator(&sl, &iterator); while ((value=skiplist_next(&iterator)) != NULL) { i++; } assert(i == 0); skiplist_destroy(&sl); assert(instance_count == 0); return 0; }
int main(int argc, char** argv) { if (argc != 2) { printf("Usage: %s HPROF_FILE\n", argv[0]); exit(1); } FILE* hprof_fp = fopen(argv[1], "r"); die(hprof_fp == NULL, "File error"); hprof_header* header; char version[19]; u4 ident_size; int count = fread(version, sizeof(version), 1, hprof_fp); die(count != 1, "Unable to read hprof header"); count = fread(&ident_size, sizeof(u4), 1, hprof_fp); die(count != 1, "Unable to read hprof header"); int success = fseek(hprof_fp, sizeof(u8), SEEK_CUR); die(success != 0, "Could not seek forward in the file"); printf("Header: version=%s identsize=%ju\n", version, (uintmax_t) be32_to_native(ident_size)); // For now just reuse it hprof_record_header* record_header = calloc(1, sizeof(hprof_record_header)); hprof_heap_summary* heap_summary = calloc(1, sizeof(hprof_heap_summary)); // The string table is a skip list that should give us // O(n log n) insertion and O(log n) lookup, This is not as // good as a malloc'd array, but does not suffer from the // out of order issues that the string id's present us with skiplist_t *string_table = malloc(sizeof(skiplist_t)); skiplist_init(string_table); skiplist_set_cmp_fn(string_table, stringtable_cmp); skiplist_set_search_fn(string_table, stringtable_search); skiplist_set_destroy_fn(string_table, __destroy); skiplist_t *class_table = malloc(sizeof(skiplist_t)); skiplist_init(class_table); skiplist_set_cmp_fn(class_table, classtable_cmp); skiplist_set_search_fn(class_table, classtable_search); skiplist_set_destroy_fn(class_table, __destroy); while(1) { if (feof(hprof_fp)) { break; } //read_record_header(record_header, hprof_fp); funpack(hprof_fp, "bd>d>", &record_header->tag, &record_header->profiling_ms, &record_header->remaining_bytes); //printf("Tag=%ju\n", (uintmax_t) record_header->tag); switch(record_header->tag) { case UTF8: //printf("UTF8\n"); ; hprof_utf8 *utf8 = malloc(sizeof(hprof_utf8)); funpack(hprof_fp, "q>", &utf8->id); //fread(&utf8->id, sizeof(id), 1, hprof_fp); long bytes_remain = record_header->remaining_bytes - sizeof(id); // Awesome, hprof strings are utf8, this is good ! the only established // C type is char and its a byte wide :D utf8->num_chars = bytes_remain / sizeof(char); utf8->hprof_offset = ftell(hprof_fp); skiplist_insert(string_table, utf8); fseek(hprof_fp, bytes_remain, SEEK_CUR); break; case LOAD_CLASS: //printf("LOAD_CLASS\n"); ; hprof_load_class *class = malloc(sizeof(hprof_load_class)); fread(&class->serial_number, sizeof(u4), 1, hprof_fp); class->serial_number = be32_to_native(class->serial_number); fseek(hprof_fp, sizeof(id) + sizeof(u4), SEEK_CUR); fread(&class->name_id, sizeof(id), 1, hprof_fp); class->name_id = be64_to_native(class->name_id); skiplist_insert(class_table, class); //fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); break; case UNLOAD_CLASS: //printf("UNLOAD_CLASS\n"); fseek(hprof_fp, record_header->remaining_bytes, SEEK_CUR); break; case FRAME: //printf("FRAME\n"); // This is bad !!! If it is slow think about doing two complete passes to // make all the I/O as sequential as possible // This implementation is going to jump all over the hprof file ; long curr_pos = ftell(hprof_fp); id ids[4]; fread(&ids, sizeof(id), 4, hprof_fp); u4 class_serial_num; fread(&class_serial_num, sizeof(u4), 1, hprof_fp); class_serial_num = be32_to_native(class_serial_num); hprof_load_class *clazz = (hprof_load_class*) skiplist_search(class_table, &class_serial_num); i4 line_num; fread(&line_num, sizeof(i4), 1, hprof_fp); line_num = be32_to_native(line_num); char *method_name = read_string(be64_to_native(ids[1]), string_table, hprof_fp); char *method_sig = read_string(be64_to_native(ids[2]), string_table, hprof_fp); char *source_file = read_string(be64_to_native(ids[3]), string_table, hprof_fp); char *class_name = "<UNKNOWN_CLASS>"; if(clazz != NULL) { class_name = read_string(clazz->name_id, string_table, hprof_fp); } // SOMETIMES NULL //printf("%s\n", read_string(ids[3], string_table, hprof_fp)); class_name = (class_name == NULL) ? "<UNKNOWN_CLASS>" : class_name; method_name = (method_name == NULL) ? "<UNKNOWN_METHOD>" : method_name; method_sig = (method_sig == NULL) ? "<UNKNOWN_METHOD_SIG>" : method_sig; source_file = (source_file == NULL) ? "<UNKNOWN_SOURCE>" : source_file; switch(line_num) { case -1: printf("Class %s\n \tMethod=%s\n\tSource=%s @ <UNKNOWN>\n", class_name, method_name, source_file); break; case -2: printf("Class %s\n \tMethod=%s\n\tSource=%s @ <COMPILED_METHOD>\n", class_name, method_name, source_file); break; case -3: printf("Class %s\n \tMethod=%s\n\tSource=%s @ <NATIVE_METHOD>\n", class_name, method_name, source_file); break; default: printf("Class %s\n \tMethod=%s\n\tSource=%s @ %ji\n", class_name, method_name, source_file, (intmax_t) line_num); break; } break; case TRACE: //printf("TRACE\n"); ; hprof_stacktrace* stacktrace = calloc(1, sizeof(hprof_stacktrace)); fread(&stacktrace->serial_number, sizeof(u4), 1, hprof_fp); fread(&stacktrace->thread_number, sizeof(u4), 1, hprof_fp); fread(&stacktrace->number_frames, sizeof(u4), 1, hprof_fp); printf("StackTrace serial_num=%ju " "thread_num=%ju num_frames=%ju\n", (uintmax_t) be64_to_native(stacktrace->serial_number), (uintmax_t) be64_to_native(stacktrace->thread_number), (uintmax_t) be64_to_native(stacktrace->number_frames)); for (int i=0; i < be32_to_native(stacktrace->number_frames); i++) { id frame_id; fread(&frame_id, sizeof(id), 1, hprof_fp); printf("FrameID=%ju\n", (uintmax_t) be64_to_native(frame_id)); } free(stacktrace); break; case ALLOC_SITES: //printf("ALLOC_SITES\n"); fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); break; case HEAP_SUMMARY: //printf("HEAP SUMMARY\n"); fread(&heap_summary->live_bytes, sizeof(u4), 1, hprof_fp); fread(&heap_summary->live_instances, sizeof(u4), 1, hprof_fp); fread(&heap_summary->allocated_bytes, sizeof(u8), 1, hprof_fp); fread(&heap_summary->allocated_instances, sizeof(u8), 1, hprof_fp); printf("Heap summary:\n\tReachable bytes=%ju\n\t" "Reachable instances=%ju\n\t" "Allocated bytes=%ju\n\t" "Allocated instances=%ju\n", (uintmax_t) be32_to_native(heap_summary->live_bytes), (uintmax_t) be32_to_native(heap_summary->live_instances), (uintmax_t) be64_to_native(heap_summary->allocated_bytes), (uintmax_t) be64_to_native(heap_summary->allocated_instances)); break; case START_THREAD: //printf("START_THREAD\n"); fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); break; case END_THREAD: //printf("END_THREAD\n"); fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); break; case HEAP_DUMP: //printf("HEAP_DUMP\n"); fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); break; case CPU_SAMPLES: //printf("CPU_SAMPLES\n"); fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); break; case CONTROL_SETTINGS: //printf("CONTROL_SETTINGS\n"); fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); break; case HEAP_DUMP_SEGMENT: //printf("HEAP_DUMP_SEGMENT\n"); fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); break; case HEAP_DUMP_END: //printf("HEAP_DUMP_END\n"); fseek(hprof_fp, be32_to_native(record_header->remaining_bytes), SEEK_CUR); exit(1); break; default: printf("BANG\n"); exit(1); break; } //printf("%lu\n", ftell(hprof_fp)); } skiplist_destroy(string_table); free(string_table); skiplist_destroy(class_table); free(class_table); fclose(hprof_fp); return 0; }