* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
#include <atomic>
#include "WsSessionManager.h"
#include "TraceTime.h"
#include "SystemViewOverallRepoInterface.h"
#include "SystemViewOverallRepoFactory.h"
#include "SystemViewOverallCacheManager.h"
#include "QuerySystemViewOverallHandler.h"
namespace Dic::Module::Timeline {
using namespace Dic::Server;
bool QuerySystemViewOverallHandler::HandleRequest(std::unique_ptr<Protocol::Request> requestPtr) {
auto &request = dynamic_cast<SystemViewOverallRequest &>(*requestPtr);
std::unique_ptr<SystemViewOverallResponse> responsePtr = std::make_unique<SystemViewOverallResponse>();
SystemViewOverallResponse &response = *responsePtr;
SetBaseResponse(request, response);
auto database = DataBaseManager::Instance().GetTraceDatabaseByFileId(request.fileId);
if (database == nullptr) {
SetTimelineError(ErrorCode::CONNECT_DATABASE_FAILED);
SendResponse(std::move(responsePtr), false);
return false;
}
if (!database->CheckValueFromStatusInfoTable(OVERLAP_ANALYSIS_UNIT, FINISH_STATUS)) {
response.isLoading = true;
SetTimelineError(ErrorCode::OVERLAP_ANALYSIS_PARSE_NOT_FINISH);
SendResponse(std::move(responsePtr), false);
return true;
}
uint64_t minTimestamp = TraceTime::Instance().GetStartTime();
std::string error;
if (!request.params.CheckParams(minTimestamp, error)) {
SetTimelineError(ErrorCode::PARAMS_ERROR);
SendResponse(std::move(responsePtr), false, error);
return false;
}
std::vector<SystemViewOverallRes> overallDetails =
SystemViewOverallCacheManager::Instance().GetOverallData(request.fileId);
if (!overallDetails.empty() && request.params.startTime == request.params.endTime) {
response.details = overallDetails;
} else if (CalOverallData(request, response, error, database)) {
if (request.params.startTime == request.params.endTime) {
SystemViewOverallCacheManager::Instance().SetOverallData(request.fileId, response.details);
}
} else {
SetTimelineError(ErrorCode::QUERY_SYSTEM_VIEW_OVERALL_FAILED);
SendResponse(std::move(responsePtr), false);
return false;
}
response.pageParam.total = response.details.size();
response.pageParam.current = request.params.page.current;
response.pageParam.pageSize = request.params.page.pageSize;
SendResponse(std::move(responsePtr), true);
return true;
}
bool QuerySystemViewOverallHandler::CalOverallData(SystemViewOverallRequest &request,
SystemViewOverallResponse &response, std::string &error, const std::shared_ptr<VirtualTraceDatabase> &database) {
SystemViewOverallHelper overallHelper;
std::string deviceId = DataBaseManager::Instance().GetDeviceIdFromRankId(request.params.rankId);
if (deviceId.empty()) {
error = "Failed to get deviceId for system view overall statistics.";
SetTimelineError(ErrorCode::GET_DEVICE_ID_FAILED);
return false;
}
request.params.deviceId = deviceId;
overallHelper.e2eTime = GetOverlapAnalysisData(overallHelper, database, request, response.details);
if (overallHelper.e2eTime == 0.0) {
error = "Failed to query system view overall. Overlap information query incomplete or missing.";
SetTimelineError(ErrorCode::QUERY_SYSTEM_VIEW_OVERALL_FAILED);
return false;
}
auto repoPtr = SystemViewOverallRepoFactory::Instance()->GetSystemViewOverallRepo(
DataBaseManager::Instance().GetDataType(request.fileId));
if (repoPtr == nullptr) {
SetTimelineError(ErrorCode::QUERY_SYSTEM_VIEW_OVERALL_FAILED);
return false;
}
if (!repoPtr->QueryDataForComputingOverallMetric(request.params, overallHelper, database)) {
ServerLog::Warn(
"Failed to get computing data for system view overall.");
}
if (!overallHelper.kernelEvents.empty()) {
overallHelper.CategorizeComputingEvents();
overallHelper.AggregateComputingOverallMetrics(response.details);
}
repoPtr->QueryCommunicationOverlapOverallInfos(request.params, overallHelper, response.details, database);
return true;
}
double QuerySystemViewOverallHandler::GetOverlapAnalysisData(SystemViewOverallHelper &overallHelper,
const std::shared_ptr<VirtualTraceDatabase> &database, const SystemViewOverallRequest &request,
std::vector<SystemViewOverallRes> &responseBody) {
double e2eTime{};
auto repoPtr = SystemViewOverallRepoFactory::Instance()->GetSystemViewOverallRepo(
DataBaseManager::Instance().GetDataType(request.fileId));
if (repoPtr == nullptr) {
return e2eTime;
}
overallHelper.overlapInfos = repoPtr->QueryOverlapAnalysisDataForOverallMetric(request.params, database);
uint32_t expectOverlapSize = 3;
if (overallHelper.overlapInfos.size() < expectOverlapSize) {
return e2eTime;
}
const size_t communicationIndex = 0;
const size_t computingIndex = 1;
const size_t freeIndex = 2;
double communicationNotOverlapped = overallHelper.overlapInfos[communicationIndex].duration;
double computingTime = overallHelper.overlapInfos[computingIndex].duration;
double freeTime = overallHelper.overlapInfos[freeIndex].duration;
e2eTime = communicationNotOverlapped + computingTime + freeTime;
if (std::fabs(e2eTime - 0.0) < std::numeric_limits<double>::epsilon()) {
return e2eTime;
}
double computingRatio = NumberUtil::DoubleReservedNDigits(PERCENTAGE_RATIO_SCALE * computingTime / e2eTime, TWO);
double communicationRatio =
NumberUtil::DoubleReservedNDigits(PERCENTAGE_RATIO_SCALE * communicationNotOverlapped / e2eTime, TWO);
double freeRatio = NumberUtil::DoubleReservedNDigits(PERCENTAGE_RATIO_SCALE * freeTime / e2eTime, TWO);
double e2eRatio = PERCENTAGE_RATIO_SCALE;
Protocol::SystemViewOverallRes tmpRes = {.totalTime = computingTime,
.ratio = computingRatio,
.nums = 0,
.avg = 0,
.max = 0,
.min = UINT32_MAX,
.name = COMPUTING_TIME,
.children = {},
.level = 1,
.id = std::to_string(overallHelper.idCounter++)};
responseBody.emplace_back(tmpRes);
tmpRes = {.totalTime = communicationNotOverlapped,
.ratio = communicationRatio,
.nums = 0,
.avg = 0,
.max = 0,
.min = 0,
.name = COMMUNICATION_NOT_OVERLAP_TIME,
.children = {},
.level = 1,
.id = std::to_string(overallHelper.idCounter++)};
responseBody.emplace_back(tmpRes);
tmpRes = {.totalTime = freeTime,
.ratio = freeRatio,
.nums = 0,
.avg = 0,
.max = 0,
.min = 0,
.name = FREE_TIME,
.children = {},
.level = 1,
.id = std::to_string(overallHelper.idCounter++)};
responseBody.emplace_back(tmpRes);
tmpRes = {.totalTime = NumberUtil::DoubleReservedNDigits(e2eTime, TWO),
.ratio = e2eRatio,
.nums = 0,
.avg = 0,
.max = 0,
.min = 0,
.name = E2E_TIME,
.children = {},
.level = 1,
.id = std::to_string(overallHelper.idCounter++)};
responseBody.emplace_back(tmpRes);
return e2eTime;
}
}