Skip to content

Commit

Permalink
i#5538 memtrace seek, part 10: Top-level headers
Browse files Browse the repository at this point in the history
Adds cached values of the 5 top-level headers to the metrace_stream_t
interface and implements this for the readers.

Adds checks of these values to invariant_checker.

Adds a test with skipped instructions using the skip_unit_tests
checked-in trace.

Reverses the order of the initial 2 markers and the tid,pid pair sent
to the reader to avoid a 0 tid in tools.  I am surprised this hasn't
caused more problems and I thought it was already this fixed way.

Issue: #5538
  • Loading branch information
derekbruening committed Nov 15, 2022
1 parent d2ee068 commit ed7963b
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 31 deletions.
3 changes: 3 additions & 0 deletions api/docs/release.dox
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ Further non-compatibility-affecting changes include:
- Deprecated the drmemtrace analysis tool functions initialize() and
parallel_shard_init(), replacing them with initialize_stream() and
parallel_shard_init_stream(). The old versions will continue to work.
The stream interface passed to analysis tools provides tools with the
record and instruction ordinals along with the values of top-level
headers.
- Added #record_analyzer_t and #record_analysis_tool_t for analyzing the
sequence of #trace_entry_t exactly as present in a stored offline trace.

Expand Down
36 changes: 36 additions & 0 deletions clients/drcachesim/common/memtrace_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,42 @@ class memtrace_stream_t {
*/
virtual std::string
get_stream_name() const = 0;

/**
* Returns the #trace_version_t value from the #TRACE_MARKER_TYPE_VERSION record
* in the trace header.
*/
virtual uint64_t
get_version() const = 0;

/**
* Returns the OFFLINE_FILE_TYPE_* bitfields of type #offline_file_type_t
* identifying the architecture and other key high-level attributes of the trace
* from the #TRACE_MARKER_TYPE_FILETYPE record in the trace header.
*/
virtual uint64_t
get_filetype() const = 0;

/**
* Returns the cache line size from the #TRACE_MARKER_TYPE_CACHE_LINE_SIZE record in
* the trace header.
*/
virtual uint64_t
get_cache_line_size() const = 0;

/**
* Returns the chunk instruction count from the #TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT
* record in the trace header.
*/
virtual uint64_t
get_chunk_instr_count() const = 0;

/**
* Returns the page size from the #TRACE_MARKER_TYPE_PAGE_SIZE record in
* the trace header.
*/
virtual uint64_t
get_page_size() const = 0;
};

#endif /* _MEMTRACE_STREAM_H_ */
15 changes: 10 additions & 5 deletions clients/drcachesim/reader/file_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ template <typename T> class file_reader_t : public reader_t {
reader_t &
skip_instructions(uint64_t instruction_count) override
{
if (instruction_count == 0)
return *this;
if (input_files_.size() > 1) {
// TODO i#5538: For fast thread-interleaved (whether serial here or the
// forthcoming per-cpu iteration) we need to read in the schedule file(s)
Expand All @@ -121,10 +123,8 @@ template <typename T> class file_reader_t : public reader_t {
return reader_t::skip_instructions(instruction_count);
}
// If the user asks to skip from the very start, we still need to find the chunk
// count marker and drain the header queue.
// TODO i#5538: Record all of the header values until the first timestamp
// and present them as new memtrace_stream_t interfaces.
while (chunk_instr_count_ == 0) {
// count marker and drain the header queue and populate the stream header values.
while (chunk_instr_count_ == 0 || page_size_ == 0) {
input_entry_ = read_next_entry();
process_input_entry();
}
Expand Down Expand Up @@ -221,6 +221,7 @@ template <typename T> class file_reader_t : public reader_t {
return false;
}
// Read the meta entries until we hit the pid.
std::queue<trace_entry_t> marker_queue;
while (read_next_thread_entry(index_, &next, &thread_eof_[index_])) {
if (next.type == TRACE_TYPE_PID) {
// We assume the pid entry is the last, right before the timestamp.
Expand All @@ -229,7 +230,7 @@ template <typename T> class file_reader_t : public reader_t {
} else if (next.type == TRACE_TYPE_THREAD)
tids_[index_] = next;
else if (next.type == TRACE_TYPE_MARKER)
queues_[index_].push(next);
marker_queue.push(next);
else {
ERRMSG("Unexpected trace sequence for input file #%zu\n", index_);
return false;
Expand All @@ -241,6 +242,10 @@ template <typename T> class file_reader_t : public reader_t {
// the first entry.
queues_[index_].push(tids_[index_]);
queues_[index_].push(pid);
while (!marker_queue.empty()) {
queues_[index_].push(marker_queue.front());
marker_queue.pop();
}
}
index_ = input_files_.size();

Expand Down
25 changes: 11 additions & 14 deletions clients/drcachesim/reader/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,17 +248,7 @@ reader_t::process_input_entry()
break;
case TRACE_TYPE_MARKER:
cur_ref_.marker.type = (trace_type_t)input_entry_->type;
if (!online_ &&
(input_entry_->size == TRACE_MARKER_TYPE_VERSION ||
input_entry_->size == TRACE_MARKER_TYPE_FILETYPE)) {
// Do not carry over a prior thread on a thread switch to a
// first-time-seen new thread, whose tid entry is *after* these
// markers for offline traces.
cur_pid_ = 0;
cur_tid_ = 0;
} else {
assert(cur_tid_ != 0 && cur_pid_ != 0);
}
assert(cur_tid_ != 0 && cur_pid_ != 0);
cur_ref_.marker.pid = cur_pid_;
cur_ref_.marker.tid = cur_tid_;
cur_ref_.marker.marker_type = (trace_marker_type_t)input_entry_->size;
Expand All @@ -281,11 +271,18 @@ reader_t::process_input_entry()
}
if (cur_ref_.marker.marker_type == TRACE_MARKER_TYPE_TIMESTAMP)
last_timestamp_instr_count_ = cur_instr_count_;
else if (cur_ref_.marker.marker_type == TRACE_MARKER_TYPE_VERSION)
version_ = cur_ref_.marker.marker_value;
else if (cur_ref_.marker.marker_type == TRACE_MARKER_TYPE_FILETYPE) {
filetype_ = cur_ref_.marker.marker_value;
if (TESTANY(OFFLINE_FILE_TYPE_ENCODINGS, filetype_))
expect_no_encodings_ = false;
} else if (cur_ref_.marker.marker_type == TRACE_MARKER_TYPE_CACHE_LINE_SIZE)
cache_line_size_ = cur_ref_.marker.marker_value;
else if (cur_ref_.marker.marker_type == TRACE_MARKER_TYPE_PAGE_SIZE)
page_size_ = cur_ref_.marker.marker_value;
else if (cur_ref_.marker.marker_type == TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT)
chunk_instr_count_ = cur_ref_.marker.marker_value;
else if (cur_ref_.marker.marker_type == TRACE_MARKER_TYPE_FILETYPE &&
TESTANY(OFFLINE_FILE_TYPE_ENCODINGS, cur_ref_.marker.marker_value))
expect_no_encodings_ = false;
break;
default:
ERRMSG("Unknown trace entry type %d\n", input_entry_->type);
Expand Down
32 changes: 31 additions & 1 deletion clients/drcachesim/reader/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,31 @@ class reader_t : public std::iterator<std::input_iterator_tag, memref_t>,
{
return cur_instr_count_;
}
uint64_t
get_version() const override
{
return version_;
}
uint64_t
get_filetype() const override
{
return filetype_;
}
uint64_t
get_cache_line_size() const override
{
return cache_line_size_;
}
uint64_t
get_chunk_instr_count() const override
{
return chunk_instr_count_;
}
uint64_t
get_page_size() const override
{
return page_size_;
}

protected:
// This reads the next entry from the stream of entries from all threads interleaved
Expand Down Expand Up @@ -171,9 +196,14 @@ class reader_t : public std::iterator<std::input_iterator_tag, memref_t>,
const char *output_prefix_ = "[reader]";
uint64_t cur_ref_count_ = 0;
uint64_t cur_instr_count_ = 0;
uint64_t chunk_instr_count_ = 0; // Unchanging once set to non-zero.
uint64_t last_timestamp_instr_count_ = 0;
trace_entry_t *input_entry_ = nullptr;
// Remember top-level headers for the memtrace_stream_t interface.
uint64_t version_ = 0;
uint64_t filetype_ = 0;
uint64_t cache_line_size_ = 0;
uint64_t chunk_instr_count_ = 0; // Unchanging once set to non-zero.
uint64_t page_size_ = 0;

private:
struct encoding_info_t {
Expand Down
44 changes: 44 additions & 0 deletions clients/drcachesim/reader/record_file_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ class record_reader_t : public std::iterator<std::input_iterator_tag, trace_entr
++cur_ref_count_;
if (type_is_instr(static_cast<trace_type_t>(cur_entry_.type)))
++cur_instr_count_;
if (cur_entry_.type == TRACE_TYPE_MARKER) {
switch (cur_entry_.size) {
case TRACE_MARKER_TYPE_VERSION: version_ = cur_entry_.addr; break;
case TRACE_MARKER_TYPE_FILETYPE: filetype_ = cur_entry_.addr; break;
case TRACE_MARKER_TYPE_CACHE_LINE_SIZE:
cache_line_size_ = cur_entry_.addr;
break;
case TRACE_MARKER_TYPE_PAGE_SIZE: page_size_ = cur_entry_.addr; break;
case TRACE_MARKER_TYPE_CHUNK_INSTR_COUNT:
chunk_instr_count_ = cur_entry_.addr;
break;
}
}
}
return *this;
}
Expand All @@ -159,6 +172,31 @@ class record_reader_t : public std::iterator<std::input_iterator_tag, trace_entr
{
return cur_instr_count_;
}
uint64_t
get_version() const override
{
return version_;
}
uint64_t
get_filetype() const override
{
return filetype_;
}
uint64_t
get_cache_line_size() const override
{
return cache_line_size_;
}
uint64_t
get_chunk_instr_count() const override
{
return chunk_instr_count_;
}
uint64_t
get_page_size() const override
{
return page_size_;
}

virtual bool
operator==(const record_reader_t &rhs) const
Expand Down Expand Up @@ -199,6 +237,12 @@ class record_reader_t : public std::iterator<std::input_iterator_tag, trace_entr
private:
uint64_t cur_ref_count_ = 0;
uint64_t cur_instr_count_ = 0;
// Remember top-level headers for the memtrace_stream_t interface.
uint64_t version_ = 0;
uint64_t filetype_ = 0;
uint64_t cache_line_size_ = 0;
uint64_t chunk_instr_count_ = 0;
uint64_t page_size_ = 0;
};

/**
Expand Down
19 changes: 19 additions & 0 deletions clients/drcachesim/tests/offline-skip.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Output format:
<record#> <instr#>: T<tid> <record details>
------------------------------------------------------------
13 63: T3854659 <marker: timestamp 13312570674112304>
14 63: T3854659 <marker: tid 3854659 on core 3>
15 64: T3854659 ifetch 4 byte(s) @ 0x0000000000401028 48 83 eb 01 sub $0x0000000000000001 %rbx -> %rbx
16 65: T3854659 ifetch 4 byte(s) @ 0x000000000040102c 48 83 fb 00 cmp %rbx $0x0000000000000000
17 66: T3854659 ifetch 2 byte(s) @ 0x0000000000401030 75 d9 jnz $0x000000000040100b
18 67: T3854659 ifetch 7 byte(s) @ 0x000000000040100b 48 c7 c7 01 00 00 00 mov $0x0000000000000001 -> %rdi
19 68: T3854659 ifetch 8 byte(s) @ 0x0000000000401012 48 8d 34 25 00 20 40 lea 0x00402000 -> %rsi
19 68: T3854659 00
20 69: T3854659 ifetch 7 byte(s) @ 0x000000000040101a 48 c7 c2 0d 00 00 00 mov $0x000000000000000d -> %rdx
21 70: T3854659 ifetch 5 byte(s) @ 0x0000000000401021 b8 01 00 00 00 mov $0x00000001 -> %eax
22 71: T3854659 ifetch 2 byte(s) @ 0x0000000000401026 0f 05 syscall -> %rcx %r11
View tool results:
8 : total instructions

===========================================================================
Trace invariant checks passed
25 changes: 25 additions & 0 deletions clients/drcachesim/tests/view_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,31 @@ run_test_helper(view_t &view, const std::vector<memref_t> &memrefs)
{
return "";
}
uint64_t
get_version() const override
{
return 0;
}
uint64_t
get_filetype() const override
{
return 0;
}
uint64_t
get_cache_line_size() const override
{
return 0;
}
uint64_t
get_chunk_instr_count() const override
{
return 0;
}
uint64_t
get_page_size() const override
{
return 0;
}

private:
view_t &view_;
Expand Down
Loading

0 comments on commit ed7963b

Please sign in to comment.