void benchmark::BenchRunner::RunAll(double elapsedTimeForOne) { perf_init(); std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "," << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n"; for (const auto &p: benchmarks()) { State state(p.first, elapsedTimeForOne); p.second(state); } perf_fini(); }
/* * The main function. */ int main(int argc, char *argv[]) { int ret = 1, debug_level = 0; FILE *log = NULL, *dump = NULL; char c; /* * The numatop requires some authorities to setup perf and increase the hard limit of * fd. So either the user runs as root or following condtions need to be satisfied. * * 1. Set "-1" in /proc/sys/kernel/perf_event_paranoid to let the non-root be able to * setup perf. e.g. * echo -1 > /proc/sys/kernel/perf_event_paranoid * * 2. The CAP_SYS_RESOURCE capability is required to user for increasing the hard * limit of fd. */ g_sortkey = SORT_KEY_CPU; g_precise = PRECISE_NORMAL; g_numatop_pid = getpid(); g_run_secs = TIME_NSEC_MAX; optind = 1; opterr = 0; /* * Parse command line arguments. */ while ((c = getopt(argc, argv, "d:l:o:f:t:hf:s:")) != EOF) { switch (c) { case 'h': print_usage(argv[0]); ret = 0; goto L_EXIT0; case 'l': debug_level = atoi(optarg); if ((debug_level < 0) || (debug_level > 2)) { stderr_print("Invalid log_level %d.\n", debug_level); print_usage(argv[0]); goto L_EXIT0; } break; case 'f': if (optarg == NULL) { stderr_print("Invalid output file.\n"); goto L_EXIT0; } if ((log = fopen(optarg, "w")) == NULL) { stderr_print("Cannot open '%s' for writing.\n", optarg); goto L_EXIT0; } break; case 's': if (optarg == NULL) { print_usage(argv[0]); goto L_EXIT0; } if (strcasecmp(optarg, "high") == 0) { g_precise = PRECISE_HIGH; break; } if (strcasecmp(optarg, "low") == 0) { g_precise = PRECISE_LOW; break; } if (strcasecmp(optarg, "normal") == 0) { g_precise = PRECISE_NORMAL; break; } stderr_print("Invalid sampling_precision '%s'.\n", optarg); print_usage(argv[0]); goto L_EXIT0; case 'd': if (optarg == NULL) { stderr_print("Invalid dump file.\n"); goto L_EXIT0; } if ((dump = fopen(optarg, "w")) == NULL) { stderr_print("Cannot open '%s' for dump.\n", optarg); goto L_EXIT0; } break; case 't': g_run_secs = atoi(optarg); if (g_run_secs <= 0) { stderr_print("Invalid run time %d.\n", g_run_secs); print_usage(argv[0]); goto L_EXIT0; } break; case ':': stderr_print("Missed argument for option %c.\n", optopt); print_usage(argv[0]); goto L_EXIT0; case '?': stderr_print("Unrecognized option %c.\n", optopt); print_usage(argv[0]); goto L_EXIT0; } } if (plat_detect() != 0) { stderr_print("CPU is not supported!\n"); ret = 2; goto L_EXIT0; } /* * It could be failed if user doesn't have authority. */ (void) ulimit_expand(PERF_FD_NUM); /* * Get the number of online cores in system. */ if ((g_ncpus = sysfs_online_ncpus()) == -1) { stderr_print("Platform is not supported " "(numatop supports up to %d CPUs)\n", NCPUS_MAX); goto L_EXIT0; } pagesize_init(); gettimeofday(&g_tvbase, 0); if (debug_init(debug_level, log) != 0) { goto L_EXIT1; } debug_print(NULL, 2, "Detected %d online CPU.\n", g_ncpus); log = NULL; sym_init(); if (dump_init(dump) != 0) { goto L_EXIT2; } dump = NULL; /* * Calculate how many nanoseconds for a TSC cycle. */ calibrate(); /* * Initialize for the "window-switching" table. */ switch_table_init(); if (proc_group_init() != 0) { goto L_EXIT3; } if (node_group_init() != 0) { stderr_print("The node/cpu number is out of range, \n" "numatop supports up to %d nodes and %d CPUs\n", NNODES_MAX, NCPUS_MAX); goto L_EXIT4; } if (disp_cons_ctl_init() != 0) { goto L_EXIT5; } /* * Catch signals from terminal. */ if ((signal(SIGINT, sigint_handler) == SIG_ERR) || (signal(SIGHUP, sigint_handler) == SIG_ERR) || (signal(SIGQUIT, sigint_handler) == SIG_ERR) || (signal(SIGTERM, sigint_handler) == SIG_ERR) || (signal(SIGPIPE, sigint_handler) == SIG_ERR)) { goto L_EXIT6; } /* * Initialize the perf sampling facility. */ if (perf_init() != 0) { debug_print(NULL, 2, "perf_init() is failed\n"); goto L_EXIT6; } /* * Initialize for display and create console thread & display thread. */ if (disp_init() != 0) { perf_fini(); goto L_EXIT6; } /* * Wait the disp thread to exit. The disp thread would * exit when user hits the hotkey 'Q' or press "CTRL+C". */ disp_dispthr_quit_wait(); /* * Notify cons thread to exit. */ disp_consthr_quit(); disp_fini(); stderr_print("NumaTOP is exiting ...\n"); (void) fflush(stdout); ret = 0; L_EXIT6: disp_cons_ctl_fini(); L_EXIT5: node_group_fini(); L_EXIT4: proc_group_fini(); L_EXIT3: dump_fini(); L_EXIT2: sym_fini(); debug_fini(); L_EXIT1: exit_msg_print(); L_EXIT0: if (dump != NULL) { (void) fclose(dump); } if (log != NULL) { (void) fclose(log); } return (ret); }
/* ARGSUSED */ static void * disp_handler(void *arg) { disp_flag_t flag; int status = 0; cmd_t cmd; boolean_t quit, pagelist_inited = B_FALSE; struct timespec timeout; uint64_t start_ms; int64_t diff_ms; /* * Wait cons thread to complete initialization. */ if (!consthr_init_wait()) { debug_print(NULL, 2, "Timeout for waiting cons thread to " "complete initialization\n"); /* * The cons thread should exit with error or startup failed, * disp thread stops running. */ goto L_EXIT; } /* * NumaTOP contains multiple windows. It uses double linked list * to link all of windows. */ page_list_init(); pagelist_inited = B_TRUE; timeout_set(&timeout, 0); start_ms = current_ms(); for (;;) { status = 0; (void) pthread_mutex_lock(&s_disp_ctl.mutex); flag = s_disp_ctl.flag; while (flag == DISP_FLAG_NONE) { status = pthread_cond_timedwait(&s_disp_ctl.cond, &s_disp_ctl.mutex, &timeout); flag = s_disp_ctl.flag; if (status == ETIMEDOUT) { break; } } if (flag == DISP_FLAG_CMD) { (void) memcpy(&cmd, &s_disp_ctl.cmd, sizeof (cmd)); } s_disp_ctl.flag = DISP_FLAG_NONE; (void) pthread_mutex_unlock(&s_disp_ctl.mutex); diff_ms = current_ms() - start_ms; if (g_run_secs <= diff_ms / MS_SEC) { g_run_secs = TIME_NSEC_MAX; debug_print(NULL, 2, "disp: it's time to exit\n"); continue; } if ((status == ETIMEDOUT) && (flag == DISP_FLAG_NONE)) { if (page_current_get() == NULL) { timeout_set(&timeout, DISP_DEFAULT_INTVAL); continue; } /* * Force a 'refresh' operation. */ CMD_ID_SET(&cmd, CMD_REFRESH_ID); cmd_execute(&cmd, NULL); timeout_set(&timeout, DISP_DEFAULT_INTVAL); continue; } switch (flag) { case DISP_FLAG_QUIT: debug_print(NULL, 2, "disp: received DISP_FLAG_QUIT\n"); goto L_EXIT; case DISP_FLAG_CMD: cmd_received(&cmd, &quit, &timeout); if (quit) { debug_print(NULL, 2, "disp thread received CMD_QUIT_ID\n"); goto L_EXIT; } break; case DISP_FLAG_PROFILING_DATA_READY: case DISP_FLAG_CALLCHAIN_DATA_READY: case DISP_FLAG_LL_DATA_READY: case DISP_FLAG_PQOS_CMT_READY: /* * Show the page. */ (void) page_next_execute(B_FALSE); timeout_set(&timeout, DISP_DEFAULT_INTVAL); break; case DISP_FLAG_PROFILING_DATA_FAIL: case DISP_FLAG_CALLCHAIN_DATA_FAIL: case DISP_FLAG_LL_DATA_FAIL: case DISP_FLAG_PQOS_CMT_FAIL: /* * Received the notification that the perf counting * was failed. */ debug_print(NULL, 2, "disp: profiling/callchain/LL data failed.\n"); disp_go_home(); break; case DISP_FLAG_SCROLLUP: /* * User hits the "UP" key. */ key_scroll(SCROLL_UP); if (status == ETIMEDOUT) { timeout_set(&timeout, DISP_DEFAULT_INTVAL); } break; case DISP_FLAG_SCROLLDOWN: /* * User hits the "DOWN" key. */ key_scroll(SCROLL_DOWN); if (status == ETIMEDOUT) { timeout_set(&timeout, DISP_DEFAULT_INTVAL); } break; case DISP_FLAG_SCROLLENTER: /* * User selects a scroll item and hit the "ENTER". */ scroll_enter(); if (status == ETIMEDOUT) { timeout_set(&timeout, DISP_DEFAULT_INTVAL); } break; default: break; } } L_EXIT: if (pagelist_inited) { page_list_fini(); } /* * Let the perf thread exit first. */ perf_fini(); debug_print(NULL, 2, "disp thread is exiting\n"); return (NULL); }