diff --git a/clients/drcachesim/tests/core_sharded_test.cpp b/clients/drcachesim/tests/core_sharded_test.cpp index 2345c3c9f18..6446f65f834 100644 --- a/clients/drcachesim/tests/core_sharded_test.cpp +++ b/clients/drcachesim/tests/core_sharded_test.cpp @@ -112,6 +112,9 @@ Total counts: 638938 total .* (.|\n)* Core [0-9] counts: +(.|\n)* + *[0-9]+ threads +(.|\n)* )DELIM"))); std::regex count("Core"); assert(std::distance(std::sregex_iterator(output.begin(), output.end(), count), @@ -128,6 +131,9 @@ Total counts: 638938 total .* (.|\n)* Core [0-9] counts: +(.|\n)* + *[0-9]+ threads +(.|\n)* )DELIM"))); std::regex count("Core"); assert(std::distance(std::sregex_iterator(output.begin(), output.end(), count), @@ -155,6 +161,9 @@ Total counts: 638938 total \(fetched\) instructions (.|\n)* Core [0-9] counts: +(.|\n)* + *[0-9]+ threads +(.|\n)* )DELIM"))); std::regex count("Core"); assert(std::distance(std::sregex_iterator(output.begin(), output.end(), count), @@ -178,27 +187,44 @@ Core [0-9] counts: assert(std::regex_search(output, std::regex(R"DELIM(Basic counts tool results: Total counts: 638938 total \(fetched\) instructions +(.|\n)* + 8 total threads (.|\n)* Core 5 counts: 175765 \(fetched\) instructions +(.|\n)* + 2 threads (.|\n)* Core 9 counts: 87891 \(fetched\) instructions +(.|\n)* + 1 threads (.|\n)* Core 0 counts: 87884 \(fetched\) instructions +(.|\n)* + 1 threads (.|\n)* Core 10? counts: 87875 \(fetched\) instructions +(.|\n)* + 1 threads (.|\n)* Core 10? counts: 87875 \(fetched\) instructions +(.|\n)* + 1 threads (.|\n)* Core 11 counts: 82508 \(fetched\) instructions +(.|\n)* + 1 threads (.|\n)* Core 8 counts: 29140 \(fetched\) instructions +(.|\n)* + 1 threads +(.|\n)* )DELIM"))); } { @@ -216,6 +242,9 @@ Total counts: 638938 total \(fetched\) instructions (.|\n)* Core .* +(.|\n)* + *[0-9]+ threads +(.|\n)* )DELIM"))); const char *replay_args[] = { "", "-core_sharded", "-simulator_type", "basic_counts", diff --git a/clients/drcachesim/tools/basic_counts.cpp b/clients/drcachesim/tools/basic_counts.cpp index de610bebfc0..103f04bdda2 100644 --- a/clients/drcachesim/tools/basic_counts.cpp +++ b/clients/drcachesim/tools/basic_counts.cpp @@ -57,6 +57,7 @@ namespace dynamorio { namespace drmemtrace { const std::string basic_counts_t::TOOL_NAME = "Basic counts tool"; +const char *const basic_counts_t::TOTAL_COUNT_PREFIX = " total"; analysis_tool_t * basic_counts_tool_create(unsigned int verbose) @@ -128,6 +129,10 @@ basic_counts_t::parallel_shard_memref(void *shard_data, const memref_t &memref) { per_shard_t *per_shard = reinterpret_cast(shard_data); counters_t *counters = &per_shard->counters[per_shard->counters.size() - 1]; + if (memref.instr.tid != per_shard->last_tid_) { + counters->unique_threads.insert(memref.instr.tid); + per_shard->last_tid_ = memref.instr.tid; + } if (type_is_instr(memref.instr.type)) { ++counters->instrs; if (TESTANY(OFFLINE_FILE_TYPE_KERNEL_SYSCALLS, per_shard->filetype_)) { @@ -258,8 +263,8 @@ basic_counts_t::cmp_threads(const std::pair &l, } void -basic_counts_t::print_counters(const counters_t &counters, int64_t num_threads, - const std::string &prefix, bool for_kernel_trace) +basic_counts_t::print_counters(const counters_t &counters, const std::string &prefix, + bool for_kernel_trace) { std::cerr << std::setw(12) << counters.instrs << prefix << " (fetched) instructions\n"; @@ -282,8 +287,10 @@ basic_counts_t::print_counters(const counters_t &counters, int64_t num_threads, << " icache flushes\n"; std::cerr << std::setw(12) << counters.dcache_flushes << prefix << " dcache flushes\n"; - if (num_threads > 0) { - std::cerr << std::setw(12) << num_threads << prefix << " threads\n"; + if (shard_type_ != SHARD_BY_THREAD || counters.unique_threads.size() > 1 || + prefix == TOTAL_COUNT_PREFIX) { + std::cerr << std::setw(12) << counters.unique_threads.size() << prefix + << " threads\n"; } std::cerr << std::setw(12) << counters.sched_markers << prefix << " scheduling markers\n"; @@ -331,7 +338,7 @@ basic_counts_t::print_results() total.shard_count = shard_map_.size(); std::cerr << TOOL_NAME << " results:\n"; std::cerr << "Total counts:\n"; - print_counters(total, shard_map_.size(), " total", for_kernel_trace); + print_counters(total, TOTAL_COUNT_PREFIX, for_kernel_trace); if (num_windows > 1) { std::cerr << "Total windows: " << num_windows << "\n"; @@ -339,7 +346,7 @@ basic_counts_t::print_results() std::cerr << "Window #" << i << ":\n"; for (const auto &shard : shard_map_) { if (shard.second->counters.size() > i) { - print_counters(shard.second->counters[i], 0, " window", + print_counters(shard.second->counters[i], " window", for_kernel_trace); } } @@ -355,7 +362,7 @@ basic_counts_t::print_results() std::cerr << "Thread " << keyvals.second->tid << " counts:\n"; else std::cerr << "Core " << keyvals.second->core << " counts:\n"; - print_counters(keyvals.second->counters[0], 0, "", for_kernel_trace); + print_counters(keyvals.second->counters[0], "", for_kernel_trace); } // TODO i#3599: also print thread-per-window stats. @@ -448,7 +455,7 @@ basic_counts_t::print_interval_results( << snapshot->interval_end_timestamp << ":\n"; counters_t diff = snapshot->counters; diff -= last; - print_counters(diff, 0, " interval delta"); + print_counters(diff, " interval delta"); last = snapshot->counters; if (knob_verbose_ > 0) { if (snapshot->instr_count_cumulative != diff --git a/clients/drcachesim/tools/basic_counts.h b/clients/drcachesim/tools/basic_counts.h index 51c7e9c6157..a4247abf2ba 100644 --- a/clients/drcachesim/tools/basic_counts.h +++ b/clients/drcachesim/tools/basic_counts.h @@ -115,10 +115,10 @@ class basic_counts_t : public analysis_tool_t { dcache_flushes += rhs.dcache_flushes; encodings += rhs.encodings; if (track_unique_pc_addrs) { - for (const uint64_t addr : rhs.unique_pc_addrs) { - unique_pc_addrs.insert(addr); - } + unique_pc_addrs.insert(rhs.unique_pc_addrs.begin(), + rhs.unique_pc_addrs.end()); } + unique_threads.insert(rhs.unique_threads.begin(), rhs.unique_threads.end()); return *this; } counters_t & @@ -148,6 +148,9 @@ class basic_counts_t : public analysis_tool_t { for (const uint64_t addr : rhs.unique_pc_addrs) { unique_pc_addrs.erase(addr); } + for (const memref_tid_t tid : rhs.unique_threads) { + unique_threads.erase(tid); + } return *this; } bool @@ -172,7 +175,8 @@ class basic_counts_t : public analysis_tool_t { other_markers == rhs.other_markers && icache_flushes == rhs.icache_flushes && dcache_flushes == rhs.dcache_flushes && encodings == rhs.encodings && - unique_pc_addrs == rhs.unique_pc_addrs; + unique_pc_addrs == rhs.unique_pc_addrs && + unique_threads == rhs.unique_threads; } int64_t instrs = 0; int64_t instrs_nofetch = 0; @@ -198,6 +202,7 @@ class basic_counts_t : public analysis_tool_t { // we use encoding_is_new as a proxy. int64_t encodings = 0; std::unordered_set unique_pc_addrs; + std::unordered_set unique_threads; // Metadata for the counts. These are not used for the equality, increment, // or decrement operation, and must be set explicitly. @@ -239,6 +244,7 @@ class basic_counts_t : public analysis_tool_t { std::string error; intptr_t last_window = -1; intptr_t filetype_ = -1; + memref_tid_t last_tid_ = INVALID_THREAD_ID; /* Indicates whether we're currently in the kernel region of the trace, which * means we've seen a TRACE_MARKER_TYPE_SYSCALL_TRACE_START without its matching * TRACE_MARKER_TYPE_SYSCALL_TRACE_STOP. @@ -262,9 +268,9 @@ class basic_counts_t : public analysis_tool_t { static bool cmp_threads(const std::pair &l, const std::pair &r); - static void - print_counters(const counters_t &counters, int64_t num_threads, - const std::string &prefix, bool for_kernel_trace = false); + void + print_counters(const counters_t &counters, const std::string &prefix, + bool for_kernel_trace = false); void compute_shard_interval_result(per_shard_t *shard, uint64_t interval_id); @@ -275,6 +281,7 @@ class basic_counts_t : public analysis_tool_t { std::mutex shard_map_mutex_; unsigned int knob_verbose_; static const std::string TOOL_NAME; + static const char *const TOTAL_COUNT_PREFIX; shard_type_t shard_type_ = SHARD_BY_THREAD; memtrace_stream_t *serial_stream_ = nullptr; };