Inherits from Task
The Chronometer
class is a utility component in the task framework that provides precise
time measurement capabilities. It extends the base Task
class to integrate with the
signal-slot system, allowing it to notify other components about timing events. The Chronometer provides
a simple interface for measuring elapsed time between start and stop operations, making it ideal for
performance profiling, operation timing, and benchmarking within the application.
class Chronometer : public Task {
public:
// Constructor
Chronometer();
// Start the timer
void start();
// Stop the timer and get elapsed time in milliseconds
int64_t stop();
private:
std::unique_ptr<std::chrono::system_clock::time_point> m_startTime;
};
Chronometer emits the following signals:
Signal | Type | Description | Arguments |
---|---|---|---|
started |
Simple | Emitted when the timer starts | None |
finished |
Simple | Emitted when the timer stops | None |
timing |
Data | Reports elapsed time on stop | int64_t (elapsed time in ms) |
error |
Data | Reports errors during timing operations | std::string (error message) |
// Create the chronometer
auto timer = std::make_shared<Chronometer>();
// Connect to signals
timer->connectSimple("started", []() {
std::cout << "Timer started" << std::endl;
});
timer->connectSimple("finished", []() {
std::cout << "Timer stopped" << std::endl;
});
timer->connectData("timing", [](const ArgumentPack& args) {
int64_t elapsedMs = args.get<int64_t>(0);
std::cout << "Elapsed time: " << elapsedMs << " ms" << std::endl;
});
// Start the timer
timer->start();
// Perform the operation to be timed
std::this_thread::sleep_for(std::chrono::milliseconds(500));
// Stop the timer and get the elapsed time
int64_t elapsed = timer->stop();
// Use the elapsed time
if (elapsed > 1000) {
std::cout << "Operation took more than 1 second!" << std::endl;
}
// Create algorithm and chronometer
auto algorithm = std::make_shared<MyAlgorithm>();
auto timer = std::make_shared<Chronometer>();
// Connect chronometer to log timing info
timer->connectData("timing", [](const ArgumentPack& args) {
int64_t elapsedMs = args.get<int64_t>(0);
std::cout << "Algorithm execution time: " << elapsedMs << " ms" << std::endl;
});
// Time the algorithm execution
timer->start();
algorithm->exec();
timer->stop();
// Create the chronometer
auto timer = std::make_shared<Chronometer>();
// Function to time an operation
auto timeOperation = [&timer](const std::string& name, std::function<void()> operation) {
std::cout << "Starting " << name << "..." << std::endl;
timer->start();
operation();
int64_t elapsed = timer->stop();
std::cout << name << " completed in " << elapsed << " ms" << std::endl;
return elapsed;
};
// Time different operations
timeOperation("Data loading", []() {
// Simulate data loading
std::this_thread::sleep_for(std::chrono::milliseconds(300));
});
timeOperation("Calculations", []() {
// Simulate calculations
std::this_thread::sleep_for(std::chrono::milliseconds(700));
});
timeOperation("Rendering", []() {
// Simulate rendering
std::this_thread::sleep_for(std::chrono::milliseconds(500));
});
The Chronometer uses the C++ standard library's chrono facilities for high-precision timing:
void Chronometer::start() {
m_startTime = std::make_unique<std::chrono::system_clock::time_point>(
std::chrono::system_clock::now());
emit("started");
}
int64_t Chronometer::stop() {
if (!m_startTime) {
emitString("error", "Chronometer not started.");
return 0;
}
auto now = std::chrono::system_clock::now();
auto timeDiff = std::chrono::duration_cast<std::chrono::milliseconds>(
now - *m_startTime)
.count();
// Create ArgumentPack with timing information
ArgumentPack timingArgs;
timingArgs.add<int64_t>(timeDiff);
// Emit both signals
emit("finished");
emit("timing", timingArgs);
m_startTime.reset();
return timeDiff;
}
The implementation follows these steps:
std::chrono::system_clock::now()
std::chrono::duration_cast
The Chronometer includes basic error handling to prevent misuse:
stop()
before start()
emits an
error signalstart()
multiple times overwrites the previous start
time// Create the chronometer
auto timer = std::make_shared<Chronometer>();
// Connect to error signal
timer->connectData("error", [](const ArgumentPack& args) {
std::string errorMsg = args.get<std::string>(0);
std::cerr << "Chronometer error: " << errorMsg << std::endl;
});
// Error: Stop without start
timer->stop(); // Will emit error: "Chronometer not started."
// Correct usage
timer->start();
// ... operations ...
timer->stop(); // Works correctly
The Chronometer can be integrated with various components in the task framework:
// Time algorithm execution
void timeAlgorithm(std::shared_ptr<Algorithm> algorithm, const ArgumentPack& args) {
auto timer = std::make_shared<Chronometer>();
// Log the results
auto logger = std::make_shared<Logger>("Performance");
timer->connectData("timing", [logger](const ArgumentPack& args) {
int64_t elapsedMs = args.get<int64_t>(0);
ArgumentPack logArgs;
logArgs.add<std::string>("Execution time: " + std::to_string(elapsedMs) + " ms");
logger->log(logArgs);
});
// Start timing
timer->start();
// Run the algorithm
algorithm->exec(args);
// Stop timing
timer->stop();
}
// Time thread pool execution
void benchmarkThreadPool(std::shared_ptr<ThreadPool> pool) {
auto timer = std::make_shared<Chronometer>();
// Connect to pool's finished signal to stop the timer
pool->connectSimple("finished", [timer]() {
timer->stop();
});
// Start timing and execute tasks
timer->start();
pool->exec();
// Timer will be stopped automatically when pool emits 'finished'
}
start()
with stop()
callstiming
signal for automatic time loggingstop()
when immediate timing
data is neededstop()
to ensure proper cleanup of timing resources
std::chrono::high_resolution_clock
instead. The current implementation focuses on
simplicity and compatibility for general application timing needs.
std::chrono::system_clock
for time measurementtiming
signal is created during construction for consistencystop()
to prevent reuse without a new start()
call