/* perfexpert_util_filename_only */ int perfexpert_util_filename_only(const char *file, char **only) { char *local_copy = NULL, *token = NULL, *last = NULL, *str = NULL; if (NULL == file) { OUTPUT(("%s", _ERROR((char *)"file is NULL"))); return PERFEXPERT_ERROR; } PERFEXPERT_ALLOC(char, local_copy, (strlen(file) + 1)); strcpy(local_copy, file); token = strtok(local_copy, "/"); while (token = strtok(NULL, "/")) { last = token; } if (NULL == last) { *only = (char *)file; } else { PERFEXPERT_ALLOC(char, str, (strlen(last) + 1)); strcpy(str, last); *only = str; } PERFEXPERT_DEALLOC(local_copy); return PERFEXPERT_SUCCESS; }
/* perfexpert_database_disconnect */ int perfexpert_database_disconnect(sqlite3 *db) { char *my_file = NULL; sqlite3_backup *pBackup; sqlite3 *disk_db; /* Sanity check: only disconnect from a DB which is connected */ if (NULL == db) { return PERFEXPERT_SUCCESS; } /* Open the DB on disk */ PERFEXPERT_ALLOC(char, my_file, (strlen(PERFEXPERT_DB) + strlen(globals.workdir) + 2)); sprintf(my_file, "%s/%s", globals.workdir, PERFEXPERT_DB); if (SQLITE_OK != sqlite3_open(my_file, &disk_db)) { OUTPUT(("%s (%s), %s", _ERROR((char *)"openning output database"), my_file, sqlite3_errmsg(disk_db))); return PERFEXPERT_ERROR; } /* Copy the data from disk DB to in-memory DB */ pBackup = sqlite3_backup_init(disk_db, "main", db, "main"); if (pBackup) { (void)sqlite3_backup_step(pBackup, -1); (void)sqlite3_backup_finish(pBackup); } if (SQLITE_OK != sqlite3_errcode(db)) { OUTPUT(("%s (%s), %s", _ERROR((char *)"writing output database"), my_file, sqlite3_errmsg(disk_db))); PERFEXPERT_DEALLOC(my_file); return PERFEXPERT_ERROR; } PERFEXPERT_DEALLOC(my_file); sqlite3_close(db); sqlite3_close(disk_db); OUTPUT_VERBOSE((4, "disconnected from database (saved in %s/%s)", globals.workdir, PERFEXPERT_DB)); return PERFEXPERT_SUCCESS; }
/* perfexpert_util_remove_dir */ int perfexpert_util_remove_dir(const char *dir) { char *command = NULL; if (NULL == dir) { OUTPUT(("%s", _ERROR((char *)"dir is NULL"))); return PERFEXPERT_ERROR; } if (PERFEXPERT_SUCCESS != perfexpert_util_dir_exists(dir)) { return PERFEXPERT_ERROR; } PERFEXPERT_ALLOC(char, command, (strlen(dir) + 8)); sprintf(command, "rm -rf %s", dir); /* It is pretty ugly :-( */ if (-1 == system(command)) { PERFEXPERT_DEALLOC(command); return PERFEXPERT_ERROR; } PERFEXPERT_DEALLOC(command); return PERFEXPERT_SUCCESS; }
/* perfexpert_util_path_only */ int perfexpert_util_path_only(const char *file, char **path) { char *prog = NULL, *my_path = NULL, *resolved_path = NULL; if (NULL == file) { OUTPUT(("%s", _ERROR((char *)"file is NULL"))); return PERFEXPERT_ERROR; } if (PERFEXPERT_SUCCESS != perfexpert_util_filename_only(file, &prog)) { OUTPUT(("%s", _ERROR((char *)"unable to extract path"))); return PERFEXPERT_ERROR; } if (0 != strcmp(file, prog)) { PERFEXPERT_ALLOC(char, my_path, (strlen(file) - strlen(prog) + 1)); strncpy(my_path, file, (strlen(file) - strlen(prog))); if (NULL == (resolved_path = realpath(my_path, resolved_path))) { resolved_path = getcwd(NULL, 0); } PERFEXPERT_DEALLOC(my_path); } else {
/* lcpi_compute */ int lcpi_compute(profile_t *profile) { lcpi_t *hotspot_lcpi = NULL, *lcpi = NULL; procedure_t *hotspot = NULL; double *values = NULL; char **names = NULL; int count = 0; OUTPUT_VERBOSE((4, " %s", _CYAN("Calculating LCPI metrics"))); /* For each hotspot in this profile... */ hotspot = (procedure_t *)perfexpert_list_get_first(&(profile->hotspots)); while ((perfexpert_list_item_t *)hotspot != &(profile->hotspots.sentinel)) { OUTPUT_VERBOSE((8, " [%d] %s", hotspot->id, _YELLOW(hotspot->name))); /* For each LCPI definition */ for (lcpi = globals.lcpi_by_name; lcpi != NULL; lcpi = lcpi->hh_str.next) { /* Copy LCPI definitions into this hotspot LCPI hash */ PERFEXPERT_ALLOC(lcpi_t, hotspot_lcpi, sizeof(lcpi_t)); strcpy(hotspot_lcpi->name_md5, lcpi->name_md5); hotspot_lcpi->name = lcpi->name; hotspot_lcpi->value = lcpi->value; hotspot_lcpi->expression = lcpi->expression; /* Get the list of variables and their values */ evaluator_get_variables(hotspot_lcpi->expression, &names, &count); if (0 < count) { int i = 0; PERFEXPERT_ALLOC(double, values, (sizeof(double*) * count)); for (i = 0; i < count; i++) { metric_t *metric = NULL; char key_md5[33]; strcpy(key_md5, perfexpert_md5_string(names[i])); perfexpert_hash_find_str(hotspot->metrics_by_name, (char *)&key_md5, metric); if (NULL == metric) { perfexpert_hash_find_str(globals.machine_by_name, (char *)&key_md5, metric); if (NULL == metric) { values[i] = 0.0; } else { values[i] = metric->value; } } else { values[i] = metric->value; } } /* Evaluate the LCPI expression */ hotspot_lcpi->value = evaluator_evaluate( hotspot_lcpi->expression, count, names, values); PERFEXPERT_DEALLOC(values); } /* Add the LCPI to the hotspot's list of LCPIs */ perfexpert_hash_add_str(hotspot->lcpi_by_name, name_md5, hotspot_lcpi); OUTPUT_VERBOSE((10, " %s=[%g]", hotspot_lcpi->name, hotspot_lcpi->value)); } /* Move on */ hotspot = (procedure_t *)perfexpert_list_get_next(hotspot); }
// This function takes the output of running VTune and creates a report CSV file // The results of running VTune are in results_folder // The output of this function is in parse_file // The command it executes is like: // amplxe-cl -R hw-events -r results_folder -group-by=function -format=csv -report-output=parse_file -csv-delimiter=',' // amplxe-cl -report hw-events -group-by=function -group-by=module -group-by=source-file -group-by=source-line -group-by=thread -r results_folder -format=csv -report-output=parse-file -csv-delimiter=',' int create_report(char* results_folder, const char* parse_file) { struct timespec time_start, time_end, time_diff; char *argv[MAX_ARGUMENTS_COUNT]; int argc = 0, i, rc; char buffer[MAX_BUFFER_SIZE]; test_t test; argv[argc] = VTUNE_CL_BIN; argc++; argv[argc] = VTUNE_ACT_REPORT; argc++; argv[argc] = VTUNE_RPT_HW; argc++; argv[argc] = "-group-by=function"; argc++; argv[argc] = "-group-by=module"; argc++; argv[argc] = "-group-by=source-file"; argc++; argv[argc] = "-group-by=source-line"; argc++; if (globals.output_mode == HYBRID_OUTPUT) { argv[argc] = "-group-by=thread"; argc++; } argv[argc] = "-r"; argc++; argv[argc] = my_module_globals.res_folder; argc++; argv[argc] = "-format=csv"; argc++; strcpy(buffer, "-report-output="); strcat(buffer, parse_file); argv[argc] = buffer; argc++; argv[argc] = "-csv-delimiter=','"; argc++; argv[argc] = NULL; /* Not using OUTPUT_VERBOSEbecause I want only one line */ if (8 <= globals.verbose) { printf("%s %s", PROGRAM_PREFIX, _YELLOW("command line:")); for (i = 0; i < argc; i++) { printf(" %s", argv[i]); } printf("\n"); } /* The super-ninja test sctructure */ PERFEXPERT_ALLOC(char, test.output, (strlen(globals.moduledir) + 14)); sprintf(test.output, "%s/vtune.output", globals.moduledir); test.input = my_module_globals.inputfile; test.info = globals.program; clock_gettime(CLOCK_MONOTONIC, &time_start); /* fork_and_wait_and_pray */ rc = perfexpert_fork_and_wait(&test, (char **)argv); /* Evaluate results if required to */ if (PERFEXPERT_FALSE == my_module_globals.ignore_return_code) { switch (rc) { case PERFEXPERT_FAILURE: case PERFEXPERT_ERROR: OUTPUT(("%s (return code: %d) Usually, this means that an error" " happened during the program execution. To see the program" "'s output, check the content of this file: [%s]. If you " "want to PerfExpert ignore the return code next time you " "run this program, set the 'return-code' option for the " "Vtune module. See 'perfexpert -H vtune' for details.", _ERROR("the target program returned non-zero"), rc, test.output)); return PERFEXPERT_ERROR; case PERFEXPERT_SUCCESS: OUTPUT_VERBOSE((7, "[ %s ]", _BOLDGREEN("OK"))); break; default: break; } } /* Calculate and display runtime */ clock_gettime(CLOCK_MONOTONIC, &time_end); perfexpert_time_diff(&time_diff, &time_start, &time_end); OUTPUT((" [1/1] %lld.%.9ld seconds (includes measurement overhead)", (long long)time_diff.tv_sec, time_diff.tv_nsec)); PERFEXPERT_DEALLOC(test.output); /* Run the AFTER program */ if (NULL != my_module_globals.after[0]) { PERFEXPERT_ALLOC(char, test.output, (strlen(globals.moduledir) + 20)); sprintf(test.output, "%s/after.output", globals.moduledir); test.input = NULL; test.info = my_module_globals.after[0]; if (0 != perfexpert_fork_and_wait(&test, (char **)my_module_globals.after)) { OUTPUT(("%s", _RED("'after' command return non-zero"))); } PERFEXPERT_DEALLOC(test.output); }
/* perfexpert_database_update */ int perfexpert_database_update(char **file) { char *sys_ver = NULL, *my_ver = NULL, *my_db = NULL; int rc = PERFEXPERT_ERROR; FILE *ver_FP; PERFEXPERT_ALLOC(char, my_db, (strlen(getenv("HOME")) + strlen(PERFEXPERT_DB) + 3)); sprintf(my_db, "%s/.%s", getenv("HOME"), PERFEXPERT_DB); PERFEXPERT_ALLOC(char, sys_ver, (strlen(PERFEXPERT_ETCDIR) + strlen(PERFEXPERT_DB) + 10)); sprintf(sys_ver, "%s/%s.version", PERFEXPERT_ETCDIR, PERFEXPERT_DB); PERFEXPERT_ALLOC(char, my_ver, (strlen(getenv("HOME")) + strlen(PERFEXPERT_DB) + 11)); sprintf(my_ver, "%s/.%s.version", getenv("HOME"), PERFEXPERT_DB); /* System version */ if (NULL == (ver_FP = fopen(sys_ver, "r"))) { OUTPUT(("%s", _ERROR("unable to open sys DB version file"))); goto CLEAN_UP; } if (0 == fscanf(ver_FP, "%s", sys_ver)) { OUTPUT(("%s", _ERROR("unable to read sys DB version file"))); fclose(ver_FP); goto CLEAN_UP; } fclose(ver_FP); OUTPUT_VERBOSE((10, " system database version (%s)", sys_ver)); /* My version */ if ((PERFEXPERT_SUCCESS == perfexpert_util_file_exists(my_db)) && (PERFEXPERT_SUCCESS == perfexpert_util_file_exists(my_ver))) { OUTPUT_VERBOSE((10, " found local database (%s)", my_db)); if (NULL != (ver_FP = fopen(my_ver, "r"))) { if (0 == fscanf(ver_FP, "%s", my_ver)) { OUTPUT(("%s", _ERROR("unable to read user DB version file"))); fclose(ver_FP); goto CLEAN_UP; } } fclose(ver_FP); OUTPUT_VERBOSE((10, " local database version (%s)", my_ver)); } else { OUTPUT_VERBOSE((10, " local database not found, creating one")); } /* Compare */ if (atof(my_ver) > atof(sys_ver)) { OUTPUT((" local database is newer, reporting error")); goto CLEAN_UP; } else if (atof(my_ver) == atof(sys_ver)) { goto DATABASE_OK; } else { OUTPUT_VERBOSE((10, " system database is newer, updating")); } /* Setup a new database */ if (0 != system("perfexpert_setup_db.sh")) { OUTPUT(("%s", _ERROR("unable to setup PerfExpert database"))); goto CLEAN_UP; } sprintf(sys_ver, "%s/%s.version", PERFEXPERT_ETCDIR, PERFEXPERT_DB); sprintf(my_ver, "%s/.%s.version", getenv("HOME"), PERFEXPERT_DB); unlink(my_ver); if (PERFEXPERT_SUCCESS != perfexpert_util_file_copy(my_ver, sys_ver)) { goto CLEAN_UP; } DATABASE_OK: *file = my_db; rc = PERFEXPERT_SUCCESS; CLEAN_UP: PERFEXPERT_DEALLOC(my_ver); PERFEXPERT_DEALLOC(sys_ver); return rc; }
/* perfexpert_util_make_path (create directory tree like 'mkdir -p') */ int perfexpert_util_make_path(const char *path) { char *p = NULL, *npath = NULL; struct stat sb; int nmode = 0755; if (NULL == path) { OUTPUT(("%s", _ERROR((char *)"path is NULL"))); return PERFEXPERT_ERROR; } /* Check if we can create such directory */ if (0 == stat(path, &sb)) { if (0 == S_ISDIR(sb.st_mode)) { OUTPUT(("%s '%s'", _ERROR((char *)"file exists but is not a directory"), path)); return PERFEXPERT_ERROR; } if (chmod(path, nmode)) { OUTPUT(("%s %s: %s", _ERROR((char *)"system error"), path, strerror(errno))); return PERFEXPERT_ERROR; } return PERFEXPERT_SUCCESS; /* directory already exists */ } /* Save a copy, so we can write to it */ PERFEXPERT_ALLOC(char, npath, (strlen(path) + 1)); strncpy(npath, path, strlen(path)); /* Skip leading slashes */ p = npath; while ('/' == *p) { p++; } while (p = strchr(p, '/')) { *p = '\0'; if (0 != stat(npath, &sb)) { if (mkdir(npath, nmode)) { OUTPUT(("%s '%s' %s", _ERROR((char *)"cannot create directory"), npath, strerror(errno))); PERFEXPERT_DEALLOC(npath); return PERFEXPERT_ERROR; } } else if (0 == S_ISDIR(sb.st_mode)) { OUTPUT(("'%s': %s", npath, _ERROR((char *)"file exists but is not a directory"))); PERFEXPERT_DEALLOC(npath); return PERFEXPERT_ERROR; } *p++ = '/'; /* restore slash */ while ('/' == *p) { p++; } } /* Create the final directory component */ if (stat(npath, &sb) && mkdir(npath, nmode)) { /* This is not portable */ OUTPUT(("%s '%s' %s", _ERROR((char *)"cannot create directory"), npath, strerror(errno))); PERFEXPERT_DEALLOC(npath); return PERFEXPERT_ERROR; } PERFEXPERT_DEALLOC(npath); return PERFEXPERT_SUCCESS; }