2010-08-31 22:18:07 +02:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2023-01-28 10:16:34 +01:00
* Copyright ( C ) 2007 - 2023 Cppcheck team .
2010-08-31 22:18:07 +02:00
*
* 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 , either version 3 of the License , or
* ( at your option ) any later version .
*
* 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 , see < http : //www.gnu.org/licenses/>.
*/
2014-06-05 17:35:27 +02:00
# include "timer.h"
2017-05-27 04:33:47 +02:00
2023-09-08 19:30:25 +02:00
# include "utils.h"
2014-01-03 10:45:14 +01:00
# include <algorithm>
2010-08-31 22:18:07 +02:00
# include <iostream>
2017-05-27 04:33:47 +02:00
# include <utility>
2014-01-03 10:45:14 +01:00
# include <vector>
2010-08-31 22:18:07 +02:00
2014-01-03 10:45:14 +01:00
namespace {
2021-01-05 17:51:32 +01:00
using dataElementType = std : : pair < std : : string , struct TimerResultsData > ;
2014-01-03 10:45:14 +01:00
bool more_second_sec ( const dataElementType & lhs , const dataElementType & rhs )
{
return lhs . second . seconds ( ) > rhs . second . seconds ( ) ;
}
2023-10-05 19:04:06 +02:00
// TODO: remove and print through (synchronized) ErrorLogger instead
std : : mutex stdCoutLock ;
2014-01-03 10:45:14 +01:00
}
2010-08-31 22:18:07 +02:00
2023-10-05 19:04:06 +02:00
// TODO: this does not include any file context when SHOWTIME_FILE thus rendering it useless - should we include the logging with the progress logging?
// that could also get rid of the broader locking
2019-11-20 15:37:09 +01:00
void TimerResults : : showResults ( SHOWTIME_MODES mode ) const
2010-08-31 22:18:07 +02:00
{
2023-05-11 14:04:22 +02:00
if ( mode = = SHOWTIME_MODES : : SHOWTIME_NONE | | mode = = SHOWTIME_MODES : : SHOWTIME_FILE_TOTAL )
2014-01-03 10:24:57 +01:00
return ;
2012-09-15 19:49:48 +02:00
TimerResultsData overallData ;
2022-08-23 20:30:45 +02:00
std : : vector < dataElementType > data ;
2023-10-05 19:04:06 +02:00
2022-08-23 20:30:45 +02:00
{
std : : lock_guard < std : : mutex > l ( mResultsSync ) ;
2023-10-05 19:04:06 +02:00
2023-03-04 12:05:17 +01:00
data . reserve ( mResults . size ( ) ) ;
2022-12-30 15:13:47 +01:00
data . insert ( data . begin ( ) , mResults . cbegin ( ) , mResults . cend ( ) ) ;
2022-08-23 20:30:45 +02:00
}
2014-01-03 10:45:14 +01:00
std : : sort ( data . begin ( ) , data . end ( ) , more_second_sec ) ;
2010-08-31 22:18:07 +02:00
2023-10-05 19:04:06 +02:00
// lock the whole logging operation to avoid multiple threads printing their results at the same time
std : : lock_guard < std : : mutex > l ( stdCoutLock ) ;
std : : cout < < std : : endl ;
2014-01-03 10:45:14 +01:00
size_t ordinal = 1 ; // maybe it would be nice to have an ordinal in output later!
2022-12-20 20:32:16 +01:00
for ( std : : vector < dataElementType > : : const_iterator iter = data . cbegin ( ) ; iter ! = data . cend ( ) ; + + iter ) {
2014-01-03 10:45:14 +01:00
const double sec = iter - > second . seconds ( ) ;
2018-06-16 22:24:44 +02:00
const double secAverage = sec / ( double ) ( iter - > second . mNumberOfResults ) ;
2023-04-11 19:52:55 +02:00
bool hasParent = false ;
{
2023-06-20 10:31:11 +02:00
// Do not use valueFlow.. in "Overall time" because those are included in Tokenizer already
2023-09-08 19:30:25 +02:00
if ( startsWith ( iter - > first , " valueFlow " ) )
2023-06-20 10:31:11 +02:00
hasParent = true ;
2023-04-11 19:52:55 +02:00
// Do not use inner timers in "Overall time"
const std : : string : : size_type pos = iter - > first . rfind ( " :: " ) ;
if ( pos ! = std : : string : : npos )
hasParent = std : : any_of ( data . cbegin ( ) , data . cend ( ) , [ iter , pos ] ( const dataElementType & d ) {
return d . first . size ( ) = = pos & & iter - > first . compare ( 0 , d . first . size ( ) , d . first ) = = 0 ;
} ) ;
}
if ( ! hasParent )
overallData . mClocks + = iter - > second . mClocks ;
2023-10-05 19:04:06 +02:00
if ( ( mode ! = SHOWTIME_MODES : : SHOWTIME_TOP5_FILE & & mode ! = SHOWTIME_MODES : : SHOWTIME_TOP5_SUMMARY ) | | ( ordinal < = 5 ) ) {
2018-06-16 22:24:44 +02:00
std : : cout < < iter - > first < < " : " < < sec < < " s (avg. " < < secAverage < < " s - " < < iter - > second . mNumberOfResults < < " result(s)) " < < std : : endl ;
2014-01-03 10:45:14 +01:00
}
+ + ordinal ;
2010-08-31 22:18:07 +02:00
}
2012-09-15 19:49:48 +02:00
const double secOverall = overallData . seconds ( ) ;
2010-08-31 22:18:07 +02:00
std : : cout < < " Overall time: " < < secOverall < < " s " < < std : : endl ;
}
2019-11-20 15:37:09 +01:00
void TimerResults : : addResults ( const std : : string & str , std : : clock_t clocks )
2010-08-31 22:18:07 +02:00
{
2022-08-23 20:30:45 +02:00
std : : lock_guard < std : : mutex > l ( mResultsSync ) ;
2018-06-17 17:20:16 +02:00
mResults [ str ] . mClocks + = clocks ;
mResults [ str ] . mNumberOfResults + + ;
2010-08-31 22:18:07 +02:00
}
2023-10-05 19:04:06 +02:00
void TimerResults : : reset ( )
{
std : : lock_guard < std : : mutex > l ( mResultsSync ) ;
mResults . clear ( ) ;
}
2022-07-28 22:51:45 +02:00
Timer : : Timer ( std : : string str , SHOWTIME_MODES showtimeMode , TimerResultsIntf * timerResults )
: mStr ( std : : move ( str ) )
2018-06-16 22:14:59 +02:00
, mTimerResults ( timerResults )
2023-05-11 14:04:22 +02:00
, mStart ( std : : clock ( ) )
2018-06-16 22:40:11 +02:00
, mShowTimeMode ( showtimeMode )
2023-05-11 14:04:22 +02:00
, mStopped ( showtimeMode = = SHOWTIME_MODES : : SHOWTIME_NONE | | showtimeMode = = SHOWTIME_MODES : : SHOWTIME_FILE_TOTAL )
{ }
Timer : : Timer ( bool fileTotal , std : : string filename )
: mStr ( std : : move ( filename ) )
, mStopped ( ! fileTotal )
{ }
2010-08-31 22:18:07 +02:00
Timer : : ~ Timer ( )
{
2019-11-20 15:37:09 +01:00
stop ( ) ;
2010-08-31 22:18:07 +02:00
}
2019-11-20 15:37:09 +01:00
void Timer : : stop ( )
2010-08-31 22:18:07 +02:00
{
2019-07-31 22:35:51 +02:00
if ( ( mShowTimeMode ! = SHOWTIME_MODES : : SHOWTIME_NONE ) & & ! mStopped ) {
2010-08-31 22:18:07 +02:00
const std : : clock_t end = std : : clock ( ) ;
2018-06-16 22:43:25 +02:00
const std : : clock_t diff = end - mStart ;
2010-08-31 22:18:07 +02:00
2019-07-31 22:35:51 +02:00
if ( mShowTimeMode = = SHOWTIME_MODES : : SHOWTIME_FILE ) {
2018-04-04 21:51:31 +02:00
const double sec = ( double ) diff / CLOCKS_PER_SEC ;
2023-10-05 19:04:06 +02:00
std : : lock_guard < std : : mutex > l ( stdCoutLock ) ;
2018-06-16 22:49:51 +02:00
std : : cout < < mStr < < " : " < < sec < < " s " < < std : : endl ;
2023-05-11 14:04:22 +02:00
} else if ( mShowTimeMode = = SHOWTIME_MODES : : SHOWTIME_FILE_TOTAL ) {
const double sec = ( double ) diff / CLOCKS_PER_SEC ;
2023-10-05 19:04:06 +02:00
std : : lock_guard < std : : mutex > l ( stdCoutLock ) ;
2023-05-11 14:04:22 +02:00
std : : cout < < " Check time: " < < mStr < < " : " < < sec < < " s " < < std : : endl ;
2011-10-13 20:53:06 +02:00
} else {
2018-06-16 22:14:59 +02:00
if ( mTimerResults )
2019-11-20 15:37:09 +01:00
mTimerResults - > addResults ( mStr , diff ) ;
2010-08-31 22:18:07 +02:00
}
}
2018-06-16 22:34:50 +02:00
mStopped = true ;
2010-08-31 22:18:07 +02:00
}