-
Notifications
You must be signed in to change notification settings - Fork 576
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
i#7216: noise generator basic structure #7283
base: master
Are you sure you want to change the base?
Changes from all commits
d426b35
f445f78
f70f5f5
3814809
cbe2176
9f1a73c
d99c991
e143e2f
db8aa84
03d79a2
2e70cd4
ae2d44f
c906bf7
d7a4365
6e21191
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -157,6 +157,9 @@ Further non-compatibility-affecting changes include: | |
- Allow v2p.textproto file in a trace directory. This file is present in public traces. | ||
- Allow v2p.textproto file to have one missing virtual_address field, which indicates | ||
virtual_address == 0x0. Necessary in case a trace accesses virtual address 0x0. | ||
- Added noise_generator_t scaffolding as a reader_t to produce synthetic trace records. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good to add "in the drmemtrace framework" to give context: remember that this list covers the entire DR release which includes various other tracing sample tools (and calls its internal superblocks "traces"). |
||
- Added -enable_noise_generator and -noise_generator_num_records as flags and scheduler | ||
options. | ||
|
||
************************************************** | ||
<hr> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -714,6 +714,18 @@ droption_t<std::string> | |
"Cache hierarchy configuration file", | ||
"The full path to the cache hierarchy configuration file."); | ||
|
||
droption_t<bool> | ||
op_enable_noise_generator(DROPTION_SCOPE_FRONTEND, "enable_noise_generator", false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But I might want multiple noise streams. These end up looking like software threads and the scheduler will interleave them with real traced threads, right? So to emulate a multi-tenant scenario we might want to add 100 different noise streams, 10 each for 10 different emulated processes and so each with different characteristics? Just trying to plan ahead. |
||
"Enables the noise generator.", | ||
"Enables the scheduler to interleave trace records " | ||
"with synthetic records."); | ||
|
||
droption_t<uint64_t> op_noise_generator_num_records( | ||
DROPTION_SCOPE_FRONTEND, "noise_generator_num_records", 0, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default is 0, but perhaps it should be the number of records of the longest thread of the trace we're adding noise to. Not sure if there is a way to do so at the moment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To your point about the longest thread: I would think most use cases want an infinite stream that doesn't end until all the other inputs have ended. Not sure how to do that...want a callback from the scheduler when it starts thinking about exiting? If we just make this the longest thread instruction count, that thread might have a bunch of wait syscalls and finish along with all the other regular threads and then the scheduler could sit there just running noise (modulo the exit early flag). Need a new scheduler feature to treat as infinite and not count toward exit calculations and just cut off when real inputs indicate exit? |
||
"Number of synthetic reords the noise generator produces.", | ||
"Determines the number of synthetic records produced by the noise generator " | ||
"excluding TRACE_TYPE_THREAD and TRACE_TYPE_PID."); | ||
|
||
// XXX: if we separate histogram + reuse_distance we should move this with them. | ||
droption_t<unsigned int> | ||
op_report_top(DROPTION_SCOPE_FRONTEND, "report_top", 10, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* ********************************************************** | ||
* Copyright (c) 2025 Google, Inc. All rights reserved. | ||
* **********************************************************/ | ||
|
||
/* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are met: | ||
* | ||
* * Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* * Redistributions in binary form must reproduce the above copyright notice, | ||
* this list of conditions and the following disclaimer in the documentation | ||
* and/or other materials provided with the distribution. | ||
* | ||
* * Neither the name of Google, Inc. nor the names of its contributors may be | ||
* used to endorse or promote products derived from this software without | ||
* specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE | ||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | ||
* DAMAGE. | ||
*/ | ||
|
||
#include <assert.h> | ||
#include "noise_generator.h" | ||
#include "trace_entry.h" | ||
#include "utils.h" | ||
|
||
namespace dynamorio { | ||
namespace drmemtrace { | ||
|
||
noise_generator_t::noise_generator_t() | ||
{ | ||
} | ||
|
||
noise_generator_t::noise_generator_t(uint64_t num_records_to_generate) | ||
: num_records_to_generate_(num_records_to_generate) | ||
{ | ||
} | ||
|
||
noise_generator_t::~noise_generator_t() | ||
{ | ||
} | ||
|
||
bool | ||
noise_generator_t::init() | ||
{ | ||
at_eof_ = false; | ||
++*this; | ||
return true; | ||
} | ||
|
||
std::string | ||
noise_generator_t::get_stream_name() const | ||
{ | ||
return "noise_generator"; | ||
} | ||
|
||
trace_entry_t * | ||
noise_generator_t::read_next_entry() | ||
{ | ||
if (num_records_to_generate_ == 0) { | ||
at_eof_ = true; | ||
return nullptr; | ||
} | ||
|
||
// Do not change the order for generating TRACE_TYPE_THREAD and TRACE_TYPE_PID. | ||
// The scheduler expects a tid first and then a pid. | ||
if (!marker_tid_generated_) { | ||
entry_ = { TRACE_TYPE_THREAD, | ||
sizeof(int), | ||
{ static_cast<addr_t>(IDLE_THREAD_ID) } }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But the idle thread means something special when computing context switch stats: I think this has to have its own unique TID (unique for each instance too). This should not be treated as idle: it should pretend to be a real thread. |
||
marker_tid_generated_ = true; | ||
return &entry_; | ||
} | ||
if (!marker_pid_generated_) { | ||
entry_ = { TRACE_TYPE_PID, | ||
sizeof(int), | ||
{ static_cast<addr_t>(INVALID_CPU_MARKER_VALUE) } }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should also have a valid but non-colliding value: wouldn't we want to pretend there's another PID here providing these synthetic records? |
||
marker_pid_generated_ = true; | ||
return &entry_; | ||
} | ||
|
||
// XXX i#7216: this is a temporary trace record that we use as a placeholder until the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be TODO (XXX is too soft: XXX means "nice to have" while this seems required). |
||
// logic to generate noise records is in place. | ||
entry_ = { TRACE_TYPE_READ, 4, { 0xdeadbeef } }; | ||
if (num_records_to_generate_ == 1) { | ||
entry_ = { TRACE_TYPE_THREAD_EXIT, | ||
sizeof(int), | ||
{ static_cast<addr_t>(IDLE_THREAD_ID) } }; | ||
} | ||
--num_records_to_generate_; | ||
|
||
return &entry_; | ||
} | ||
|
||
} // namespace drmemtrace | ||
} // namespace dynamorio |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* ********************************************************** | ||
* Copyright (c) 2025 Google, Inc. All rights reserved. | ||
* **********************************************************/ | ||
|
||
/* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are met: | ||
* | ||
* * Redistributions of source code must retain the above copyright notice, | ||
* this list of conditions and the following disclaimer. | ||
* | ||
* * Redistributions in binary form must reproduce the above copyright notice, | ||
* this list of conditions and the following disclaimer in the documentation | ||
* and/or other materials provided with the distribution. | ||
* | ||
* * Neither the name of Google, Inc. nor the names of its contributors may be | ||
* used to endorse or promote products derived from this software without | ||
* specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE | ||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | ||
* DAMAGE. | ||
*/ | ||
|
||
#ifndef _NOISE_GENERATOR_H_ | ||
#define _NOISE_GENERATOR_H_ 1 | ||
|
||
#include "reader.h" | ||
#include "../common/trace_entry.h" | ||
|
||
namespace dynamorio { | ||
namespace drmemtrace { | ||
|
||
/** | ||
* Generates synthetic #dynamorio::drmemtrace::memref_t trace entries in a single thread | ||
* and presents them via an iterator interface to the scheduler. | ||
*/ | ||
class noise_generator_t : public reader_t { | ||
public: | ||
noise_generator_t(); | ||
|
||
noise_generator_t(uint64_t num_records_to_generate); | ||
|
||
virtual ~noise_generator_t(); | ||
|
||
bool | ||
init() override; | ||
|
||
std::string | ||
get_stream_name() const override; | ||
|
||
protected: | ||
virtual trace_entry_t * | ||
read_next_entry() override; | ||
|
||
private: | ||
trace_entry_t entry_ = {}; | ||
bool marker_pid_generated_ = false; | ||
bool marker_tid_generated_ = false; | ||
// This counter does not count TRACE_TYPE_THREAD or TRACE_TYPE_PID. | ||
// The idea is that when we want to generate at least 1 record, tid and pid have to be | ||
// there as well, otherwise the scheduler will report an error. | ||
uint64_t num_records_to_generate_ = 0; | ||
}; | ||
|
||
} // namespace drmemtrace | ||
} // namespace dynamorio | ||
|
||
#endif /* _NOISE_GENERATOR_H_ */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,7 @@ | |
#include "mutex_dbg_owned.h" | ||
#include "reader.h" | ||
#include "record_file_reader.h" | ||
#include "noise_generator.h" | ||
#include "trace_entry.h" | ||
#ifdef HAS_LZ4 | ||
# include "lz4_file_reader.h" | ||
|
@@ -117,6 +118,13 @@ replay_file_checker_t::check(archive_istream_t *infile) | |
* Specializations for scheduler_tmpl_impl_t<reader_t>, aka scheduler_impl_t. | ||
*/ | ||
|
||
template <> | ||
std::unique_ptr<reader_t> | ||
scheduler_impl_tmpl_t<memref_t, reader_t>::get_noise_generator(uint64_t num_records) | ||
{ | ||
return std::unique_ptr<noise_generator_t>(new noise_generator_t(num_records)); | ||
} | ||
|
||
template <> | ||
std::unique_ptr<reader_t> | ||
scheduler_impl_tmpl_t<memref_t, reader_t>::get_default_reader() | ||
|
@@ -353,6 +361,15 @@ scheduler_impl_tmpl_t<memref_t, reader_t>::insert_switch_tid_pid(input_info_t &i | |
* record_scheduler_impl_t. | ||
*/ | ||
|
||
template <> | ||
std::unique_ptr<dynamorio::drmemtrace::record_reader_t> | ||
scheduler_impl_tmpl_t<trace_entry_t, record_reader_t>::get_noise_generator( | ||
uint64_t num_records) | ||
{ | ||
error_string_ = "Noise generator is not suppported for record_reader_t"; | ||
return std::unique_ptr<dynamorio::drmemtrace::record_reader_t>(); | ||
} | ||
|
||
template <> | ||
std::unique_ptr<dynamorio::drmemtrace::record_reader_t> | ||
scheduler_impl_tmpl_t<trace_entry_t, record_reader_t>::get_default_reader() | ||
|
@@ -629,6 +646,10 @@ scheduler_impl_tmpl_t<RecordType, ReaderType>::print_configuration() | |
options_.honor_infinite_timeouts); | ||
VPRINT(this, 1, " %-25s : %f\n", "exit_if_fraction_inputs_left", | ||
options_.exit_if_fraction_inputs_left); | ||
VPRINT(this, 1, " %-25s : %d\n", "enable_noise_generator", | ||
options_.enable_noise_generator); | ||
VPRINT(this, 1, " %-25s : %" PRIu64 "\n", "noise_generator_num_records", | ||
options_.noise_generator_num_records); | ||
} | ||
|
||
template <typename RecordType, typename ReaderType> | ||
|
@@ -705,6 +726,18 @@ scheduler_impl_tmpl_t<RecordType, ReaderType>::init( | |
{ | ||
options_ = std::move(options); | ||
verbosity_ = options_.verbosity; | ||
|
||
// Add noise generator reader to workload_inputs. | ||
if (options_.enable_noise_generator) { | ||
auto noise_generator = get_noise_generator(options_.noise_generator_num_records); | ||
auto noise_generator_end = get_noise_generator(0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps we should have a separate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. |
||
std::vector<typename sched_type_t::input_reader_t> readers; | ||
// Use a sentinel for the tid so the scheduler will use the memref record tid. | ||
readers.emplace_back(std::move(noise_generator), std::move(noise_generator_end), | ||
/* tid = */ INVALID_THREAD_ID); | ||
workload_inputs.emplace_back(std::move(readers)); | ||
} | ||
|
||
// workload_inputs is not const so we can std::move readers out of it. | ||
for (int workload_idx = 0; workload_idx < static_cast<int>(workload_inputs.size()); | ||
++workload_idx) { | ||
|
@@ -1514,6 +1547,11 @@ scheduler_impl_tmpl_t<RecordType, ReaderType>::get_initial_input_content( | |
// output stream(s). | ||
for (size_t i = 0; i < inputs_.size(); ++i) { | ||
input_info_t &input = inputs_[i]; | ||
// If the input is a noise generator, we don't want to read ahead to find | ||
// timestamp records, since we don't have any. | ||
if (dynamic_cast<noise_generator_t *>(input.reader.get()) != nullptr) | ||
continue; | ||
|
||
std::lock_guard<mutex_dbg_owned> lock(*input.lock); | ||
|
||
// If the input jumps to the middle immediately, do that now so we'll have | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Schedule stats tool results: | ||
Total counts: | ||
4 cores | ||
2 threads: W.*, W.* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really sure why only |
||
.* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the 11.3 list: the next version list is up above.