VTrain/base/Statistic/Statistic.cpp

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;
}