1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
2023-03-02 15:59:42 +00:00

309 lines
10 KiB
C++

/* Copyright (C) 2014 InfiniDB, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/******************************************************************************
* $Id: timeset.h 9655 2013-06-25 23:08:13Z xlou $
*
*****************************************************************************/
/** @file timeset.h
* Used to maintain collection of timers tracking elapsed times for set of tasks
*/
#pragma once
#include <ctime>
#include <iostream>
#include <string>
#include <map>
namespace joblist
{
//------------------------------------------------------------------------------
/** @brief Maintains a group of simulated timers and their elapsed times.
*
* This class maintains a collection of timers that can be used to collect
* statistics about the cumulative elapsed time spent on selected tasks.
*/
//------------------------------------------------------------------------------
class TimeSet
{
// TimerMap maps a timer to its start time
// ElapsedMap maps a timer to its cumulative elapsed time
typedef std::map<std::string, timespec> TimerMap;
typedef std::map<std::string, timespec> ElapsedMap;
public:
TimeSet() : fTimer(), fElapsed()
{
}
void displayAll() const;
void display(const std::string& key) const;
double totalTime() const;
double totalTime(const std::string& key) const;
void holdTimer(const std::string& key);
void startTimer(const std::string& key);
void stopTimer(const std::string& key);
void setTimer(const std::string& key, bool start = true);
TimeSet& operator+=(const TimeSet& rhs);
void clear()
{
fTimer.clear();
fElapsed.clear();
}
private:
void timespec_sub(const struct timespec& tv1, // start time
const struct timespec& tv2, // end time
struct timespec& diff) const;
void timespec_add(const struct timespec& tv1, const struct timespec& tv2, struct timespec& sum) const;
TimerMap fTimer;
ElapsedMap fElapsed;
};
//------------------------------------------------------------------------------
// Print the contents (to std::cout) of all timers in the ElapsedMap map.
//------------------------------------------------------------------------------
inline void TimeSet::displayAll() const
{
ElapsedMap::const_iterator itend = fElapsed.end();
for (ElapsedMap::const_iterator it = fElapsed.begin(); it != itend; ++it)
{
double t;
t = (double)it->second.tv_sec + (double)it->second.tv_nsec / 1000000000.0;
std::cout << "TimeSet " << it->first << ": " << t << "s\n";
}
std::cout.flush();
}
//------------------------------------------------------------------------------
// Print the specified timer to std::cout.
// If specified timer is in the ElapsedMap map, then the contents of that
// timer will be printed, else if the specified timer is in the TimerMap map,
// then the contents of that timer will be printed.
// key (in) - string that identifies the timer to be printed.
//------------------------------------------------------------------------------
inline void TimeSet::display(const std::string& key) const
{
ElapsedMap::const_iterator em = fElapsed.find(key);
if (fElapsed.end() != em)
{
double t;
t = (double)em->second.tv_sec + (double)em->second.tv_nsec / 1000000000.0;
std::cout << "TimeSet elapse " << em->first << ": " << t << "s\n";
}
else
{
TimerMap::const_iterator tm = fTimer.find(key);
if (fTimer.end() != tm)
{
double t;
t = (double)tm->second.tv_sec + (double)tm->second.tv_nsec / 1000000000.0;
std::cout << "TimeSet start " << tm->first << ": " << t << "s\n";
}
}
std::cout.flush();
}
//------------------------------------------------------------------------------
// Return sum of all timer elapsed times.
//------------------------------------------------------------------------------
inline double TimeSet::totalTime() const
{
struct timespec tSum = {0, 0};
ElapsedMap::const_iterator itend = fElapsed.end();
for (ElapsedMap::const_iterator it = fElapsed.begin(); it != itend; ++it)
{
}
double totSeconds;
totSeconds = (double)tSum.tv_sec + (double)tSum.tv_nsec / 1000000000.0;
return totSeconds;
}
//------------------------------------------------------------------------------
// Return current elapsed time for the specified timer.
// key (in) - string that identifies the timer of interest.
//------------------------------------------------------------------------------
inline double TimeSet::totalTime(const std::string& key) const
{
ElapsedMap::const_iterator el = fElapsed.find(key);
if (fElapsed.end() != el)
{
double totSeconds;
totSeconds = (double)el->second.tv_sec + (double)el->second.tv_nsec / 1000000000.0;
return totSeconds;
}
else
{
return 0;
}
}
//------------------------------------------------------------------------------
// "Hold" the specified timer.
// Elapsed time is recorded, and added to total elapsed time.
// Unlike stopTimer(), the start time is not reset to current time; instead
// startTimer() or setTimer() must be called by the application code when it
// is time to reset the start time and effectively resume or restart the timer.
// key (in) - string that identifies the timer to be "held".
//------------------------------------------------------------------------------
inline void TimeSet::holdTimer(const std::string& key)
{
TimerMap::iterator it = fTimer.find(key);
if (fTimer.end() != it)
{
struct timespec tEnd;
struct timespec tDiff;
#if defined(CLOCK_REALTIME)
clock_gettime(CLOCK_REALTIME, &tEnd);
#else
tEnd.tv_sec = tEnd.tv_nsec = 0;
#endif
timespec_sub(it->second, tEnd, tDiff);
struct timespec tElapsed = fElapsed[key];
timespec_add(tElapsed, tDiff, fElapsed[key]);
}
}
//------------------------------------------------------------------------------
// Start the specified timer.
// Start time is set to current time.
// key (in) - string that identifies the timer to be started.
//------------------------------------------------------------------------------
inline void TimeSet::startTimer(const std::string& key)
{
struct timespec ts;
#if defined(CLOCK_REALTIME)
clock_gettime(CLOCK_REALTIME, &ts);
#else
ts.tv_sec = ts.tv_nsec = 0;
#endif
fTimer[key] = ts;
}
//------------------------------------------------------------------------------
// Stop the specified timer.
// Elapsed time is recorded, and start time is set to current time.
// key (in) - string that identifies the timer to be stopped.
//------------------------------------------------------------------------------
inline void TimeSet::stopTimer(const std::string& key)
{
TimerMap::iterator it = fTimer.find(key);
if (fTimer.end() != it)
{
struct timespec tEnd;
struct timespec tDiff;
#if defined(CLOCK_REALTIME)
clock_gettime(CLOCK_REALTIME, &tEnd);
#else
tEnd.tv_sec = tEnd.tv_nsec = 0;
#endif
timespec_sub(it->second, tEnd, tDiff);
fElapsed[key] = tDiff;
fTimer[key] = tEnd;
}
}
//------------------------------------------------------------------------------
// Start or stop the specified timer.
// key (in) - string that identifies the timer to be started or stopped.
// start (in) - boolean indicating whether to start or stop the timer.
//------------------------------------------------------------------------------
inline void TimeSet::setTimer(const std::string& key, bool start /*= true*/)
{
if (start)
startTimer(key);
else
stopTimer(key);
}
//------------------------------------------------------------------------------
// Adds the specified TimeSet elapsed times to "this" TimeSet.
// rhs (in) - TimeSet with elapsed times to be added to "this" TimeSet.
//------------------------------------------------------------------------------
inline TimeSet& TimeSet::operator+=(const TimeSet& rhs)
{
ElapsedMap::const_iterator itend = rhs.fElapsed.end();
for (ElapsedMap::const_iterator it = rhs.fElapsed.begin(); it != itend; ++it)
{
struct timespec tLhs = fElapsed[it->first];
timespec_add(tLhs, it->second, fElapsed[it->first]);
}
return (*this);
}
//------------------------------------------------------------------------------
// Takes the difference between 2 timespec values.
// tv1 (in) - first timespec value (subtracted from tv2)
// tv2 (in) - second timespec value
// diff (out) - value of tv2 - tv1
//------------------------------------------------------------------------------
inline void TimeSet::timespec_sub(const struct timespec& tv1, // start time
const struct timespec& tv2, // end time
struct timespec& diff) const
{
if (tv2.tv_nsec < tv1.tv_nsec)
{
diff.tv_sec = tv2.tv_sec - tv1.tv_sec - 1;
diff.tv_nsec = tv2.tv_nsec + 1000000000 - tv1.tv_nsec;
}
else
{
diff.tv_sec = tv2.tv_sec - tv1.tv_sec;
diff.tv_nsec = tv2.tv_nsec - tv1.tv_nsec;
}
}
//------------------------------------------------------------------------------
// Add 2 timespec values.
// tv1 (in) - first timespec value
// tv2 (in) - second timespec value
// sum (out) - sum of tv1 and tv2
//------------------------------------------------------------------------------
inline void TimeSet::timespec_add(const struct timespec& tv1, // start time
const struct timespec& tv2, // end time
struct timespec& sum) const
{
sum.tv_sec = tv1.tv_sec + tv2.tv_sec;
sum.tv_nsec = tv1.tv_nsec + tv2.tv_nsec;
if (sum.tv_nsec >= 1000000000)
{
sum.tv_sec += 1;
sum.tv_nsec -= 1000000000;
}
}
}; // namespace joblist