Skip to content
Draft
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
114 changes: 114 additions & 0 deletions examples/common/utility/trace_collector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
Copyright (c) 2026 UXL Foundation Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef TRACE_COLLECTOR_H
#define TRACE_COLLECTOR_H

#include <chrono>
#include <fstream>
#include <mutex>
#include <algorithm>
#include <string>
#include <vector>
#include <utility>
#include <cstdio>

// Trace collection helper class
class TraceCollector {
private:
struct trace_event {
std::string name;
std::string phase; // "B" or "E"
int tid;
int64_t ts; // microseconds from start
};

std::chrono::time_point<std::chrono::steady_clock> start_time;
std::vector<trace_event> events;
std::mutex mtx;

public:
TraceCollector() : start_time(std::chrono::steady_clock::now()) {}

// Record a BEGIN or END event
void record_event(const std::string& name, const std::string& phase, int tid) {
auto now = std::chrono::steady_clock::now();
auto ts_us = std::chrono::duration_cast<std::chrono::microseconds>(now - start_time).count();
std::lock_guard<std::mutex> lock(mtx);
events.push_back({name, phase, tid, ts_us});
}

// Write trace to JSON file
void write_trace(const std::string& filename,
int pid,
const std::string& category,
const std::vector<std::pair<int, std::string>>& thread_names) {
// Sort events by timestamp
std::sort(events.begin(), events.end(),
[](const trace_event& a, const trace_event& b) { return a.ts < b.ts; });

// Write JSON Array Format
std::ofstream trace_file(filename);
trace_file << "[\n";

// Add thread name metadata events
for (size_t i = 0; i < thread_names.size(); ++i) {
int tid = thread_names[i].first;
const std::string& name = thread_names[i].second;
trace_file << " {\"name\": \"thread_name\", \"ph\": \"M\", \"pid\": " << pid
<< ", \"tid\": " << tid
<< ", \"args\": {\"name\": \"" << name << "\"}}";
if (i < thread_names.size() - 1 || !events.empty()) {
trace_file << ",";
}
trace_file << "\n";
}

// Write trace events
for (size_t i = 0; i < events.size(); ++i) {
const auto& e = events[i];
trace_file << " {\"name\": \"" << e.name << "\""
<< ", \"cat\": \"" << category << "\""
<< ", \"ph\": \"" << e.phase << "\""
<< ", \"ts\": " << e.ts
<< ", \"pid\": " << pid
<< ", \"tid\": " << e.tid
<< "}";
if (i < events.size() - 1) trace_file << ",";
trace_file << "\n";
}
trace_file << "]\n";
trace_file.close();
std::printf("Trace written to %s\n", filename.c_str());
}
};

// RAII class for scoped trace events
class ScopedTraceEvent {
TraceCollector& collector;
std::string name;
int tid;
public:
ScopedTraceEvent(TraceCollector& c, const std::string& n, int t)
: collector(c), name(n), tid(t) {
collector.record_event(name, "B", tid);
}
~ScopedTraceEvent() {
collector.record_event(name, "E", tid);
}
};

#endif // TRACE_COLLECTOR_H
9 changes: 9 additions & 0 deletions examples/graph/dining_philosophers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,18 @@ add_executable(dining_philosophers dining_philosophers.cpp)
target_link_libraries(dining_philosophers TBB::tbb Threads::Threads)
target_compile_options(dining_philosophers PRIVATE ${TBB_CXX_STD_FLAG})

add_executable(dining_philosophers_resource_limited dining_philosophers_resource_limited.cpp)

target_link_libraries(dining_philosophers_resource_limited TBB::tbb Threads::Threads)
target_compile_options(dining_philosophers_resource_limited PRIVATE ${TBB_CXX_STD_FLAG})

set(EXECUTABLE "$<TARGET_FILE:dining_philosophers>")
set(EXECUTABLE_RL "$<TARGET_FILE:dining_philosophers_resource_limited>")
set(ARGS auto 5)
set(LIGHT_ARGS auto 3)

add_execution_target(run_dining_philosophers dining_philosophers ${EXECUTABLE} "${ARGS}")
add_execution_target(light_test_dining_philosophers dining_philosophers ${EXECUTABLE} "${LIGHT_ARGS}")

add_execution_target(run_dining_philosophers_resource_limited dining_philosophers_resource_limited ${EXECUTABLE_RL} "${ARGS}")
add_execution_target(light_test_dining_philosophers_resource_limited dining_philosophers_resource_limited ${EXECUTABLE_RL} "${LIGHT_ARGS}")
Loading
Loading