/* Errors should be returned, not ignored! */ static void dump_profile(struct profile_node *root, int level, void (*cb)(const char *, void *), void *data) { int i; struct profile_node *p; void *iter; long retval; char *name, *value; iter = 0; do { retval = profile_find_node_relation(root, 0, &iter, &name, &value); if (retval) break; for (i=0; i < level; i++) cb("\t", data); if (need_double_quotes(value)) { cb(name, data); cb(" = ", data); output_quoted_string(value, cb, data); cb(EOL, data); } else { cb(name, data); cb(" = ", data); cb(value, data); cb(EOL, data); } } while (iter != 0); iter = 0; do { retval = profile_find_node_subsection(root, 0, &iter, &name, &p); if (retval) break; if (level == 0) { /* [xxx] */ cb("[", data); cb(name, data); cb("]", data); cb(profile_is_node_final(p) ? "*" : "", data); cb(EOL, data); dump_profile(p, level+1, cb, data); cb(EOL, data); } else { /* xxx = { ... } */ for (i=0; i < level; i++) cb("\t", data); cb(name, data); cb(" = {", data); cb(EOL, data); dump_profile(p, level+1, cb, data); for (i=0; i < level; i++) cb("\t", data); cb("}", data); cb(profile_is_node_final(p) ? "*" : "", data); cb(EOL, data); } } while (iter != 0); }
errcode_t profile_write_tree_file(struct profile_node *root, FILE *dstfile) { dump_profile(root, 0, dump_profile_to_file_cb, dstfile); return 0; }
int main() { Node root; Node longLivedTree; Node tempTree; long tStart, tFinish; long tElapsed; int i, d; double *array; #ifdef GC // GC_full_freq = 30; // GC_free_space_divisor = 16; // GC_enable_incremental(); #endif printf("Garbage Collector Test\n"); printf(" Live storage will peak at %d bytes.\n\n", 2 * sizeof(Node0) * TreeSize(kLongLivedTreeDepth) + sizeof(double) * kArraySize); printf(" Stretching memory with a binary tree of depth %d\n", kStretchTreeDepth); PrintDiagnostics(); # ifdef PROFIL init_profiling(); # endif tStart = currentTime(); // Stretch the memory space quickly tempTree = MakeTree(kStretchTreeDepth); # ifndef GC destroy_Node(tempTree); # endif tempTree = 0; // Create a long lived object printf(" Creating a long-lived binary tree of depth %d\n", kLongLivedTreeDepth); # ifndef GC longLivedTree = calloc(1, sizeof(Node0)); # else longLivedTree = GC_NEW(Node0); # endif Populate(kLongLivedTreeDepth, longLivedTree); ggggc_collectFull(); // Create long-lived array, filling half of it printf(" Creating a long-lived array of %d doubles\n", kArraySize); # ifndef GC array = malloc(kArraySize * sizeof(double)); # else # ifndef NO_PTRFREE array = GC_MALLOC_ATOMIC(sizeof(double) * kArraySize); # else array = GC_MALLOC(sizeof(double) * kArraySize); # endif # endif ggggc_collectFull(); for (i = 0; i < kArraySize/2; ++i) { array[i] = 1.0/i; } PrintDiagnostics(); for (d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) { TimeConstruction(d); } if (longLivedTree == 0 || array[1000] != 1.0/1000) fprintf(stderr, "Failed\n"); // fake reference to LongLivedTree // and array // to keep them from being optimized away tFinish = currentTime(); tElapsed = elapsedTime(tFinish-tStart); PrintDiagnostics(); printf("Completed in %d msec\n", tElapsed); # ifdef GC printf("Completed %d collections\n", GC_gc_no); printf("Heap size is %d\n", GC_get_heap_size()); # endif # ifdef PROFIL dump_profile(); # endif }
int main(int argc, char *argv[]) { bool need_exit = false; ptrace_context ptrace_ctx; program_params params; struct itimerval itv; struct proc_timer proc_time; calltree_node *root = NULL; g_progname = argv[0]; if (!parse_args(¶ms, argc, argv)) usage(); print_message("Reading symbols (list of function)"); init_fndescr(params.pid); if (params.just_print_symbols) { print_symbols(); free_fndescr(); exit(0); } if (!reset_process_time(&proc_time, params.pid, params.prof_method)) { free_fndescr(); errx(2, "Failed to retrieve process time"); } print_message("Attaching to process: %d", params.pid); memset(&ptrace_ctx, 0, sizeof(ptrace_ctx)); if (!trace_init(params.pid, &ptrace_ctx)) err(1, "Failed to initialize unwind internals"); signal(SIGCHLD, on_sigchld); if (ptrace(PTRACE_ATTACH, params.pid, 0, 0) == -1) { int saved_errno = errno; warn("ptrace(PTRACE_ATTACH) failed"); if (saved_errno == EPERM) { printf("You have to see NOTES section of `man crxprof' for workarounds.\n"); } exit(2); } if (do_wait(&ptrace_ctx, true) != WR_STOPPED) err(1, "Error occured while stopping the process"); if (ptrace(PTRACE_CONT, params.pid, 0, 0) < 0) err(1, "Error occured while stopping the process 2"); /* interval timer for snapshots */ itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = params.us_sleep; itv.it_value = itv.it_interval; signal(SIGALRM, on_sigalarm); if (setitimer(ITIMER_REAL, &itv, NULL) == -1) err(1, "setitimer failed"); print_message("Starting profile (interval %dms)", params.us_sleep / 1000); print_message("Press ^C once to show profile, twice to quit"); signal(SIGINT, on_sigint); /* drop first meter since it contains our preparations */ (void)get_process_dt(&proc_time); while(!need_exit) { waitres_t wres = WR_NOTHING; sleep(1); if (timer_alarmed) { uint64_t proc_dt = get_process_dt(&proc_time); bool need_prof = (params.prof_method == PROF_REALTIME); if (params.prof_method == PROF_CPUTIME) { char st = get_procstate(&ptrace_ctx); if (st == 'R') need_prof = true; } if (need_prof) { kill(params.pid, SIGSTOP); wres = do_wait(&ptrace_ctx, true); if (wres == WR_STOPPED) { int signo_cont = (ptrace_ctx.stop_signal == SIGSTOP) ? 0 : ptrace_ctx.stop_signal; if (!get_backtrace(&ptrace_ctx)) err(2, "failed to get backtrace of process"); /* continue tracee ASAP */ if (ptrace_verbose(PTRACE_CONT, params.pid, 0, signo_cont) < 0) err(1, "ptrace(PTRACE_CONT) failed"); ptrace_ctx.nsnaps++; if (fill_backtrace(proc_dt, &ptrace_ctx.stk, &root)) ptrace_ctx.nsnaps_accounted++; } } } if (wres != WR_FINISHED && wres != WR_NEED_DETACH) { wres = discard_wait(&ptrace_ctx); } if (sigint_caught_twice) { need_exit = true; } else if (sigint_caught || wres == WR_FINISHED || wres == WR_NEED_DETACH) { if (root) { print_message("%" PRIu64 " snapshot interrputs got (%" PRIu64 " dropped)", ptrace_ctx.nsnaps, ptrace_ctx.nsnaps - ptrace_ctx.nsnaps_accounted); visualize_profile(root, ¶ms.vprops); if (params.dumpfile) dump_profile(root, params.dumpfile); } else print_message("No symbolic snapshot caught yet!"); sigint_caught = false; } if (wres == WR_FINISHED || wres == WR_NEED_DETACH) { if (wres == WR_NEED_DETACH) (void)ptrace_verbose(PTRACE_DETACH, params.pid, 0, ptrace_ctx.stop_signal); need_exit = true; } } free_fndescr(); trace_free(&ptrace_ctx); if (root) calltree_destroy(root); return 0; }