#include "profiling_task.h" #include #include #include using namespace mx::tasking::profiling; ProfilingTask::ProfilingTask(mx::util::maybe_atomic &is_running, mx::tasking::Channel &channel, Timer::Connection &timer) : _is_running(is_running), _channel(channel), _timer (timer) { _idle_ranges.reserve(1 << 16); } mx::tasking::TaskResult ProfilingTask::execute(const std::uint16_t /*core_id*/, const std::uint16_t /*channel_id*/) { IdleRange range(_timer); while (this->_is_running && this->_channel.empty()) { this->_channel.fill(); } range.stop(); if (range.nanoseconds() > 10U) { this->_idle_ranges.emplace_back(std::move(range)); } if (this->_is_running) { return tasking::TaskResult::make_succeed(this); } return tasking::TaskResult::make_null(); } Profiler::~Profiler() { for (auto *task : this->_tasks) { delete task; } } void Profiler::profile(const std::string &profiling_output_file) { for (auto *task : this->_tasks) { delete task; } this->_tasks.clear(); this->_profiling_output_file.emplace(profiling_output_file); this->_start = std::chrono::steady_clock::now(); } void Profiler::profile(util::maybe_atomic &is_running, Channel &channel) { auto *task = new (memory::GlobalHeap::allocate_cache_line_aligned(sizeof(ProfilingTask))) ProfilingTask(is_running, channel, _timer); task->annotate(channel.id()); task->annotate(mx::tasking::priority::low); this->_tasks.push_back(task); mx::tasking::runtime::spawn(*task); } void Profiler::stop() { const auto end = std::chrono::time_point(std::chrono::microseconds(_timer.elapsed_ms())); const auto end_relative_nanoseconds = std::chrono::duration_cast(end - this->_start).count(); if (this->_profiling_output_file.has_value()) { auto output = nlohmann::json{}; for (auto *task : this->_tasks) { if (task != nullptr && task->idle_ranges().empty() == false) { nlohmann::json channel_output; channel_output["channel"] = task->annotated_channel(); nlohmann::json ranges{}; for (const auto &range : task->idle_ranges()) { const auto normalized = range.normalize(this->_start); auto normalized_json = nlohmann::json{}; normalized_json["s"] = std::get<0>(normalized); normalized_json["e"] = std::get<1>(normalized); ranges.push_back(std::move(normalized_json)); } channel_output["ranges"] = std::move(ranges); output.push_back(std::move(channel_output)); } } nlohmann::json end_output; end_output["end"] = end_relative_nanoseconds; output.push_back(std::move(end_output)); //std::ofstream out_file{this->_profiling_output_file.value()}; Genode::log(output.dump().c_str()); // dump to serial console for the moment } this->_profiling_output_file = std::nullopt; }