Skip to content

Commit

Permalink
i#5538 memtrace seek, part 10: Top-level headers (#5739)
Browse files Browse the repository at this point in the history
Adds cached values of the 5 top-level headers to the memtrace_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.
Long-term maybe we could swap in the file itself but this is complex
as it moves the version field.

Issue: #5538
  • Loading branch information
derekbruening authored Nov 17, 2022
1 parent 619c963 commit cd7bd0d
Show file tree
Hide file tree
Showing 13 changed files with 282 additions and 29 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_ */
2 changes: 1 addition & 1 deletion clients/drcachesim/common/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ droption_t<bytesize_t> op_chunk_instr_count(
// We do not support tiny chunks. We do not support disabling chunks with a 0
// value, to simplify testing: although we're still having to support generating
// non-zip files for !HAS_ZLIB/!HAS_ZIP!
bytesize_t(10),
bytesize_t(1000),
#ifdef X64
bytesize_t(1ULL << 63),
#else
Expand Down
19 changes: 14 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,10 @@ 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.
// XXX: We assume the page size is the final header; it is complex to wait for
// the timestamp as we don't want to read it yet.
while (page_size_ == 0) {
input_entry_ = read_next_entry();
process_input_entry();
}
Expand Down Expand Up @@ -221,6 +223,9 @@ template <typename T> class file_reader_t : public reader_t {
return false;
}
// Read the meta entries until we hit the pid.
// We want to pass the tid+pid to the reader *before* any markers,
// even though 2 markers preced the tid+pid in the file.
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 +234,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 +246,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
26 changes: 12 additions & 14 deletions clients/drcachesim/reader/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ reader_t::process_input_entry()
cur_pc_ = next_pc_;
cur_ref_.instr.addr = cur_pc_;
next_pc_ = cur_pc_ + cur_ref_.instr.size;
++cur_instr_count_;
// input_entry_->size stores the number of instrs in this bundle
assert(input_entry_->size <= sizeof(input_entry_->length));
if (bundle_idx_ == input_entry_->size)
Expand Down Expand Up @@ -249,17 +250,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 @@ -284,11 +275,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 @@ -145,6 +145,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 @@ -174,9 +199,14 @@ class reader_t : public std::iterator<std::input_iterator_tag, memref_t>,
uint64_t cur_ref_count_ = 0;
int64_t suppress_ref_count_ = -1;
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;
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
Binary file modified clients/drcachesim/tests/drmemtrace.allasm_x86_64.trace.zip
Binary file not shown.
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>
------------------------------------------------------------
0 63: T1384871 <marker: timestamp 13313186810097539>
0 63: T1384871 <marker: tid 1384871 on core 9>
92 64: T1384871 ifetch 4 byte(s) @ 0x0000000000401028 48 83 eb 01 sub $0x0000000000000001 %rbx -> %rbx
93 65: T1384871 ifetch 4 byte(s) @ 0x000000000040102c 48 83 fb 00 cmp %rbx $0x0000000000000000
94 66: T1384871 ifetch 2 byte(s) @ 0x0000000000401030 75 d9 jnz $0x000000000040100b
95 67: T1384871 ifetch 7 byte(s) @ 0x000000000040100b 48 c7 c7 01 00 00 00 mov $0x0000000000000001 -> %rdi
96 68: T1384871 ifetch 8 byte(s) @ 0x0000000000401012 48 8d 34 25 00 20 40 lea 0x00402000 -> %rsi
96 68: T1384871 00
97 69: T1384871 ifetch 7 byte(s) @ 0x000000000040101a 48 c7 c2 0d 00 00 00 mov $0x000000000000000d -> %rdx
98 70: T1384871 ifetch 5 byte(s) @ 0x0000000000401021 b8 01 00 00 00 mov $0x00000001 -> %eax
99 71: T1384871 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 cd7bd0d

Please sign in to comment.