Skip to content
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
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ CM11_proj/tmp.obj

TODO.md

# User-provided proprietary scenarios - track folder structure but ignore contents
/tests/UserScenarios/*
!/tests/UserScenarios/.gitkeep
!/tests/UserScenarios/README.md

# Active debug configuration (per-worktree, for VS debugging)
/TrafficLayer/.active_config

**/nul

.claude/
147 changes: 147 additions & 0 deletions CommonLib/PerformanceTimer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#ifndef PERFORMANCE_TIMER_H
#define PERFORMANCE_TIMER_H

#include <chrono>
#include <string>
#include <fstream>
#include <unordered_map>
#include <iomanip>
#include <ctime>
#include <cstdarg>

// Toggle performance timing
// Define ENABLE_PERF_TIMING before including this header to enable timing
// (see VirEnvHelper.cpp for example)

#ifdef ENABLE_PERF_TIMING

class PerformanceTimer {
private:
// File stream for logging (static = shared)
static std::ofstream perfLogFile;
static std::string perfLogPath;

// Tic/toc storage (map label -> start time)
static std::unordered_map<std::string, std::chrono::high_resolution_clock::time_point> ticMap;

public:
// Initialize performance logging (call once at startup)
static void init(const std::string& logPath = "RealSimPerf.log") {
if (!perfLogFile.is_open()) {
perfLogPath = logPath;
// Use std::ios::out to truncate file (reset on each init)
perfLogFile.open(perfLogPath, std::ios::out | std::ios::trunc);

// Write session header with timestamp
if (perfLogFile.is_open()) {
auto now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
perfLogFile << "=============================================" << std::endl;
perfLogFile << "Performance Log Session: " << std::ctime(&now_c);
perfLogFile << "=============================================" << std::endl;
perfLogFile.flush();
}
}
}

// Start timing
static void tic(const std::string& label) {
ticMap[label] = std::chrono::high_resolution_clock::now();
}

// Stop timing and log
static void toc(const std::string& label) {
auto it = ticMap.find(label);
if (it == ticMap.end()) return;

auto end_time = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsed = end_time - it->second;

// Write to performance log file with timestamp
if (perfLogFile.is_open()) {
auto now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()) % 1000;

struct tm timeinfo;
#ifdef _WIN32
localtime_s(&timeinfo, &now_c);
#else
localtime_r(&now_c, &timeinfo);
#endif
char timestamp[64];
std::strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &timeinfo);

perfLogFile << "[" << timestamp << "." << std::setfill('0') << std::setw(3) << now_ms.count() << "] "
<< "[PERF] " << label << ": "
<< std::fixed << std::setprecision(3)
<< elapsed.count() << " ms" << std::endl;
perfLogFile.flush();
}

ticMap.erase(it);
}

// Log diagnostic message (printf-style)
static void logf(const char* format, ...) {
if (perfLogFile.is_open()) {
char buffer[512];
va_list args;
va_start(args, format);
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);

auto now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()) % 1000;

struct tm timeinfo;
#ifdef _WIN32
localtime_s(&timeinfo, &now_c);
#else
localtime_r(&now_c, &timeinfo);
#endif
char timestamp[64];
std::strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &timeinfo);

perfLogFile << "[" << timestamp << "." << std::setfill('0') << std::setw(3) << now_ms.count() << "] "
<< "[DIAG] " << buffer;
perfLogFile.flush();
}
}

// Cleanup (call at shutdown)
static void shutdown() {
if (perfLogFile.is_open()) {
perfLogFile.close();
}
ticMap.clear();
}
};

// Static member initialization
std::ofstream PerformanceTimer::perfLogFile;
std::string PerformanceTimer::perfLogPath;
std::unordered_map<std::string, std::chrono::high_resolution_clock::time_point> PerformanceTimer::ticMap;

// Convenience macros
#define PERF_INIT(logPath) PerformanceTimer::init(logPath)
#define PERF_SHUTDOWN() PerformanceTimer::shutdown()
#define PERF_TIC(name) PerformanceTimer::tic(name)
#define PERF_TOC(name) PerformanceTimer::toc(name)
#define PERF_LOG(...) PerformanceTimer::logf(__VA_ARGS__)

#else // ENABLE_PERF_TIMING not defined

// No-op macros when disabled (zero overhead)
#define PERF_INIT(logPath)
#define PERF_SHUTDOWN()
#define PERF_TIC(name)
#define PERF_TOC(name)
#define PERF_LOG(...)

#endif // ENABLE_PERF_TIMING

#endif // PERFORMANCE_TIMER_H
4 changes: 2 additions & 2 deletions CommonLib/RealSimPack.m
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function setupImpl(obj)
% % try

% initialize ByteData
ByteData = zeros(200, 1, 'uint8');
ByteData = zeros(1024, 1, 'uint8');

% parser ByteData
[ByteData, nMsgSize] = obj.packVehData(simState, t, ByteData, VehDataBus);
Expand All @@ -98,7 +98,7 @@ function validateInputsImpl(obj, simState, t, VehData)
function [sz1, sz2] = getOutputSizeImpl(obj)
% Maximum length of linear indices and element vector is the
% number of elements in the input
sz1 = [200 1]; sz2 = [1 1];
sz1 = [1024 1]; sz2 = [1 1];
end

function [fz1, fz2] = isOutputFixedSizeImpl(~)
Expand Down
2 changes: 1 addition & 1 deletion CommonLib/RealSimSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#pragma comment (lib, "AdvApi32.lib")

#define RECVBUFFERSIZE 1024
#define SENDBUFFERSIZE 200
#define SENDBUFFERSIZE 1024


// s-function parameters
Expand Down
Loading