diff --git a/libCacheSim/bin/traceAnalyzer/cli_parser.cpp b/libCacheSim/bin/traceAnalyzer/cli_parser.cpp index 588e4866..e3d62c80 100644 --- a/libCacheSim/bin/traceAnalyzer/cli_parser.cpp +++ b/libCacheSim/bin/traceAnalyzer/cli_parser.cpp @@ -74,11 +74,13 @@ static struct argp_option options[] = { "enable popularity analysis, output freq:cnt in dataname.popularity file, " "and prints the skewness to stdout and stat file", 3}, - {"popularityDacay", OPTION_ENABLE_POPULARITY_DECAY, NULL, + {"popularityDecay", OPTION_ENABLE_POPULARITY_DECAY, NULL, OPTION_ARG_OPTIONAL, "enable popularity decay analysis, this calculates popularity fade as a " "heatmap. It is an expensive analysis, enable only when needed.", 3}, + {"popularityDacay", OPTION_ENABLE_POPULARITY_DECAY, NULL, + OPTION_ARG_OPTIONAL | OPTION_HIDDEN, NULL, 3}, {"reuse", OPTION_ENABLE_REUSE, NULL, OPTION_ARG_OPTIONAL, "reuse analysis, output a reuse distribution (both real time and virtual " "time) in dataname.reuse file", @@ -110,8 +112,8 @@ static struct argp_option options[] = { {NULL, 0, NULL, 0, "common parameters:", 0}, - {"output", OPTION_OUTPUT_PATH, "", OPTION_ARG_OPTIONAL, "Output path", 8}, - {"verbose", OPTION_VERBOSE, NULL, OPTION_ARG_OPTIONAL, + {"output", OPTION_OUTPUT_PATH, "PATH", 0, "Output path prefix", 8}, + {"verbose", OPTION_VERBOSE, NULL, 0, "Produce verbose output", 8}, {NULL, 0, NULL, 0, NULL, 0}}; @@ -128,6 +130,10 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { arguments->trace_type_params = arg; break; case OPTION_OUTPUT_PATH: + if (arg == nullptr) { + argp_usage(state); + exit(1); + } strncpy(arguments->ofilepath, arg, OFILEPATH_LEN - 1); arguments->ofilepath[OFILEPATH_LEN - 1] = '\0'; break; @@ -149,6 +155,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { case OPTION_TRACK_N_HIT: arguments->analysis_param.track_n_hit = atoi(arg); break; + case OPTION_TRACK_N_POPULAR: + arguments->analysis_param.track_n_popular = atoi(arg); + break; case OPTION_ENABLE_ALL: arguments->analysis_option.req_rate = true; arguments->analysis_option.access_pattern = true; @@ -187,7 +196,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { break; case OPTION_VERBOSE: - arguments->verbose = is_true(arg) ? true : false; + arguments->verbose = true; break; case ARGP_KEY_ARG: if (state->arg_num >= N_ARGS) { @@ -236,7 +245,6 @@ static void init_arg(struct arguments *args) { args->trace_path = NULL; args->trace_type_params = NULL; - args->verbose = true; memset(args->ofilepath, 0, OFILEPATH_LEN); args->n_req = -1; args->verbose = false; diff --git a/libCacheSim/bin/traceAnalyzer/main.cpp b/libCacheSim/bin/traceAnalyzer/main.cpp index de7e4c6e..afa28994 100644 --- a/libCacheSim/bin/traceAnalyzer/main.cpp +++ b/libCacheSim/bin/traceAnalyzer/main.cpp @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) { args.reader, args.ofilepath, args.analysis_option, args.analysis_param); stat->run(); - ofstream ofs("traceStat", ios::out | ios::app); + ofstream ofs(args.ofilepath + string(".traceStat"), ios::out | ios::app); ofs << *stat << endl; ofs.close(); cout << *stat; diff --git a/libCacheSim/traceAnalyzer/analyzer.cpp b/libCacheSim/traceAnalyzer/analyzer.cpp index 2ec5a4a9..e7129bc5 100644 --- a/libCacheSim/traceAnalyzer/analyzer.cpp +++ b/libCacheSim/traceAnalyzer/analyzer.cpp @@ -89,8 +89,76 @@ void traceAnalyzer::TraceAnalyzer::cleanup() { void traceAnalyzer::TraceAnalyzer::run() { if (has_run_) return; + auto dump_outputs = [&]() { + ofstream ofs(output_path_ + ".stat", ios::out | ios::app); + ofs << gen_stat_str() << endl; + ofs.close(); + + if (ttl_stat_ != nullptr) { + ttl_stat_->dump(output_path_); + } + + if (req_rate_stat_ != nullptr) { + req_rate_stat_->dump(output_path_); + } + + if (reuse_stat_ != nullptr) { + reuse_stat_->dump(output_path_); + } + + if (size_stat_ != nullptr) { + size_stat_->dump(output_path_); + } + + if (access_stat_ != nullptr) { + access_stat_->dump(output_path_); + } + + if (popularity_stat_ != nullptr) { + popularity_stat_->dump(output_path_); + } + + if (popularity_decay_stat_ != nullptr) { + popularity_decay_stat_->dump(output_path_); + } + + if (prob_at_age_ != nullptr) { + prob_at_age_->dump(output_path_); + } + + if (lifetime_stat_ != nullptr) { + lifetime_stat_->dump(output_path_); + } + + if (create_future_reuse_ != nullptr) { + create_future_reuse_->dump(output_path_); + } + + // if (write_reuse_stat_ != nullptr) { + // write_reuse_stat_->dump(output_path_); + // } + + // if (write_future_reuse_stat_ != nullptr) { + // write_future_reuse_stat_->dump(output_path_); + // } + + if (scan_detector_ != nullptr) { + scan_detector_->dump(output_path_); + } + + has_run_ = true; + }; + request_t *req = new_request(); read_one_req(reader_, req); + if (!req->valid) { + start_ts_ = 0; + end_ts_ = 0; + post_processing(); + free_request(req); + dump_outputs(); + return; + } start_ts_ = req->clock_time; int32_t curr_time_window_idx = 0; int next_time_window_ts = time_window_; @@ -226,67 +294,35 @@ void traceAnalyzer::TraceAnalyzer::run() { free_request(req); - ofstream ofs("stat", ios::out | ios::app); - ofs << gen_stat_str() << endl; - ofs.close(); - - if (ttl_stat_ != nullptr) { - ttl_stat_->dump(output_path_); - } - - if (req_rate_stat_ != nullptr) { - req_rate_stat_->dump(output_path_); - } - - if (reuse_stat_ != nullptr) { - reuse_stat_->dump(output_path_); - } - - if (size_stat_ != nullptr) { - size_stat_->dump(output_path_); - } - - if (access_stat_ != nullptr) { - access_stat_->dump(output_path_); - } - - if (popularity_stat_ != nullptr) { - popularity_stat_->dump(output_path_); - } - - if (popularity_decay_stat_ != nullptr) { - popularity_decay_stat_->dump(output_path_); - } - - if (prob_at_age_ != nullptr) { - prob_at_age_->dump(output_path_); - } - - if (lifetime_stat_ != nullptr) { - lifetime_stat_->dump(output_path_); - } - - if (create_future_reuse_ != nullptr) { - create_future_reuse_->dump(output_path_); - } - - // if (write_reuse_stat_ != nullptr) { - // write_reuse_stat_->dump(output_path_); - // } - - // if (write_future_reuse_stat_ != nullptr) { - // write_future_reuse_stat_->dump(output_path_); - // } - - if (scan_detector_ != nullptr) { - scan_detector_->dump(output_path_); - } - - has_run_ = true; + dump_outputs(); } string traceAnalyzer::TraceAnalyzer::gen_stat_str() { stat_ss_.clear(); + if (n_req_ == 0) { + stat_ss_ << setprecision(4) << fixed << "dat: " << reader_->trace_path + << "\n" + << "number of requests: 0, number of objects: 0\n" + << "number of req GiB: 0.0000, number of obj GiB: 0.0000\n" + << "compulsory miss ratio (req/byte): 0.0000/0.0000\n" + << "object size weighted by req/obj: 0/0\n" + << "frequency mean: 0.0000\n" + << "time span: 0(0.0000 day)\n" + << "write: 0(0.0000), overwrite: 0(0.0000), del:0(0.0000)\n" + << "X-hit (number of obj accessed X times): "; + for (int i = 0; i < track_n_hit_; i++) { + stat_ss_ << "0(0.0000), "; + } + stat_ss_ << "\n"; + + stat_ss_ << "freq (fraction) of the most popular obj: "; + for (int i = 0; i < track_n_popular_; i++) { + stat_ss_ << "0(0.0000), "; + } + stat_ss_ << "\n"; + return stat_ss_.str(); + } + double cold_miss_ratio = (double)obj_map_.size() / (double)n_req_; double byte_cold_miss_ratio = (double)sum_obj_size_obj / (double)sum_obj_size_req; @@ -354,7 +390,7 @@ void traceAnalyzer::TraceAnalyzer::post_processing() { } } - if (option_.popularity) { + if (option_.popularity && !obj_map_.empty()) { popularity_stat_ = new Popularity(obj_map_); auto &sorted_freq = popularity_stat_->get_sorted_freq(); int n = std::min(track_n_popular_, (int)sorted_freq.size()); diff --git a/libCacheSim/traceReader/reader.c b/libCacheSim/traceReader/reader.c index 7705e57b..e3f9d14f 100644 --- a/libCacheSim/traceReader/reader.c +++ b/libCacheSim/traceReader/reader.c @@ -241,7 +241,8 @@ int read_one_req(reader_t *const reader, request_t *const req) { return 1; } - if (reader->cap_at_n_req > 1 && reader->n_read_req >= reader->cap_at_n_req) { + if (reader->cap_at_n_req >= 0 && + reader->n_read_req >= reader->cap_at_n_req) { DEBUG("read_one_req: processed %ld requests capped by the user\n", (long)reader->n_read_req); req->valid = false; diff --git a/scripts/run_traceAnalyzer.sh b/scripts/run_traceAnalyzer.sh index a1c545e8..4896dbce 100644 --- a/scripts/run_traceAnalyzer.sh +++ b/scripts/run_traceAnalyzer.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -euo pipefail + function help() { echo "Usage: $0 []" } @@ -9,20 +11,33 @@ if [ $# -lt 2 ]; then exit 1; fi -CURR_DIR=$(cd $(dirname $0); pwd) +CURR_DIR=$(cd "$(dirname "$0")"; pwd) +REPO_DIR=$(cd "${CURR_DIR}/.."; pwd) +TRACE_ANALYZER="${REPO_DIR}/_build/bin/traceAnalyzer" + +if [ ! -x "${TRACE_ANALYZER}" ]; then + echo "traceAnalyzer binary not found at ${TRACE_ANALYZER}; build the project first" >&2 + exit 1 +fi + tracepath=$1 trace_format=$2 -trace_format_parameters=${@:3} +shift 2 + +analyzer_args=("${tracepath}" "${trace_format}" "--common") +if [ $# -gt 0 ]; then + analyzer_args+=("--trace-type-params" "$*") +fi -./_build/bin/traceAnalyzer ${tracepath} ${trace_format} ${trace_format_parameters} --common +"${TRACE_ANALYZER}" "${analyzer_args[@]}" -dataname=$(basename ${tracepath}) -python3 ${CURR_DIR}/traceAnalysis/access_pattern.py ${dataname}.accessRtime -python3 ${CURR_DIR}/traceAnalysis/access_pattern.py ${dataname}.accessVtime -python3 ${CURR_DIR}/traceAnalysis/req_rate.py ${dataname}.reqRate_w300 -python3 ${CURR_DIR}/traceAnalysis/size.py ${dataname}.size -python3 ${CURR_DIR}/traceAnalysis/reuse.py ${dataname}.reuse -python3 ${CURR_DIR}/traceAnalysis/popularity.py ${dataname}.popularity +dataname=$(basename "${tracepath}") +python3 "${CURR_DIR}/traceAnalysis/access_pattern.py" "${dataname}.accessRtime" +python3 "${CURR_DIR}/traceAnalysis/access_pattern.py" "${dataname}.accessVtime" +python3 "${CURR_DIR}/traceAnalysis/req_rate.py" "${dataname}.reqRate_w300" +python3 "${CURR_DIR}/traceAnalysis/size.py" "${dataname}.size" +python3 "${CURR_DIR}/traceAnalysis/reuse.py" "${dataname}.reuse" +python3 "${CURR_DIR}/traceAnalysis/popularity.py" "${dataname}.popularity" # python3 ${CURR_DIR}/traceAnalysis/requestAge.py ${dataname}.requestAge # python3 ${CURR_DIR}/traceAnalysis/size_heatmap.py ${dataname}.sizeWindow_w300 # python3 ${CURR_DIR}/traceAnalysis/futureReuse.py ${dataname}.access