250 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			250 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | /*
 | ||
|  |  * Copyright(C) 2020. Huawei Technologies Co.,Ltd. All rights reserved. | ||
|  |  * | ||
|  |  * 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. | ||
|  |  */ | ||
|  | 
 | ||
|  | #include "Statistic.h"
 | ||
|  | #include <iostream>
 | ||
|  | #include <iomanip>
 | ||
|  | #include <sstream>
 | ||
|  | #include <fstream>
 | ||
|  | #include <algorithm>
 | ||
|  | #include "FileManager.h"
 | ||
|  | #include "Log.h"
 | ||
|  | 
 | ||
|  | bool Statistic::statisticEnable = false; | ||
|  | std::mutex Statistic::mutex_ = {}; | ||
|  | uint32_t Statistic::globalTimeCount = 0; | ||
|  | bool Statistic::globalTimeIsOver = false; | ||
|  | bool Statistic::globalTimeIsInit = false; | ||
|  | timeval Statistic::globalTimeStart = { 0, 0 }; | ||
|  | timeval Statistic::globalTimeStop = { 0, 0 }; | ||
|  | std::string Statistic::globalTimeModeName = {}; | ||
|  | std::string Statistic::globalTimeFileToSave = DEFAUTL_SAVE_FILE; | ||
|  | 
 | ||
|  | namespace { | ||
|  | const int SPLIT_LENGTH = 120; | ||
|  | const int INTERVAL_LENGTH_NAME = 40; | ||
|  | const int INTERVAL_LENGTH_DEFAULT = 15; | ||
|  | const double TIME_TRANS = 1000.0; | ||
|  | const int RUN_TIME_STATISTIC_PERIOD = 1000; | ||
|  | const int GLOBAL_TIME_STATISTIC_PERIOD = 2000; | ||
|  | const int DEFATL_RECORD_SIZE = 10000; | ||
|  | } | ||
|  | 
 | ||
|  | void Statistic::SetStatisticEnable(bool flag) | ||
|  | { | ||
|  |     statisticEnable = flag; | ||
|  | } | ||
|  | 
 | ||
|  | void Statistic::RunTimeStatisticStart(std::string modelName, uint32_t id, bool autoShowResult, std::string fileToSave) | ||
|  | { | ||
|  |     if (Statistic::statisticEnable) { | ||
|  |         if (!runTimeIsInit_) { | ||
|  |             runTimeModelName_ = modelName; | ||
|  |             runTimeId_ = id; | ||
|  |             runTimeTotal_ = 0.0; | ||
|  |             runTimeCount_ = 0; | ||
|  |             runTimeIsOver_ = false; | ||
|  |             if (!fileToSave.empty()) { | ||
|  |                 runTimeFileToSave_ = fileToSave; | ||
|  |             } | ||
|  |             if (autoShowResult) { | ||
|  |                 std::thread t(Statistic::ShowRunTimeStatistic, this); | ||
|  |                 t.detach(); | ||
|  |             } | ||
|  |             runTimeIsInit_ = true; | ||
|  |             runTimeRecord_.clear(); | ||
|  |             runTimeRecord_.reserve(DEFATL_RECORD_SIZE); | ||
|  |         } | ||
|  |         gettimeofday(&runTimeStart_, nullptr); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | void Statistic::RunTimeStatisticStop(uint32_t dynamicRunTimeCount) | ||
|  | { | ||
|  |     if (Statistic::statisticEnable) { | ||
|  |         gettimeofday(&runTimeStop_, nullptr); | ||
|  |         double tt = (runTimeStop_.tv_sec - runTimeStart_.tv_sec) * TIME_TRANS + | ||
|  |             (runTimeStop_.tv_usec - runTimeStart_.tv_usec) / TIME_TRANS; | ||
|  |         runTimeRecord_.push_back(std::make_pair(tt, std::max(dynamicRunTimeCount, 1U))); | ||
|  |         runTimeTotal_ += tt; | ||
|  |         while (runTimeIsOver_) { | ||
|  |             runTimeIsOver_ = false; | ||
|  |         } | ||
|  |         runTimeCount_ += std::max(dynamicRunTimeCount, 1U); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void Statistic::ShowRunTimeStatistic(Statistic *statistic) | ||
|  | { | ||
|  |     if (statistic == nullptr) { | ||
|  |         LogError << "input statistic is null"; | ||
|  |         return; | ||
|  |     } | ||
|  |     while (!statistic->runTimeIsOver_) { | ||
|  |         statistic->runTimeIsOver_ = true; | ||
|  |         std::this_thread::sleep_for(std::chrono::milliseconds(RUN_TIME_STATISTIC_PERIOD)); | ||
|  |     } | ||
|  |     if (statistic->runTimeCount_ == 0) { | ||
|  |         LogDebug << "the statistic is not start within a measurement period"; | ||
|  |         return; | ||
|  |     } | ||
|  |     statistic->ShowStatisticResult(); | ||
|  |     statistic->ShowStatisticRecord(); | ||
|  |     while (statistic->runTimeIsInit_) { | ||
|  |             statistic->runTimeIsInit_ = false; | ||
|  |         } | ||
|  |     while (statistic->runTimeIsOver_) { | ||
|  |         statistic->runTimeIsOver_ = false; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void Statistic::ShowStatisticResult() const | ||
|  | { | ||
|  |     std::string split(SPLIT_LENGTH, '-'); | ||
|  |     std::ostringstream ss; | ||
|  |     ss << std::endl << split << std::endl; | ||
|  |     ss.setf(std::ios::left); | ||
|  |     ss << std::setw(INTERVAL_LENGTH_NAME) << "model name" << std::setw(INTERVAL_LENGTH_DEFAULT) << "id" | ||
|  |        << std::setw(INTERVAL_LENGTH_DEFAULT) << "time(ms)" << std::setw(INTERVAL_LENGTH_DEFAULT) << "count" | ||
|  |        << std::setw(INTERVAL_LENGTH_DEFAULT) << "average(ms)" | ||
|  |        << "tps" << std::endl; | ||
|  |     ss << std::setw(INTERVAL_LENGTH_NAME) << runTimeModelName_ << std::setw(INTERVAL_LENGTH_DEFAULT) << runTimeId_ | ||
|  |        << std::setw(INTERVAL_LENGTH_DEFAULT) << runTimeTotal_ << std::setw(INTERVAL_LENGTH_DEFAULT) << runTimeCount_ | ||
|  |        << std::setw(INTERVAL_LENGTH_DEFAULT) << (runTimeTotal_ / runTimeCount_) << std::setw(INTERVAL_LENGTH_DEFAULT) | ||
|  |        << (runTimeCount_ / runTimeTotal_ * TIME_TRANS) << std::endl; | ||
|  |     ss.setf(std::ios::right); | ||
|  |     ss << split << std::endl << std::endl; | ||
|  | 
 | ||
|  |     std::lock_guard<std::mutex> locker(mutex_); | ||
|  |     std::cout << ss.str(); | ||
|  |     CreateDirRecursively(runTimeFileToSave_.substr(0, runTimeFileToSave_.rfind('/'))); | ||
|  |     SaveFileAppend(runTimeFileToSave_, ss.str().c_str(), ss.str().length()); | ||
|  | } | ||
|  | 
 | ||
|  | void Statistic::ShowStatisticRecord() const | ||
|  | { | ||
|  |     std::string split(SPLIT_LENGTH, '-'); | ||
|  |     std::ostringstream ss; | ||
|  | 
 | ||
|  |     ss << std::endl << split << std::endl; | ||
|  |     ss.setf(std::ios::left); | ||
|  |     ss << std::setw(INTERVAL_LENGTH_NAME) << "model name" << std::setw(INTERVAL_LENGTH_DEFAULT) << "No." | ||
|  |        << std::setw(INTERVAL_LENGTH_DEFAULT) << "id" << std::setw(INTERVAL_LENGTH_DEFAULT) << "time(ms)" | ||
|  |        << std::setw(INTERVAL_LENGTH_DEFAULT) << "count" << std::endl; | ||
|  |     for (size_t i = 0; i < runTimeRecord_.size(); ++i) { | ||
|  |         ss << std::setw(INTERVAL_LENGTH_NAME) << runTimeModelName_ << std::setw(INTERVAL_LENGTH_DEFAULT) | ||
|  |            << ("No." + std::to_string(i)) << std::setw(INTERVAL_LENGTH_DEFAULT) << runTimeId_ | ||
|  |            << std::setw(INTERVAL_LENGTH_DEFAULT) << runTimeRecord_[i].first << std::setw(INTERVAL_LENGTH_DEFAULT) | ||
|  |            << runTimeRecord_[i].second << std::endl; | ||
|  |     } | ||
|  |     ss.setf(std::ios::right); | ||
|  |     ss << split << std::endl << std::endl; | ||
|  |     SaveFileAppend(runTimeFileToSave_, ss.str().c_str(), ss.str().length()); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void Statistic::GlobalTimeStatisticStart(std::string modelName, bool autoShowResult, std::string fileToSave) | ||
|  | { | ||
|  |     if (Statistic::statisticEnable && !Statistic::globalTimeIsInit) { | ||
|  |         globalTimeIsOver = false; | ||
|  |         globalTimeCount = 0; | ||
|  |         Statistic::globalTimeModeName = modelName; | ||
|  |         Statistic::globalTimeFileToSave = fileToSave; | ||
|  |         if (autoShowResult) { | ||
|  |             std::thread t(Statistic::ShowGlobalTimeStatistic); | ||
|  |             t.detach(); | ||
|  |         } | ||
|  |         Statistic::globalTimeIsInit = true; | ||
|  |         gettimeofday(&Statistic::globalTimeStart, nullptr); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | void Statistic::GlobalTimeStatisticStop() | ||
|  | { | ||
|  |     gettimeofday(&Statistic::globalTimeStop, nullptr); | ||
|  |     while (globalTimeIsOver) { | ||
|  |         globalTimeIsOver = false; | ||
|  |     } | ||
|  |     ++Statistic::globalTimeCount; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void Statistic::ShowGlobalTimeStatistic() | ||
|  | { | ||
|  |     while (!Statistic::globalTimeIsOver) { | ||
|  |         Statistic::globalTimeIsOver = true; | ||
|  |         std::this_thread::sleep_for(std::chrono::milliseconds(GLOBAL_TIME_STATISTIC_PERIOD)); | ||
|  |     } | ||
|  |     if (Statistic::globalTimeCount == 0) { | ||
|  |         LogDebug << "the statistic is not start within a measurement period"; | ||
|  |         while (Statistic::globalTimeIsInit) { | ||
|  |             Statistic::globalTimeIsInit = false; | ||
|  |         } | ||
|  |         return; | ||
|  |     } | ||
|  |     double tt = (Statistic::globalTimeStop.tv_sec - Statistic::globalTimeStart.tv_sec) * TIME_TRANS + | ||
|  |         (Statistic::globalTimeStop.tv_usec - Statistic::globalTimeStart.tv_usec) / TIME_TRANS; | ||
|  | 
 | ||
|  |     std::string split(SPLIT_LENGTH, '-'); | ||
|  |     std::ostringstream ss; | ||
|  | 
 | ||
|  |     ss << std::endl << std::endl << split << std::endl; | ||
|  |     ss.setf(std::ios::left); | ||
|  |     ss << std::setw(INTERVAL_LENGTH_NAME) << "model name" << std::setw(INTERVAL_LENGTH_DEFAULT) << "time(ms)" | ||
|  |        << std::setw(INTERVAL_LENGTH_DEFAULT) << "count" << std::setw(INTERVAL_LENGTH_DEFAULT) << "average(ms)" | ||
|  |        << "tps" << std::endl; | ||
|  |     ss << std::setw(INTERVAL_LENGTH_NAME) << Statistic::globalTimeModeName << std::setw(INTERVAL_LENGTH_DEFAULT) | ||
|  |        << tt << std::setw(INTERVAL_LENGTH_DEFAULT) << Statistic::globalTimeCount << std::setw(INTERVAL_LENGTH_DEFAULT) | ||
|  |        << (tt / Statistic::globalTimeCount) << std::setw(INTERVAL_LENGTH_DEFAULT) | ||
|  |        << (Statistic::globalTimeCount / tt * TIME_TRANS) << std::endl; | ||
|  |     ss.setf(std::ios::right); | ||
|  |     ss << split << std::endl << std::endl << std::endl; | ||
|  | 
 | ||
|  |     std::lock_guard<std::mutex> locker(mutex_); | ||
|  |     std::cout << ss.str(); | ||
|  |     CreateDirRecursively( | ||
|  |         Statistic::globalTimeFileToSave.substr(0, Statistic::globalTimeFileToSave.rfind('/'))); | ||
|  |     SaveFileAppend(Statistic::globalTimeFileToSave, ss.str().c_str(), ss.str().length()); | ||
|  | 
 | ||
|  |     while (Statistic::globalTimeIsOver) { | ||
|  |         Statistic::globalTimeIsOver = false; | ||
|  |     } | ||
|  |     while (Statistic::globalTimeIsInit) { | ||
|  |         Statistic::globalTimeIsInit = false; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | double Statistic::GetRunTimeAvg(bool avg) const | ||
|  | { | ||
|  |     double result = runTimeTotal_ / runTimeCount_; | ||
|  |     if (!avg) { | ||
|  |         result = runTimeTotal_; | ||
|  |     } | ||
|  |     return result; | ||
|  | } | ||
|  | 
 | ||
|  | double Statistic::GetGlobalTimeAvg(bool avg) | ||
|  | { | ||
|  |     double globalTimeTotal = (Statistic::globalTimeStop.tv_sec - Statistic::globalTimeStart.tv_sec) * TIME_TRANS + | ||
|  |         (Statistic::globalTimeStop.tv_usec - Statistic::globalTimeStart.tv_usec) / TIME_TRANS; | ||
|  |     double result = globalTimeTotal / globalTimeCount; | ||
|  |     if (!avg) { | ||
|  |         result = globalTimeTotal; | ||
|  |     } | ||
|  |     return result; | ||
|  | } |