Skip to content
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

Bug/646 observer memory leaks #647

Merged
merged 7 commits into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/cosim/observer/time_series_observer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class time_series_observer : public time_series_provider
{
public:
/**
* Default constructor. Creates an unbuffered `time_series_observer`.
* Default constructor. Creates a buffered `time_series_observer`, with a fixed buffer size of 10000 samples for each observed variable.
*/
time_series_observer();

Expand Down
37 changes: 18 additions & 19 deletions src/cosim/observer/file_observer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ class file_observer::slave_value_writer

private:
template<typename T>
void write(const std::vector<T>& values)
void write(const std::vector<T>& values, std::stringstream& ss)
{
for (auto it = values.begin(); it != values.end(); ++it) {
ss_ << "," << *it;
ss << "," << *it;
}
}

Expand Down Expand Up @@ -190,6 +190,7 @@ class file_observer::slave_value_writer
void create_log_file()
{
std::string filename;
std::stringstream ss;
if (!timeStampedFileNames_) {
filename = observable_->name().append(".csv");
} else {
Expand All @@ -205,46 +206,45 @@ class file_observer::slave_value_writer
throw std::runtime_error("Failed to open file stream for logging");
}

ss_ << "Time,StepCount";
ss << "Time,StepCount";

for (const auto& vd : realVars_) {
ss_ << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
ss << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
}
for (const auto& vd : intVars_) {
ss_ << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
ss << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
}
for (const auto& vd : boolVars_) {
ss_ << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
ss << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
}
for (const auto& vd : stringVars_) {
ss_ << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
ss << "," << vd.name << " [" << vd.reference << " " << vd.type << " " << vd.causality << "]";
}

ss_ << std::endl;
ss << std::endl;

if (fsw_.is_open()) {
fsw_ << ss_.rdbuf();
fsw_ << ss.rdbuf();
}
}

void persist()
{
ss_.clear();

std::stringstream ss;
if (fsw_.is_open()) {

for (const auto& [stepCount, times] : timeSamples_) {
ss_ << times << "," << stepCount;
ss << times << "," << stepCount;

if (realSamples_.count(stepCount)) write<double>(realSamples_[stepCount]);
if (intSamples_.count(stepCount)) write<int>(intSamples_[stepCount]);
if (boolSamples_.count(stepCount)) write<bool>(boolSamples_[stepCount]);
if (stringSamples_.count(stepCount)) write<std::string_view>(stringSamples_[stepCount]);
if (realSamples_.count(stepCount)) write<double>(realSamples_[stepCount], ss);
if (intSamples_.count(stepCount)) write<int>(intSamples_[stepCount], ss);
if (boolSamples_.count(stepCount)) write<bool>(boolSamples_[stepCount], ss);
if (stringSamples_.count(stepCount)) write<std::string_view>(stringSamples_[stepCount], ss);

ss_ << std::endl;
ss << std::endl;
}

fsw_ << ss_.rdbuf();
fsw_ << ss.rdbuf();
}

realSamples_.clear();
Expand All @@ -267,7 +267,6 @@ class file_observer::slave_value_writer
cosim::filesystem::path logDir_;
size_t decimationFactor_ = 1;
std::ofstream fsw_;
std::stringstream ss_;
std::atomic<bool> recording_ = true;
std::mutex mutex_;
bool timeStampedFileNames_ = true;
Expand Down
15 changes: 9 additions & 6 deletions src/cosim/observer/time_series_observer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ size_t get_samples(
template<typename T>
void adjustIfFull(std::map<step_number, T>& buffer, size_t maxSize)
{
if (maxSize <= 0) {
return;
}
if (buffer.size() > maxSize) {
buffer.erase(buffer.begin());
}
Expand Down Expand Up @@ -191,7 +188,7 @@ class time_series_observer::single_slave_observer
steps[1] = lastStep;
}

const std::map<step_number, double> get_real_samples_map(value_reference idx)
std::map<step_number, double> get_real_samples_map(value_reference idx)
{
std::lock_guard<std::mutex> lock(lock_);
return realSamples_.at(idx);
Expand All @@ -207,13 +204,19 @@ class time_series_observer::single_slave_observer
};

time_series_observer::time_series_observer()
: bufSize_(0)
: bufSize_(10000)
{
}

time_series_observer::time_series_observer(size_t bufferSize)
: bufSize_(bufferSize)
{
if (bufferSize > 0) {
bufSize_ = bufferSize;
} else {
std::ostringstream oss;
oss << "Can't define an observer with buffer size " << bufferSize << ", minimum allowed buffer size is 1.";
throw std::invalid_argument(oss.str());
}
}

void time_series_observer::simulator_added(simulator_index index, observable* simulator, time_point currentTime)
Expand Down