已合并
支持C化各模块前向无环图注册机制 #395
Wangang Yu创建于 8月4日
支持C化各模块前向无环图注册机制 #395
已合并
Wangang Yu创建于 8月4日
36 个文件变更+3383-1116
@@ -16,12 +16,15 @@
16 16 
17#include "analysis/csrc/application/database/db_assembler.h"17#include "analysis/csrc/application/database/db_assembler.h"
18 18 
19-#include <atomic>
20#include <functional>19#include <functional>
20+#include <memory>
21+#include <string>
22+#include <unordered_map>
23+#include <vector>
21 24 
22#include "analysis/csrc/application/credential/id_pool.h"25#include "analysis/csrc/application/credential/id_pool.h"
23#include "analysis/csrc/application/database/db_constant.h"26#include "analysis/csrc/application/database/db_constant.h"
24-#include "analysis/csrc/domain/data_process/ai_task/overlap_analysis_processor.h"27+#include "analysis/csrc/domain/data_process/data_processor.h"
25#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/api_data.h"28#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/api_data.h"
26#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ascend_task_data.h"29#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ascend_task_data.h"
27#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ccu_mission_data.h"30#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ccu_mission_data.h"
@@ -53,7 +56,7 @@
53#include "analysis/csrc/domain/services/environment/context.h"56#include "analysis/csrc/domain/services/environment/context.h"
54#include "analysis/csrc/infrastructure/dfx/error_code.h"57#include "analysis/csrc/infrastructure/dfx/error_code.h"
55#include "analysis/csrc/infrastructure/dump_tools/json_tool/include/json_writer.h"58#include "analysis/csrc/infrastructure/dump_tools/json_tool/include/json_writer.h"
56-#include "analysis/csrc/infrastructure/utils/thread_pool.h"59+#include "analysis/csrc/infrastructure/process/include/topo_callback_process.h"
57 60 
58namespace Analysis61namespace Analysis
59{62{
@@ -161,7 +164,7 @@ bool CreateTableIndex(const std::string& tableName, const std::string& indexName
161 164 
162bool SaveApiData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath)165bool SaveApiData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath)
163{166{
164- uint32_t pid = Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath);167+ uint32_t pid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath);
165 auto apiData = dataInventory.GetPtr<std::vector<ApiData>>();168 auto apiData = dataInventory.GetPtr<std::vector<ApiData>>();
166 if (apiData == nullptr)169 if (apiData == nullptr)
167 {170 {
@@ -501,8 +504,8 @@ bool SaveHostInfoData(DataInventory& dataInventory, DBInfo& msprofDB, const std:
501 // hostuid, hostname504 // hostuid, hostname
502 using HostInfoDataFormat = std::vector<std::tuple<std::string, std::string>>;505 using HostInfoDataFormat = std::vector<std::tuple<std::string, std::string>>;
503 HostInfoDataFormat hostInfoData;506 HostInfoDataFormat hostInfoData;
504- std::string hostUid = Context::GetInstance().GetHostUid(HOST_ID, profPath);507+ std::string hostUid = Environment::Context::GetInstance().GetHostUid(HOST_ID, profPath);
505- std::string hostName = Context::GetInstance().GetHostName(HOST_ID, profPath);508+ std::string hostName = Environment::Context::GetInstance().GetHostName(HOST_ID, profPath);
506 hostInfoData.emplace_back(hostUid, hostName);509 hostInfoData.emplace_back(hostUid, hostName);
507 if (hostInfoData.empty())510 if (hostInfoData.empty())
508 {511 {
@@ -571,7 +574,7 @@ bool SaveMsprofTxData(DataInventory& dataInventory, DBInfo& msprofDB, const std:
571 ERROR("Reserved for MsprofTx data failed.");574 ERROR("Reserved for MsprofTx data failed.");
572 return false;575 return false;
573 }576 }
574- uint32_t pid = Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath);577+ uint32_t pid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath);
575 for (const auto& item : *msprofTxData)578 for (const auto& item : *msprofTxData)
576 {579 {
577 uint64_t message = IdPool::GetInstance().GetUint64Id(item.message);580 uint64_t message = IdPool::GetInstance().GetUint64Id(item.message);
@@ -588,7 +591,7 @@ void UpdateNpuData(const std::string& profPath, const std::string& deviceDir,
588 std::vector<std::tuple<int16_t, int16_t>>& rankDeviceMapData)591 std::vector<std::tuple<int16_t, int16_t>>& rankDeviceMapData)
589{592{
590 uint16_t deviceId = Utils::GetDeviceIdByDevicePath(deviceDir);593 uint16_t deviceId = Utils::GetDeviceIdByDevicePath(deviceDir);
591- uint16_t chip = Context::GetInstance().GetPlatformVersion(deviceId, profPath);594+ uint16_t chip = Environment::Context::GetInstance().GetPlatformVersion(deviceId, profPath);
592 std::string chipName;595 std::string chipName;
593 auto it = CHIP_TABLE.find(chip);596 auto it = CHIP_TABLE.find(chip);
594 if (it == CHIP_TABLE.end())597 if (it == CHIP_TABLE.end())
@@ -694,7 +697,7 @@ bool SaveNpuOpMemData(DataInventory& dataInventory, DBInfo& msprofDB, const std:
694 return false;697 return false;
695 }698 }
696 uint64_t stringGeId = IdPool::GetInstance().GetUint64Id("GE");699 uint64_t stringGeId = IdPool::GetInstance().GetUint64Id("GE");
697- uint32_t pid = Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath);700+ uint32_t pid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath);
698 uint64_t operatorNameId;701 uint64_t operatorNameId;
699 uint64_t globalTid;702 uint64_t globalTid;
700 for (const auto& item : *npuOpMemData)703 for (const auto& item : *npuOpMemData)
@@ -768,7 +771,7 @@ bool SaveSessionTimeInfoData(DataInventory& dataInventory, DBInfo& msprofDB, con
768 // startTime, endTime771 // startTime, endTime
769 using TimeDataFormat = std::vector<std::tuple<uint64_t, uint64_t>>;772 using TimeDataFormat = std::vector<std::tuple<uint64_t, uint64_t>>;
770 Utils::ProfTimeRecord tempRecord;773 Utils::ProfTimeRecord tempRecord;
771- if (!Context::GetInstance().GetProfTimeRecordInfo(tempRecord, profPath))774+ if (!Environment::Context::GetInstance().GetProfTimeRecordInfo(tempRecord, profPath))
772 {775 {
773 ERROR("GetProfTimeRecordInfo failed, profPath is %.", profPath);776 ERROR("GetProfTimeRecordInfo failed, profPath is %.", profPath);
774 return false;777 return false;
@@ -878,7 +881,7 @@ bool SaveAscendTaskData(DataInventory& dataInventory, DBInfo& msprofDB, const st
878 return false;881 return false;
879 }882 }
880 uint64_t globalTaskId;883 uint64_t globalTaskId;
881- uint32_t globalPid = Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath);884+ uint32_t globalPid = Environment::Context::GetInstance().GetPidFromInfoJson(HOST_ID, profPath);
882 uint64_t taskType;885 uint64_t taskType;
883 if (ascendTaskData != nullptr)886 if (ascendTaskData != nullptr)
884 {887 {
@@ -1195,16 +1198,6 @@ bool SaveOSRuntimeApiData(DataInventory& dataInventory, DBInfo& msprofDB, const
1195bool SaveOverlapAnalysisData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath)1198bool SaveOverlapAnalysisData(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath)
1196{1199{
1197 auto overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>();1200 auto overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>();
1198- if (overlapData == nullptr)
1199- {
1200- OverlapAnalysisProcessor processor(profPath);
1201- if (!processor.Run(dataInventory, PROCESSOR_NAME_OVERLAP_ANALYSIS))
1202- {
1203- ERROR("Process overlap analysis data failed.");
1204- return false;
1205- }
1206- overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>();
1207- }
1208 if (overlapData == nullptr || overlapData->empty())1201 if (overlapData == nullptr || overlapData->empty())
1209 {1202 {
1210 WARN("Overlap analysis data not exist.");1203 WARN("Overlap analysis data not exist.");
@@ -1246,7 +1239,7 @@ bool SaveQosData(DataInventory& dataInventory, DBInfo& msprofDB, const std::stri
1246 for (const auto& devicePath : deviceList)1239 for (const auto& devicePath : deviceList)
1247 {1240 {
1248 auto deviceId = GetDeviceIdByDevicePath(devicePath);1241 auto deviceId = GetDeviceIdByDevicePath(devicePath);
1249- auto qosEvents = Context::GetInstance().GetQosEvents(deviceId, profPath);1242+ auto qosEvents = Environment::Context::GetInstance().GetQosEvents(deviceId, profPath);
1250 std::vector<uint64_t> qosEventsIds;1243 std::vector<uint64_t> qosEventsIds;
1251 for (const auto& event : qosEvents)1244 for (const auto& event : qosEvents)
1252 {1245 {
@@ -1488,9 +1481,9 @@ bool SaveCCUData(DataInventory& dataInventory, DBInfo& msprofDB, const std::stri
1488 1481 
1489 return SaveData(res, TABLE_NAME_CCU, msprofDB);1482 return SaveData(res, TABLE_NAME_CCU, msprofDB);
1490}1483}
1491-// 创建 SaveData 的函数类型1484+const std::string DB_PREFIX = "DB:";
1492-using SaveDataFunc = std::function<bool(DataInventory& dataInventory, DBInfo& msprofDB, const std::string& profPath)>;1485+const std::string DB_STRING_IDS = DB_PREFIX + TABLE_NAME_STRING_IDS;
1493-const std::unordered_map<std::string, SaveDataFunc> DATA_SAVER = {1486+const std::unordered_map<std::string, DBSaveDataFunc> DATA_SAVER = {
1494 {PROCESSOR_NAME_API, SaveApiData},1487 {PROCESSOR_NAME_API, SaveApiData},
1495 {PROCESSOR_NAME_COMMUNICATION, SaveCommunicationData},1488 {PROCESSOR_NAME_COMMUNICATION, SaveCommunicationData},
1496 {PROCESSOR_NAME_ACC_PMU, SaveAccPmuData},1489 {PROCESSOR_NAME_ACC_PMU, SaveAccPmuData},
@@ -1532,107 +1525,67 @@ const std::unordered_map<std::string, SaveDataFunc> DATA_SAVER = {
1532 {PROCESSOR_NAME_CCU_MISSION, SaveCCUData},1525 {PROCESSOR_NAME_CCU_MISSION, SaveCCUData},
1533};1526};
1534 1527 
1535-bool CheckMsprofDb(const std::string& outputPath)
1536-{
1537- std::vector<std::string> files = File::GetOriginData(outputPath, {DB_NAME_MSPROF_DB}, {".json", ".csv"});
1538- if (files.empty())
1539- {
1540- return false;
1541- }
1542- std::string timestampMax;
1543- std::string latestFile;
1544- for (const auto& file : files)
1545- {
1546- auto dbName = Split(file, "/").back();
1547- size_t start = dbName.find(DB_NAME_MSPROF_DB) + DB_NAME_MSPROF_DB.length() + 1;
1548- size_t end = dbName.find(".db");
1549- if (start == std::string::npos || end == std::string::npos) continue;
1550- 
1551- std::string timestampStr = dbName.substr(start, end - start);
1552- if (!IsNumber(timestampStr) || timestampStr.size() != EXPECT_TIME_LEN)
1553- {
1554- ERROR("Invalid msprof db name %.", dbName);
1555- continue;
1556- }
1557- if (timestampStr > timestampMax)
1558- {
1559- timestampMax = timestampStr;
1560- latestFile = file;
1561- }
1562- }
1563- 
1564- DBInfo msprofDB(latestFile, TABLE_NAME_STRING_IDS);
1565- if (!msprofDB.ConstructDBRunner(latestFile))
1566- {
1567- ERROR("Construct for msprof db runner failed.");
1568- return false;
1569- }
1570- 
1571- if (!Utils::FileReader::Check(latestFile, MAX_DB_BYTES))
1572- {
1573- ERROR("Check % failed.", latestFile);
1574- return false;
1575- }
1576- if (msprofDB.dbRunner->CheckTableExists(msprofDB.tableName))
1577- {
1578- INFO("Find completed msprof db, %.", latestFile);
1579- return true;
1580- }
1581- 
1582- INFO("The % database is incomplete and will be deleted.", latestFile);
1583- PRINT_INFO("The % database is incomplete and will be deleted.", latestFile);
1584- if (!Utils::File::DeleteFile(latestFile))
1585- {
1586- ERROR("Failed to delete file, %.", latestFile);
1587- }
1588- return false;
1589-}
1590- 
1591std::string GetDBPath(const std::string& outputDir)1528std::string GetDBPath(const std::string& outputDir)
1592{1529{
1593 return Utils::File::PathJoin({outputDir, DB_NAME_MSPROF_DB + "_" + Analysis::Utils::GetFormatLocalTime() + ".db"});1530 return Utils::File::PathJoin({outputDir, DB_NAME_MSPROF_DB + "_" + Analysis::Utils::GetFormatLocalTime() + ".db"});
1594}1531}
1595 1532 
1596-const std::set<std::string> DB_DATA_PROCESS_LIST{
1597- PROCESSOR_NAME_API,
1598- PROCESSOR_NAME_COMMUNICATION,
1599- PROCESSOR_NAME_COMPUTE_TASK_INFO,
1600- PROCESSOR_NAME_KFC_TASK,
1601- PROCESSOR_NAME_DEVICE_TX,
1602- PROCESSOR_NAME_MSTX,
1603- PROCESSOR_NAME_STEP_TRACE,
1604- PROCESSOR_NAME_TASK,
1605- PROCESSOR_NAME_ACC_PMU,
1606- PROCESSOR_NAME_AICORE_FREQ,
1607- PROCESSOR_NAME_LOW_POWER,
1608- PROCESSOR_NAME_DDR,
1609- PROCESSOR_NAME_HBM,
1610- PROCESSOR_NAME_HCCS,
1611- PROCESSOR_NAME_NETDEV_STATS,
1612- PROCESSOR_NAME_CPU_USAGE,
1613- PROCESSOR_NAME_MEM_USAGE,
1614- PROCESSOR_NAME_DISK_USAGE,
1615- PROCESSOR_NAME_NETWORK_USAGE,
1616- PROCESSOR_NAME_OSRT_API,
1617- PROCESSOR_NAME_LLC,
1618- PROCESSOR_NAME_NPU_MEM,
1619- PROCESSOR_NAME_PCIE,
1620- PROCESSOR_NAME_DPU,
1621- PROCESSOR_NAME_SIO,
1622- PROCESSOR_NAME_UB,
1623- PROCESSOR_NAME_SOC,
1624- PROCESSOR_NAME_NIC,
1625- PROCESSOR_NAME_ROCE,
1626- PROCESSOR_NAME_QOS,
1627- PROCESSOR_NAME_CCU_MISSION,
1628- PROCESSOR_MC2_COMM_INFO,
1629- PROCESSOR_NAME_MEMCPY_INFO,
1630- PROCESSOR_NAME_NPU_OP_MEM,
1631- PROCESSOR_NAME_NPU_MODULE_MEM,
1632- PROCESSOR_NAME_UNIFIED_PMU,
1633-};
1634} // namespace1533} // namespace
1635 1534 
1535+TopoNodeCreatorFactory DBAssembler::CreateSaver(const std::string& name)
Y
Yyuliangbin8月10日

【review】 问题:两个函数在模式上高度重复,后续维护容易出现行为漂移 CreateSaver 和 CreateStringIdsSaver 本质都是: 取 session 判空 构造 ProcessCreator 在 TopoAssemblerProcess 中执行保存逻辑 但现在它们的日志、错误处理、输出语义已经不一致了,这通常就是重复代码带来的维护偏差。 建议: 抽一个统一的辅助构造函数,把“取 session、判空、创建 TopoAssemblerProcess、日志包装”这些共性逻辑收敛起来。 这样可以统一错误处理和日志规范,也能减少未来继续出现一个函数修了、另一个没修的问题。

likedislike
1536+{
1537+ return [name](const TopoBuildContext& context) -> Infra::ProcessCreator
P
Ppanzhaohu8月10日

[review]这里和下面的CreateStringIdsSaver函数都是直接使用匿名函数进行处理,这样处理让人难以看懂,建议直接写成函数体处理

likedislike
1538+ {
1539+ const auto saverIter = DATA_SAVER.find(name.substr(DB_PREFIX.size()));
Y
Yyuliangbin8月10日

【review】 问题:name.substr(DB_PREFIX.size()) 存在越界/异常风险 CreateSaver 里直接执行 name.substr(DB_PREFIX.size()),但这段代码没有先确认 name 是否真的以 DB_PREFIX 开头,也没有确认长度是否足够。 如果传入的 name 不符合预期,substr 可能抛出 std::out_of_range,这里又没有异常保护,会直接中断流程。 建议: 在截取前先做前缀和长度校验,例如先判断 name.size() >= DB_PREFIX.size() 且 name.compare(0, DB_PREFIX.size(), DB_PREFIX) == 0。 如果不满足条件,建议直接返回空的 ProcessCreator,同时补一条错误或告警日志,方便定位非法入参。

likedislike
1540+ if (saverIter == DATA_SAVER.end())
1541+ {
1542+ return Infra::ProcessCreator();
1543+ }
1544+ const auto session = context.dbSession;
Y
Yyuliangbin8月10日

【review】 问题:session 的生命周期可能不安全 两个函数都从 context.dbSession 取出 session,然后被多层 lambda 捕获并延后执行。 如果 dbSession 本质上是裸指针,或者它背后的对象生命周期短于 Process 的执行周期,这里就有悬空引用/悬空指针风险,后续访问 session->msprofDB_、session->profPath_ 可能导致未定义行为。 建议: 明确 dbSession 的所有权模型。 如果它本身就是 shared_ptr,那当前“按值捕获”通常是安全的,但建议在代码里体现这一点,降低误读成本。 如果不是共享所有权对象,建议改成显式延长生命周期的方案,比如持有 shared_ptr,或者在更高层保证 session 生命周期覆盖整个异步执行过程。

likedislike
1545+ if (session == nullptr)
1546+ {
1547+ return Infra::ProcessCreator();
1548+ }
1549+ const DBSaveDataFunc saver = saverIter->second;
1550+ return [name, saver, session]() -> std::unique_ptr<Infra::Process>
1551+ {
1552+ return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess(
1553+ [name, saver, session](DataInventory& dataInventory) -> bool
1554+ {
1555+ INFO("Begin to save % data.", name);
1556+ const bool result = saver(dataInventory, session->msprofDB_, session->profPath_);
1557+ if (!result)
1558+ {
1559+ ERROR("Save % data failed.", name);
1560+ }
1561+ return result;
1562+ }));
1563+ };
1564+ };
1565+}
1566+ 
1567+TopoNodeCreatorFactory DBAssembler::CreateStringIdsSaver()
Y
Yyuliangbin8月10日

【review】 问题:保存失败时的日志语义不一致,CreateStringIdsSaver 甚至会误报成功结束 CreateSaver 中有开始日志,失败时也会打印错误日志;但 CreateStringIdsSaver 中无论 SaveStringIdsData(...) 成功还是失败,都会打印 End exporting db output_file... 这会让日志看起来像“已经成功结束导出”,实际却可能失败,容易误导排查。 建议: 统一日志策略: 成功时打印成功结束日志,失败时打印错误日志,不要在失败路径输出成功语义的信息。 最好让 CreateStringIdsSaver 的日志风格与 CreateSaver 保持一致,例如: 开始保存时打印开始日志 result == false 时打印失败日志 result == true 时再打印完成日志

likedislike
1568+{
1569+ return [](const TopoBuildContext& context) -> Infra::ProcessCreator
Y
Yyuliangbin8月10日

【review】 问题:关键失败分支静默返回,排障信息不足 两处代码在以下情况下都只是直接返回空的 Infra::ProcessCreator(): DATA_SAVER 中找不到对应 saver session == nullptr 从功能上看这是“失败”,但从日志上看几乎无痕。调用方如果只是拿到空 creator,很难快速判断是配置名错了、前缀不对,还是 session 没初始化。 建议: 在这些返回空对象的分支增加明确日志,至少带上 name 或分支原因。 例如: saver 未注册:打印 name 和实际查找 key session == nullptr:打印上下文缺失信息 这样后续定位问题会快很多。

likedislike
1570+ {
1571+ const auto session = context.dbSession;
1572+ if (session == nullptr)
1573+ {
1574+ return Infra::ProcessCreator();
1575+ }
1576+ return [session]() -> std::unique_ptr<Infra::Process>
1577+ {
1578+ return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess(
1579+ [session](DataInventory& dataInventory) -> bool
1580+ {
1581+ const bool result = SaveStringIdsData(dataInventory, session->msprofDB_, session->profPath_);
1582+ PRINT_INFO("End exporting db output_file. The file is stored in the PROF file.");
1583+ return result;
1584+ }));
1585+ };
1586+ };
1587+}
1588+ 
1636DBAssembler::DBAssembler(const std::string& profPath, const std::string& outputPath)1589DBAssembler::DBAssembler(const std::string& profPath, const std::string& outputPath)
1637 : profPath_(profPath), outputPath_(outputPath)1590 : profPath_(profPath), outputPath_(outputPath)
1638{1591{
@@ -1642,44 +1595,44 @@ DBAssembler::DBAssembler(const std::string& profPath, const std::string& outputP
1642 msprofDB_.ConstructDBRunner(msprofDBPath);1595 msprofDB_.ConstructDBRunner(msprofDBPath);
1643}1596}
1644 1597 
1645-bool DBAssembler::Run(DataInventory& dataInventory)1598+bool DBAssembler::GetTopologyRoots(std::vector<TopoNodeId>& roots)
1646{1599{
1647- INFO("Start exporting db!");1600+ const size_t rootsSize = roots.size();
1648- PRINT_INFO("Start exporting the db!");1601+ for (const auto& saver : DATA_SAVER)
1649- if (CheckMsprofDb(outputPath_))
1650 {1602 {
1651- PRINT_INFO("Find completed msprof db. End exporting db output_file.");1603+ const TopoNodeId id{TopoNodeStage::DATABASE_PERSISTENCE, DB_PREFIX + saver.first};
1652- return true;1604+ if (TopoNodeRegistry::Find(id) == nullptr)
1605+ {
1606+ ERROR("DB execution list node % has no static topology registration.", id.name);
1607+ roots.resize(rootsSize);
1608+ return false;
1609+ }
1610+ roots.push_back(id);
1653 }1611 }
1654- 1612+ const TopoNodeId stringIds{TopoNodeStage::FLOW_CONTROL, DB_STRING_IDS};
1655- std::atomic<bool> retFlag(true);1613+ if (TopoNodeRegistry::Find(stringIds) == nullptr)
1656- const uint16_t processorsLimit = 10; // 最多有10个线程
1657- Analysis::Utils::ThreadPool pool(processorsLimit);
1658- pool.Start();
1659- 
1660- for (const auto& saveFunc : DATA_SAVER)
1661 {1614 {
1662- pool.AddTask(1615+ ERROR("DB StringIds node has no static topology registration.");
1663- [saveFunc, &retFlag, &dataInventory, this]()1616+ roots.resize(rootsSize);
1664- {1617+ return false;
1665- INFO("Begin to save % data.", saveFunc.first);
1666- auto flag = saveFunc.second(dataInventory, msprofDB_, profPath_);
1667- if (!flag)
1668- {
1669- ERROR("Save % data failed.", saveFunc.first);
1670- }
1671- retFlag = flag && retFlag;
1672- });
1673 }1618 }
1674- pool.WaitAllTasks();1619+ roots.push_back(stringIds);
1675- pool.Stop();1620+ return true;
1676- 1621+}
1677- // StringIds为id到name映射表,需要最后落盘1622+ 
1678- retFlag = SaveStringIdsData(dataInventory, msprofDB_, profPath_) && retFlag;1623+std::vector<TopoNodeId> DBAssembler::ResolveSelectedDBSavers(const TopoBuildContext&,
1679- PRINT_INFO("End exporting db output_file. The file is stored in the PROF file.");1624+ const std::vector<TopoNodeId>& roots)
1680- return retFlag;1625+{
1626+ std::vector<TopoNodeId> dependencies;
1627+ for (const auto& root : roots)
1628+ {
1629+ if (root.stage == TopoNodeStage::DATABASE_PERSISTENCE)
1630+ {
1631+ dependencies.push_back(root);
P
Ppanzhaohu8月10日

[review]从C++内存开销角度来看,vector容器使用emplace_back比push_back减少了一次创建对象开销,建议使用emplace_back

likedislike
Wangang Yu
Wangang Yu
8月11日 评论:
1632+ }
1633+ }
1634+ return dependencies;
1681}1635}
1682 1636 
1683-const std::set<std::string>& DBAssembler::GetProcessList() { return DB_DATA_PROCESS_LIST; }
1684} // namespace Application1637} // namespace Application
1685} // namespace Analysis1638} // namespace Analysis
@@ -17,9 +17,14 @@
17#ifndef ANALYSIS_APPLICATION_DB_ASSEMBLER_H17#ifndef ANALYSIS_APPLICATION_DB_ASSEMBLER_H
18#define ANALYSIS_APPLICATION_DB_ASSEMBLER_H18#define ANALYSIS_APPLICATION_DB_ASSEMBLER_H
19 19 
20+#include <functional>
21+#include <string>
22+#include <vector>
23+ 
20#include "analysis/csrc/application/database/msprof_db.h"24#include "analysis/csrc/application/database/msprof_db.h"
21#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h"25#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h"
22#include "analysis/csrc/infrastructure/db/include/db_info.h"26#include "analysis/csrc/infrastructure/db/include/db_info.h"
27+#include "analysis/csrc/infrastructure/process/include/topo_graph.h"
23#include "analysis/csrc/infrastructure/utils/utils.h"28#include "analysis/csrc/infrastructure/utils/utils.h"
24 29 
25namespace Analysis30namespace Analysis
@@ -28,14 +33,19 @@ namespace Application
28{33{
29using namespace Analysis::Infra;34using namespace Analysis::Infra;
30 35 
36+using DBSaveDataFunc = std::function<bool(DataInventory &dataInventory, DBInfo &msprofDB, const std::string &profPath)>;
37+ 
31class DBAssembler38class DBAssembler
32{39{
33 public:40 public:
34 DBAssembler() = default;41 DBAssembler() = default;
35 DBAssembler(const std::string &profPath, const std::string &outputPath);42 DBAssembler(const std::string &profPath, const std::string &outputPath);
36 virtual ~DBAssembler() = default;43 virtual ~DBAssembler() = default;
37- bool Run(DataInventory &dataInventory);44+ static bool GetTopologyRoots(std::vector<TopoNodeId> &roots);
38- const static std::set<std::string> &GetProcessList();45+ static std::vector<TopoNodeId> ResolveSelectedDBSavers(const TopoBuildContext &context,
46+ const std::vector<TopoNodeId> &roots);
47+ static TopoNodeCreatorFactory CreateSaver(const std::string &name);
48+ static TopoNodeCreatorFactory CreateStringIdsSaver();
39 49 
40 private:50 private:
41 std::string profPath_;51 std::string profPath_;
@@ -0,0 +1,167 @@
1+/* -------------------------------------------------------------------------
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This file is part of the MindStudio project.
4+ *
5+ * MindStudio is licensed under Mulan PSL v2.
6+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
7+ * You may obtain a copy of Mulan PSL v2 at:
8+ *
9+ * http://license.coscl.org.cn/MulanPSL2
10+ *
11+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14+ * See the Mulan PSL v2 for more details.
15+ * -------------------------------------------------------------------------*/
16+ 
17+#include "analysis/csrc/application/database/db_assembler.h"
18+#include "analysis/csrc/application/database/db_constant.h"
19+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/api_data.h"
20+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ascend_task_data.h"
21+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ccu_mission_data.h"
22+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/communication_info_data.h"
23+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/dpu_data.h"
24+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/kfc_turn_data.h"
25+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/mc2_comm_info_data.h"
26+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/memcpy_info_data.h"
27+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/msprof_tx_host_data.h"
28+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/task_info_data.h"
29+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/unified_pmu_data.h"
30+#include "analysis/csrc/domain/entities/viewer_data/system/include/acc_pmu_data.h"
31+#include "analysis/csrc/domain/entities/viewer_data/system/include/ddr_data.h"
32+#include "analysis/csrc/domain/entities/viewer_data/system/include/hbm_data.h"
33+#include "analysis/csrc/domain/entities/viewer_data/system/include/hccs_data.h"
34+#include "analysis/csrc/domain/entities/viewer_data/system/include/host_usage_data.h"
35+#include "analysis/csrc/domain/entities/viewer_data/system/include/llc_data.h"
36+#include "analysis/csrc/domain/entities/viewer_data/system/include/low_power_data.h"
37+#include "analysis/csrc/domain/entities/viewer_data/system/include/netdev_stats_data.h"
38+#include "analysis/csrc/domain/entities/viewer_data/system/include/npu_mem_data.h"
39+#include "analysis/csrc/domain/entities/viewer_data/system/include/npu_module_mem_data.h"
40+#include "analysis/csrc/domain/entities/viewer_data/system/include/npu_op_mem_data.h"
41+#include "analysis/csrc/domain/entities/viewer_data/system/include/overlap_analysis_data.h"
42+#include "analysis/csrc/domain/entities/viewer_data/system/include/pcie_data.h"
43+#include "analysis/csrc/domain/entities/viewer_data/system/include/qos_data.h"
44+#include "analysis/csrc/domain/entities/viewer_data/system/include/sio_data.h"
45+#include "analysis/csrc/domain/entities/viewer_data/system/include/soc_bandwidth_data.h"
46+#include "analysis/csrc/domain/entities/viewer_data/system/include/sys_io_data.h"
47+#include "analysis/csrc/domain/entities/viewer_data/system/include/ub_data.h"
48+ 
49+namespace Analysis
50+{
51+namespace Application
52+{
53+using namespace Analysis::Domain;
54+ 
55+namespace
56+{
57+const std::string DB_PREFIX = "DB:";
58+const std::string DB_STRING_IDS = DB_PREFIX + TABLE_NAME_STRING_IDS;
59+ 
60+} // namespace
61+ 
62+#define REGISTER_DB_SAVER(Name, Dependencies) \
63+ REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(DATABASE_PERSISTENCE, DB_PREFIX + Name), true, \
64+ DBAssembler::CreateSaver(DB_PREFIX + Name), Dependencies, nullptr)
65+ 
66+#define REGISTER_DB_SAVER_WITH_DATA(Name, Dependencies, ...) \
67+ REGISTER_DB_SAVER(Name, Dependencies); \
68+ REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(DATABASE_PERSISTENCE, DB_PREFIX + Name), __VA_ARGS__)
69+ 
70+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_API, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_API)),
71+ std::vector<ApiData>);
72+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_COMMUNICATION,
73+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMMUNICATION)),
74+ std::vector<CommunicationOpData>, std::vector<KfcOpData>,
75+ std::vector<CommunicationTaskData>, std::vector<KfcTaskData>);
76+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_ACC_PMU, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_ACC_PMU)),
77+ std::vector<AccPmuData>);
78+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_AICORE_FREQ,
79+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_AICORE_FREQ),
80+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_LOW_POWER)),
81+ std::vector<LowPowerData>);
82+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_DDR, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DDR)),
83+ std::vector<DDRData>);
84+REGISTER_DB_SAVER(PROCESSOR_NAME_ENUM, TOPO_DEPS());
85+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_HBM, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HBM)),
86+ std::vector<HbmData>);
87+REGISTER_DB_SAVER(PROCESSOR_NAME_HOST_INFO, TOPO_DEPS());
88+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_HCCS, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HCCS)),
89+ std::vector<HccsData>);
90+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NETDEV_STATS,
91+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NETDEV_STATS)),
92+ std::vector<NetDevStatsEventData>);
93+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_LLC, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_LLC)),
94+ std::vector<LLcData>);
95+REGISTER_DB_SAVER(PROCESSOR_NAME_META_DATA, TOPO_DEPS());
96+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_MSTX, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MSTX)),
97+ std::vector<MsprofTxHostData>);
98+REGISTER_DB_SAVER(PROCESSOR_NAME_NPU_INFO, TOPO_DEPS());
99+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NPU_MEM, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NPU_MEM)),
100+ std::vector<NpuMemData>);
101+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NPU_OP_MEM, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NPU_OP_MEM)),
102+ std::vector<NpuOpMemData>);
103+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NPU_MODULE_MEM,
104+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NPU_MODULE_MEM)),
105+ std::vector<NpuModuleMemData>);
106+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_PCIE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_PCIE)),
107+ std::vector<PCIeData>);
108+REGISTER_DB_SAVER(PROCESSOR_NAME_SESSION_TIME_INFO, TOPO_DEPS());
109+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_SOC, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_SOC)),
110+ std::vector<SocBandwidthData>);
111+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NIC, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NIC)),
112+ std::vector<NicOriginalData>);
113+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_ROCE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_ROCE)),
114+ std::vector<RoceOriginalData>);
115+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_DPU, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DPU)),
116+ std::vector<DPUData>);
117+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_SIO, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_SIO)),
118+ std::vector<SioData>);
119+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_UB, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_UB)),
120+ std::vector<UbData>);
121+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_TASK,
122+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK),
123+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DEVICE_TX)),
124+ std::vector<AscendTaskData>, std::vector<MsprofTxDeviceData>);
125+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_COMPUTE_TASK_INFO,
126+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO),
127+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_MC2_COMM_INFO)),
128+ std::vector<TaskInfoData>, std::vector<MC2CommInfoData>);
129+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_MEMCPY_INFO,
130+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MEMCPY_INFO)),
131+ std::vector<MemcpyInfoData>);
132+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_TASK_PMU_INFO,
133+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_UNIFIED_PMU)),
134+ std::vector<UnifiedTaskPmu>);
135+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_SAMPLE_PMU_TIMELINE,
136+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_UNIFIED_PMU)),
137+ std::vector<UnifiedSampleTimelinePmu>);
138+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_SAMPLE_PMU_SUMMARY,
139+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_UNIFIED_PMU)),
140+ std::vector<UnifiedSampleSummaryPmu>);
141+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_CPU_USAGE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_CPU_USAGE)),
142+ std::vector<CpuUsageData>);
143+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_MEM_USAGE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MEM_USAGE)),
144+ std::vector<MemUsageData>);
145+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_DISK_USAGE, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DISK_USAGE)),
146+ std::vector<DiskUsageData>);
147+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_NETWORK_USAGE,
148+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_NETWORK_USAGE)),
149+ std::vector<NetWorkUsageData>);
150+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_OSRT_API, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_OSRT_API)),
151+ std::vector<OSRuntimeApiData>);
152+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_OVERLAP_ANALYSIS,
153+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_OVERLAP_ANALYSIS)),
154+ std::vector<OverlapAnalysisData>);
155+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_QOS, TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_QOS)),
156+ std::vector<QosData>);
157+REGISTER_DB_SAVER_WITH_DATA(PROCESSOR_NAME_CCU_MISSION,
158+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_CCU_MISSION)),
159+ std::vector<CCUMissionTimelineData>);
160+ 
161+REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(FLOW_CONTROL, DB_STRING_IDS), true,
162+ DBAssembler::CreateStringIdsSaver(), TOPO_DEPS(), DBAssembler::ResolveSelectedDBSavers);
163+ 
164+#undef REGISTER_DB_SAVER_WITH_DATA
165+#undef REGISTER_DB_SAVER
166+} // namespace Application
167+} // namespace Analysis
@@ -1,4 +1,4 @@
1-/* -------------------------------------------------------------------------1+/* -------------------------------------------------------------------------
2 * Copyright (c) 2025 Huawei Technologies Co., Ltd.2 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 * This file is part of the MindStudio project.3 * This file is part of the MindStudio project.
4 *4 *
@@ -6,28 +6,32 @@
6 * You can use this software according to the terms and conditions of the Mulan PSL v2.6 * You can use this software according to the terms and conditions of the Mulan PSL v2.
7 * You may obtain a copy of Mulan PSL v2 at:7 * You may obtain a copy of Mulan PSL v2 at:
8 *8 *
9- * http://license.coscl.org.cn/MulanPSL29+ * http://license.coscl.org.cn/MulanPSL2
10 *10 *
11 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,11 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,12 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.13+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
14 * See the Mulan PSL v2 for more details.14 * See the Mulan PSL v2 for more details.
15 * -------------------------------------------------------------------------*/15 * -------------------------------------------------------------------------*/
16 16 
17#include "analysis/csrc/application/include/export_manager.h"17#include "analysis/csrc/application/include/export_manager.h"
18 18 
19-#include <atomic>19+#include <algorithm>
20+#include <memory>
21+#include <new>
22+#include <set>
23+#include <string>
24+#include <utility>
25+#include <vector>
20 26 
21#include "analysis/csrc/application/database/db_assembler.h"27#include "analysis/csrc/application/database/db_assembler.h"
22#include "analysis/csrc/application/database/db_constant.h"28#include "analysis/csrc/application/database/db_constant.h"
23#include "analysis/csrc/application/summary/summary_manager.h"29#include "analysis/csrc/application/summary/summary_manager.h"
24#include "analysis/csrc/application/timeline/json_constant.h"30#include "analysis/csrc/application/timeline/json_constant.h"
25#include "analysis/csrc/application/timeline/timeline_manager.h"31#include "analysis/csrc/application/timeline/timeline_manager.h"
26-#include "analysis/csrc/domain/data_process/ai_task/hash_init_processor.h"
27-#include "analysis/csrc/domain/data_process/include/data_processor_factory.h"
28#include "analysis/csrc/domain/services/environment/context.h"32#include "analysis/csrc/domain/services/environment/context.h"
29#include "analysis/csrc/infrastructure/dfx/error_code.h"33#include "analysis/csrc/infrastructure/dfx/error_code.h"
30-#include "analysis/csrc/infrastructure/utils/thread_pool.h"34+#include "analysis/csrc/infrastructure/process/include/process_control.h"
31 35 
32namespace Analysis36namespace Analysis
33{37{
@@ -47,64 +51,21 @@ std::string CreateOutputPath(const std::string& profPath)
47 }51 }
48 return outputPath;52 return outputPath;
49}53}
50-} // namespace
51 54 
52-bool ExportManager::ProcessData(DataInventory& dataInventory, const std::set<ExportMode>& exportModeSet)55+bool HasExportedMsprofDB(const std::string& profPath)
Y
Yyuliangbin8月10日

【review】 问题:函数名 HasExportedMsprofDB 的语义可能比实现更强,容易让调用方误解 从函数名看,它像是在判断“是否已经导出了 msprof 数据库”;但实际实现只是检查 profPath 下是否存在前缀为 DB_NAME_MSPROF_DB + "_" 且后缀为 .db 的文件。 这两者并不完全等价,例如文件可能是残留文件、空文件、半生成文件,甚至只是命名碰巧匹配。 建议: 如果当前需求只是判断“是否存在符合命名规则的 db 文件”,建议把函数名改得更贴近真实行为,比如 HasMsprofDbFile 或 ExistsExportedMsprofDbFile。 如果业务上真的要判断“已成功导出”,那应补充更严格的校验,例如文件存在性、大小、可打开性,甚至必要的 schema/表检查。

likedislike
53{56{
54- // hash数据作为其他流程的依赖数据,需要优先加载57+ const std::string dbSuffix = ".db";
55- HashInitProcessor hashProcessor(profPath_);58+ const std::vector<std::string> dbFiles = File::GetFilesWithPrefix(profPath, DB_NAME_MSPROF_DB + "_");
56- hashProcessor.Run(dataInventory, PROCESSOR_NAME_HASH);59+ return std::any_of(dbFiles.begin(), dbFiles.end(),
57- const uint16_t tableProcessors = 10; // 最多有10个线程60+ [&dbSuffix](const std::string& dbPath)
58- Analysis::Utils::ThreadPool pool(tableProcessors);61+ {
59- pool.Start();62+ return dbPath.size() >= dbSuffix.size() &&
Y
Yyuliangbin8月10日

【review】 问题:dbSuffix 用 std::string 局部变量有一点不必要的运行期开销 ".db" 是固定字面量,每次调用都构造一个 std::string dbSuffix,虽然开销不大,但属于可以顺手优化掉的细节,尤其是在高频调用场景下没必要重复分配/构造。 建议: 可以改成 constexpr std::string_view dbSuffix = ".db";,或者至少改成静态常量。 这样语义更明确,也更轻量。

likedislike
60- std::atomic<bool> retFlag(true);63+ dbPath.compare(dbPath.size() - dbSuffix.size(), dbSuffix.size(), dbSuffix) == 0;
Y
Yyuliangbin8月10日

【review】 问题:后缀匹配逻辑正确但可读性一般,维护成本略高 现在通过 dbPath.compare(dbPath.size() - dbSuffix.size(), dbSuffix.size(), dbSuffix) == 0 来判断是否以 .db 结尾,逻辑没问题,但表达稍显绕,阅读时需要停一下理解“从尾部开始比较”。 建议: 如果项目使用的 C++ 标准支持,可以考虑改成更直观的 ends-with 风格实现;如果不支持,也可以封装一个通用的 EndsWith 工具函数。 这样能让这类“后缀判断”意图更直接,减少重复样板代码。

likedislike
61- static const std::unordered_map<ExportMode, const std::set<std::string>& (*)()> processListFactory = {64+ });
62- {ExportMode::DB, &DBAssembler::GetProcessList},
63- {ExportMode::TIMELINE, &TimelineManager::GetProcessList},
64- {ExportMode::SUMMARY, &SummaryManager::GetProcessList}};
65- 
66- std::set<std::string> dataProcessList;
67- for (auto exportMode : exportModeSet)
68- {
69- auto it = processListFactory.find(exportMode);
70- if (it == processListFactory.end())
71- {
72- ERROR("Unsupported ExportMode: %.", static_cast<int>(exportMode));
73- return false;
74- }
75- auto tmpSet = it->second();
76- dataProcessList.insert(tmpSet.begin(), tmpSet.end());
77- }
78- 
79- for (const auto& name : dataProcessList)
80- {
81- pool.AddTask(
82- [this, &name, &retFlag, &dataInventory]()
83- {
84- auto processor = DataProcessorFactory::GetDataProcessByName(profPath_, name);
85- if (processor == nullptr)
86- {
87- ERROR("% is not defined", name);
88- retFlag = false;
89- return;
90- }
91- retFlag = processor->Run(dataInventory, name) && retFlag;
92- });
93- }
94- pool.WaitAllTasks();
95- pool.Stop();
96- if (!retFlag)
97- {
98- ERROR("The % for data process failed to be executed.", profPath_);
99- PRINT_ERROR(
100- "The % for data process failed to be executed. "
101- "Please check msprof_analysis_log in outputPath for more info.",
102- profPath_);
103- return false;
104- }
105- return true;
106}65}
107 66 
67+} // namespace
68+ 
108bool ExportManager::CheckProfDirsValid()69bool ExportManager::CheckProfDirsValid()
109{70{
110 if (profPath_.find("PROF") == std::string::npos)71 if (profPath_.find("PROF") == std::string::npos)
@@ -149,64 +110,106 @@ bool ExportManager::Run(const std::set<ExportMode>& exportModeSet)
149 {110 {
150 return false;111 return false;
151 }112 }
152- DataInventory dataInventory;
153- std::atomic<bool> runFlag(true);
154- runFlag = ProcessData(dataInventory, exportModeSet);
155- const std::map<ExportMode, std::function<bool(DataInventory&)>> operationMap = {
156- {ExportMode::DB,
157- [this](DataInventory& dataInventory) -> bool
158- {
159- DBAssembler dbAssembler(profPath_, profPath_);
160- return dbAssembler.Run(dataInventory);
161- }},
162- {ExportMode::TIMELINE,
163- [this](DataInventory& dataInventory) -> bool
164- {
165- std::string outputPath = CreateOutputPath(profPath_);
166- if (outputPath.empty())
167- {
168- return false;
169- }
170- TimelineManager timelineManager(profPath_, outputPath);
171- std::vector<JsonProcess> jsonProcesses = GetProcessEnum();
172- return timelineManager.Run(dataInventory, jsonProcesses);
173- }},
174- {ExportMode::SUMMARY,
175- [this](DataInventory& dataInventory) -> bool
176- {
177- std::string outputPath = CreateOutputPath(profPath_);
178- if (outputPath.empty())
179- {
180- return false;
181- }
182- SummaryManager summaryManager(profPath_, outputPath);
183- return summaryManager.Run(dataInventory);
184- }},
185- };
186 113 
187- const uint16_t processorsLimit = 3; // 最多有3个线程114+ ExportSelection selection;
188- Analysis::Utils::ThreadPool pool(processorsLimit);115+ if (!GetExportSelection(exportModeSet, selection))
189- pool.Start();116+ {
117+ return false;
118+ }
119+ 
120+ TopoBuildContext buildContext;
121+ buildContext.profPath = profPath_;
122+ buildContext.outputPath = profPath_;
123+ buildContext.timelineProcesses = selection.timelineProcesses;
124+ std::vector<TopoNodeId> roots;
190 for (const auto& exportMode : exportModeSet)125 for (const auto& exportMode : exportModeSet)
191 {126 {
192- auto iter = operationMap.find(exportMode);127+ switch (exportMode)
193- if (iter != operationMap.end())
194 {128 {
195- pool.AddTask([iter, &runFlag, &dataInventory]() { runFlag = iter->second(dataInventory) && runFlag; });129+ case ExportMode::DB:
W
Wwangzixuan8月7日

[review] 这里逻辑依然保留了原本的exportManager的流程。本质还是将timeline和summary导出分作两个大流程处理。当前pr先保持原有能力的前后一致性。后续需要考虑将导出流程归一,一次导出所有交付件,减少导出重复无意义开销,将导出能力彻底归一。

likedislike
130+ {
131+ if (HasExportedMsprofDB(profPath_))
132+ {
133+ INFO("The exported msprof db already exists, skip DB export.");
134+ break;
hhz0
hhz0hhz08月10日

[review] 问题: 这里 检测到已有 DB 后只执行 break,没有添加任何拓扑根节点。随后 topo_graph.cpp (line 131) 会因为 roots.empty() 返回失败。 影响: 用户再次执行仅 DB 导出时,日志提示“skip DB export”,但最终命令仍然失败,与原来已有完整 DB 时返回成功的行为不一致。 修改建议: 记录“DB 已存在且成功跳过”的状态。当所有请求项都已完成、没有待执行根节点时直接返回成功。补充“仅请求 DB 且 DB 已存在”的单测。

likedislike
135+ }
136+ buildContext.dbSession =
137+ std::shared_ptr<DBAssembler>(new (std::nothrow) DBAssembler(profPath_, profPath_));
138+ if (buildContext.dbSession == nullptr || !DBAssembler::GetTopologyRoots(roots))
139+ {
140+ ERROR("Build DB topology roots failed.");
141+ return false;
142+ }
143+ break;
144+ }
145+ case ExportMode::TIMELINE:
146+ {
147+ const std::string outputPath = CreateOutputPath(profPath_);
148+ if (outputPath.empty())
149+ {
150+ return false;
151+ }
152+ buildContext.outputPath = outputPath;
153+ buildContext.timelineSession =
154+ std::shared_ptr<TimelineManager>(new (std::nothrow) TimelineManager(profPath_, outputPath));
155+ if (buildContext.timelineSession == nullptr ||
156+ !TimelineManager::GetTopologyRoots(selection.timelineProcesses, roots))
157+ {
158+ return false;
159+ }
160+ break;
161+ }
162+ case ExportMode::SUMMARY:
163+ if (CreateOutputPath(profPath_).empty() ||
Mrtutu
MrtutuMrtutu8月10日

严重程度: 建议

问题: ExportMode::SUMMARY 分支调用 CreateOutputPath(profPath_) 仅检查返回值是否为空,但丢弃了实际输出路径,buildContext.outputPath 保持为 profPath_(行 118 的默认值)。而 ExportMode::TIMELINE 分支(行 148)会更新 buildContext.outputPath = outputPath,二者处理方式不一致。

原因: 当前 SummaryManager::CreateSummaryAssembler 只捕获 context.profPath,行为与基线一致,暂无功能影响。但 buildContext.outputPath 对 TIMELINE 更新、对 SUMMARY 不更新的不一致性,容易误导后续新增的汇总装配器——若新装配器按设计意图使用 context.outputPath,在 SUMMARY 单独导出时会拿到 profPath_(PROF 根目录)而非 mindstudio_profiler_output 子目录,导致输出位置错误。

怎么改: 与 TIMELINE 分支保持一致,捕获并赋值输出路径:

case ExportMode::SUMMARY:
{
    const std::string outputPath = CreateOutputPath(profPath_);
    if (outputPath.empty() || !SummaryManager::GetTopologyRoots(selection.summaryDeliverables, roots))
    {
        return false;
    }
    buildContext.outputPath = outputPath;
    break;
}

即使当前汇总装配器不使用 outputPath,保持 buildContext 语义一致也能降低后续维护风险。

likedislike
164+ !SummaryManager::GetTopologyRoots(selection.summaryDeliverables, roots))
165+ {
166+ return false;
167+ }
168+ break;
169+ default:
170+ ERROR("Unsupported ExportMode: %.", static_cast<int>(exportMode));
171+ return false;
196 }172 }
197 }173 }
198- pool.WaitAllTasks();174+ 
199- pool.Stop();175+ Infra::ProcessCollection processes;
200- return runFlag;176+ TopoGraphBuilder graphBuilder;
177+ if (!graphBuilder.Build(buildContext, roots, processes))
178+ {
179+ ERROR("Build export topology failed.");
180+ return false;
181+ }
182+ 
183+ DataInventory dataInventory;
184+ Infra::Context context;
185+ Infra::ProcessControl processControl(processes);
186+ if (!processControl.ExecuteProcess(dataInventory, context))
187+ {
188+ ERROR("The % export topology failed to be executed.", profPath_);
189+ PRINT_ERROR(
190+ "The % for export failed to be executed. "
191+ "Please check msprof_analysis_log in outputPath for more info.",
192+ profPath_);
193+ return false;
194+ }
195+ return true;
201}196}
202 197 
203-std::vector<JsonProcess> ExportManager::GetProcessEnum()198+bool ExportManager::GetExportSelection(const std::set<ExportMode>& exportModeSet, ExportSelection& selection)
204{199{
200+ selection.timelineProcesses.clear();
201+ selection.summaryDeliverables.clear();
202+ const bool exportTimeline = exportModeSet.find(ExportMode::TIMELINE) != exportModeSet.end();
203+ const bool exportSummary = exportModeSet.find(ExportMode::SUMMARY) != exportModeSet.end();
204+ if (exportTimeline)
205+ {
206+ selection.timelineProcesses = allProcesses;
207+ }
205 if (jsonPath_.empty())208 if (jsonPath_.empty())
206 {209 {
207 INFO("The report parameter is not used.");210 INFO("The report parameter is not used.");
208 PRINT_INFO("The report parameter is not used.");211 PRINT_INFO("The report parameter is not used.");
209- return allProcesses;212+ return true;
210 }213 }
211 FileReader fd(jsonPath_);214 FileReader fd(jsonPath_);
212 nlohmann::json config;215 nlohmann::json config;
@@ -214,41 +217,107 @@ std::vector<JsonProcess> ExportManager::GetProcessEnum()
214 {217 {
215 ERROR("Load report config failed: '%'.", jsonPath_);218 ERROR("Load report config failed: '%'.", jsonPath_);
216 PRINT_ERROR("Load report config failed: '%'.", jsonPath_);219 PRINT_ERROR("Load report config failed: '%'.", jsonPath_);
217- return allProcesses;220+ return true;
218 }221 }
219- auto jsonProcessConfig = config["json_process"];222+ 
220- if (jsonProcessConfig.is_null() || !jsonProcessConfig.is_object() || jsonProcessConfig.empty())223+ if (exportTimeline)
221 {224 {
222- INFO("The json_process is not exist.");225+ const auto jsonProcessConfig = config["json_process"];
223- PRINT_INFO("The json_process is not exist.");226+ if (jsonProcessConfig.is_null() || !jsonProcessConfig.is_object() || jsonProcessConfig.empty())
224- return allProcesses;
225- }
226- std::vector<JsonProcess> jsonProcesses;
227- for (nlohmann::json::iterator it = jsonProcessConfig.begin(); it != jsonProcessConfig.end(); ++it)
228- {
229- if (strToJsonProcess.find(it.key()) == strToJsonProcess.end())
230 {227 {
231- ERROR("Json process contains invalid key.");228+ INFO("The json_process is not exist.");
232- PRINT_ERROR("Json process contains invalid key.");229+ PRINT_INFO("The json_process is not exist.");
233- return allProcesses;
234 }230 }
235- if (!it.value().is_boolean())231+ else
236 {232 {
237- ERROR("Json contains invalid value, only the bool type is supported.");233+ std::vector<JsonProcess> jsonProcesses;
238- PRINT_ERROR("Json contains invalid value, only the bool type is supported.");234+ bool valid = true;
239- return allProcesses;235+ for (nlohmann::json::const_iterator it = jsonProcessConfig.begin(); it != jsonProcessConfig.end(); ++it)
240- }
241- if (it.value())
242- {
243- auto processEnum = strToJsonProcess.at(it.key());
244- jsonProcesses.push_back(processEnum);
245- if (it.key() == "freq")
246 {236 {
247- jsonProcesses.push_back(JsonProcess::LOW_POWER);237+ if (strToJsonProcess.find(it.key()) == strToJsonProcess.end())
238+ {
239+ ERROR("Json process contains invalid key.");
240+ PRINT_ERROR("Json process contains invalid key.");
241+ valid = false;
242+ break;
243+ }
244+ if (!it.value().is_boolean())
245+ {
246+ ERROR("Json contains invalid value, only the bool type is supported.");
247+ PRINT_ERROR("Json contains invalid value, only the bool type is supported.");
248+ valid = false;
249+ break;
250+ }
251+ if (it.value())
252+ {
253+ const auto processEnum = strToJsonProcess.at(it.key());
254+ jsonProcesses.emplace_back(processEnum);
255+ if (it.key() == "freq")
256+ {
257+ jsonProcesses.emplace_back(JsonProcess::LOW_POWER);
258+ }
259+ }
260+ }
261+ if (valid)
262+ {
263+ if (jsonProcesses.empty())
264+ {
265+ ERROR("Json process has no enabled timeline deliverable.");
266+ return false;
267+ }
268+ selection.timelineProcesses = std::move(jsonProcesses);
248 }269 }
249 }270 }
250 }271 }
251- return std::move(jsonProcesses);272+ 
273+ if (exportSummary)
274+ {
275+ const auto summaryProcessConfig = config["summary_process"];
276+ if (summaryProcessConfig.is_null())
277+ {
278+ return true;
279+ }
280+ if (!summaryProcessConfig.is_object())
281+ {
282+ ERROR("Summary process must be a JSON object.");
283+ PRINT_ERROR("Summary process must be a JSON object.");
284+ return false;
285+ }
286+ if (summaryProcessConfig.empty())
287+ {
288+ INFO("The summary_process is empty.");
289+ PRINT_INFO("The summary_process is empty.");
290+ return true;
291+ }
292+ 
293+ std::vector<std::string> summaryDeliverables;
294+ for (nlohmann::json::const_iterator it = summaryProcessConfig.begin(); it != summaryProcessConfig.end(); ++it)
295+ {
296+ if (!SummaryManager::IsDeliverableSupported(it.key()))
297+ {
298+ ERROR("Summary process contains invalid key.");
299+ PRINT_ERROR("Summary process contains invalid key.");
300+ return false;
301+ }
302+ if (!it.value().is_boolean())
303+ {
304+ ERROR("Summary process value must be bool.");
305+ PRINT_ERROR("Summary process value must be bool.");
306+ return false;
307+ }
308+ if (it.value())
309+ {
310+ summaryDeliverables.emplace_back(it.key());
311+ }
312+ }
313+ if (summaryDeliverables.empty())
314+ {
315+ ERROR("Summary process has no enabled deliverable.");
316+ return false;
317+ }
318+ selection.summaryDeliverables = std::move(summaryDeliverables);
319+ }
320+ return true;
252}321}
253} // namespace Application322} // namespace Application
254} // namespace Analysis323} // namespace Analysis
@@ -17,32 +17,45 @@
17#ifndef ANALYSIS_APPLICATION_EXPORT_MANAGER_H17#ifndef ANALYSIS_APPLICATION_EXPORT_MANAGER_H
18#define ANALYSIS_APPLICATION_EXPORT_MANAGER_H18#define ANALYSIS_APPLICATION_EXPORT_MANAGER_H
19 19 
20+#include <set>
20#include <string>21#include <string>
21-#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h"22+#include <vector>
22-#include "analysis/csrc/application/timeline/json_process_enum.h"
23-#include "analysis/csrc/application/include/export_mode_enum.h"
24 23 
25-namespace Analysis {24+#include "analysis/csrc/application/include/export_mode_enum.h"
26-namespace Application {25+#include "analysis/csrc/application/timeline/json_process_enum.h"
26+#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h"
27+ 
28+namespace Analysis
29+{
30+namespace Application
31+{
27using namespace Analysis::Infra;32using namespace Analysis::Infra;
28-class ExportManager {33+ 
29-public:34+struct ExportSelection
30- explicit ExportManager(const std::string &profPath) : profPath_(profPath) {}35+{
31- ExportManager(const std::string& profPath, const std::string& jsonPath) : profPath_(profPath),36+ std::vector<JsonProcess> timelineProcesses;
32- jsonPath_(jsonPath)37+ std::vector<std::string> summaryDeliverables;
33- {}38+};
39+ 
40+class ExportManager
41+{
42+ public:
43+ explicit ExportManager(const std::string& profPath) : profPath_(profPath) {}
44+ ExportManager(const std::string& profPath, const std::string& jsonPath) : profPath_(profPath), jsonPath_(jsonPath)
45+ {
46+ }
34 bool Run(const std::set<ExportMode>& exportModeSet);47 bool Run(const std::set<ExportMode>& exportModeSet);
35-private:48+ bool GetExportSelection(const std::set<ExportMode>& exportModeSet, ExportSelection& selection);
49+ 
50+ private:
36 bool Init();51 bool Init();
37 bool CheckProfDirsValid();52 bool CheckProfDirsValid();
38- bool ProcessData(DataInventory &dataInventory, const std::set<ExportMode>& exportModeSet);
39- std::vector<JsonProcess> GetProcessEnum();
40 53 
41-private:54+ private:
42 std::string profPath_;55 std::string profPath_;
43 std::string jsonPath_;56 std::string jsonPath_;
44};57};
45-}58+} // namespace Application
46-}59+} // namespace Analysis
47 60 
48-#endif // ANALYSIS_APPLICATION_EXPORT_MANAGER_H61+#endif // ANALYSIS_APPLICATION_EXPORT_MANAGER_H
@@ -16,10 +16,13 @@
16 16 
17#include "analysis/csrc/application/summary/summary_manager.h"17#include "analysis/csrc/application/summary/summary_manager.h"
18 18 
19-#include <atomic>19+#include <set>
20+#include <string>
21+#include <unordered_map>
22+#include <vector>
20 23 
21#include "analysis/csrc/application/summary/summary_factory.h"24#include "analysis/csrc/application/summary/summary_factory.h"
22-#include "analysis/csrc/infrastructure/utils/thread_pool.h"25+#include "analysis/csrc/infrastructure/process/include/topo_callback_process.h"
23 26 
24namespace Analysis27namespace Analysis
25{28{
@@ -27,81 +30,101 @@ namespace Application
27{30{
28namespace31namespace
29{32{
30-using namespace Utils;
31-const uint8_t PROCESSOR_POOL_NUM = 5;
32const std::vector<std::string> DATA_ASSEMBLE_LIST{PROCESSOR_OP_SUMMARY, PROCESSOR_NAME_COMM_STATISTIC,33const std::vector<std::string> DATA_ASSEMBLE_LIST{PROCESSOR_OP_SUMMARY, PROCESSOR_NAME_COMM_STATISTIC,
33 PROCESSOR_NAME_OP_STATISTIC, PROCESSOR_NAME_NPU_MEM,34 PROCESSOR_NAME_OP_STATISTIC, PROCESSOR_NAME_NPU_MEM,
34 PROCESSOR_NAME_NPU_MODULE_MEM, PROCESSOR_NAME_API,35 PROCESSOR_NAME_NPU_MODULE_MEM, PROCESSOR_NAME_API,
35 PROCESSOR_NAME_FUSION_OP, PROCESSOR_TASK_TIME_SUMMARY,36 PROCESSOR_NAME_FUSION_OP, PROCESSOR_TASK_TIME_SUMMARY,
36 PROCESSOR_NAME_STEP_TRACE, PROCESSOR_NAME_PAGE_FAULT};37 PROCESSOR_NAME_STEP_TRACE, PROCESSOR_NAME_PAGE_FAULT};
37 38 
38-const std::set<std::string> SUMMARY_DATA_PROCESS_LIST{PROCESSOR_NAME_COMMUNICATION,39+const std::unordered_map<std::string, std::string> SUMMARY_DELIVERABLES{
39- PROCESSOR_NAME_COMPUTE_TASK_INFO,40+ {"op_summary", PROCESSOR_OP_SUMMARY},
40- PROCESSOR_NAME_TASK,41+ {"comm_statistic", PROCESSOR_NAME_COMM_STATISTIC},
41- PROCESSOR_PMU,42+ {"op_statistic", PROCESSOR_NAME_OP_STATISTIC},
42- PROCESSOR_NAME_COMM_STATISTIC,43+ {"npu_memory", PROCESSOR_NAME_NPU_MEM},
43- PROCESSOR_NAME_OP_STATISTIC,44+ {"npu_module_memory", PROCESSOR_NAME_NPU_MODULE_MEM},
44- PROCESSOR_NAME_NPU_MEM,45+ {"api_statistic", PROCESSOR_NAME_API},
45- PROCESSOR_NAME_NPU_MODULE_MEM,46+ {"fusion_op", PROCESSOR_NAME_FUSION_OP},
46- PROCESSOR_NAME_API,47+ {"task_time", PROCESSOR_TASK_TIME_SUMMARY},
47- PROCESSOR_NAME_FUSION_OP,48+ {"step_trace", PROCESSOR_NAME_STEP_TRACE},
48- PROCESSOR_NAME_MODEL_NAME,49+ {"page_fault", PROCESSOR_NAME_PAGE_FAULT},
49- PROCESSOR_NAME_STEP_TRACE,50+};
50- PROCESSOR_HOST_TASK,51+ 
51- PROCESSOR_NAME_PAGE_FAULT};
52} // namespace52} // namespace
53 53 
54-bool SummaryManager::Run(DataInventory& dataInventory)54+bool SummaryManager::IsDeliverableSupported(const std::string& deliverableName)
55{55{
56- INFO("Start exporting summary!");56+ return SUMMARY_DELIVERABLES.find(deliverableName) != SUMMARY_DELIVERABLES.end();
57- PRINT_INFO("Start exporting the summary!");57+}
58- bool runFlag = ProcessSummary(dataInventory);58+ 
59- if (!runFlag)59+bool SummaryManager::GetTopologyRoots(const std::vector<std::string>& deliverableNames, std::vector<TopoNodeId>& roots)
60+{
61+ const size_t rootsSize = roots.size();
62+ std::vector<std::string> assemblerNames;
63+ if (!GetAssemblerList(deliverableNames, assemblerNames))
60 {64 {
61- ERROR("The unified summary process failed to be executed.");
62- PRINT_ERROR(
63- "The unified summary process failed to be executed. "
64- "Please check msprof_analysis_log in outputPath for more info.");
65 return false;65 return false;
66 }66 }
67- PRINT_INFO("End exporting summary output_file. The file is stored in the PROF file.");67+ for (const auto& name : assemblerNames)
68+ {
69+ const TopoNodeId id{TopoNodeStage::SUMMARY_GENERATION, name};
70+ if (TopoNodeRegistry::Find(id) == nullptr)
71+ {
72+ ERROR("Summary execution list node % has no static topology registration.", name);
73+ roots.resize(rootsSize);
74+ return false;
75+ }
76+ roots.push_back(id);
77+ }
68 return true;78 return true;
69}79}
70 80 
71-bool SummaryManager::ProcessSummary(Analysis::Infra::DataInventory& dataInventory)81+bool SummaryManager::GetAssemblerList(const std::vector<std::string>& deliverableNames,
82+ std::vector<std::string>& assemblerNames)
72{83{
73- Analysis::Utils::ThreadPool pool(PROCESSOR_POOL_NUM);84+ assemblerNames.clear();
74- pool.Start();85+ if (deliverableNames.empty())
75- std::atomic<bool> retFlag(true);
76- for (const auto& name : DATA_ASSEMBLE_LIST)
77 {86 {
78- pool.AddTask(87+ assemblerNames = DATA_ASSEMBLE_LIST;
79- [this, &name, &retFlag, &dataInventory]()88+ return true;
80- {89+ }
81- auto assembler = SummaryFactory::GetAssemblerByName(name, profPath_);90+ 
82- if (assembler == nullptr)91+ std::set<std::string> selectedAssemblers;
92+ for (const auto& deliverableName : deliverableNames)
93+ {
94+ const auto deliverableIter = SUMMARY_DELIVERABLES.find(deliverableName);
95+ if (deliverableIter == SUMMARY_DELIVERABLES.end())
96+ {
97+ ERROR("Summary deliverable % is not supported.", deliverableName);
98+ return false;
99+ }
100+ if (selectedAssemblers.insert(deliverableIter->second).second)
101+ {
102+ assemblerNames.emplace_back(deliverableIter->second);
103+ }
104+ }
105+ return true;
106+}
107+ 
108+TopoNodeCreatorFactory SummaryManager::CreateSummaryAssembler(const std::string& name)
109+{
110+ return [name](const TopoBuildContext& context)
111+ {
112+ const std::string profPath = context.profPath;
113+ return [name, profPath]() -> std::unique_ptr<Infra::Process>
114+ {
115+ return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess(
116+ [name, profPath](DataInventory& dataInventory) -> bool
83 {117 {
84- ERROR("% is not defined", name);118+ const auto assembler = SummaryFactory::GetAssemblerByName(name, profPath);
85- retFlag = false;119+ if (assembler == nullptr)
86- return;120+ {
87- }121+ ERROR("% is not defined", name);
88- retFlag = assembler->Run(dataInventory) && retFlag;122+ return false;
89- });123+ }
90- }124+ return assembler->Run(dataInventory);
91- pool.WaitAllTasks();125+ }));
92- pool.Stop();126+ };
93- if (!retFlag)127+ };
94- {
95- ERROR("The % for summary assemble failed to be executed.", profPath_);
96- PRINT_ERROR(
97- "The % for summary assemble failed to be executed. "
98- "Please check msprof_analysis_log in outputPath for more info.",
99- profPath_);
100- return false;
101- }
102- return true;
103}128}
104- 
105-const std::set<std::string>& SummaryManager::GetProcessList() { return SUMMARY_DATA_PROCESS_LIST; }
106} // namespace Application129} // namespace Application
107} // namespace Analysis130} // namespace Analysis
@@ -17,26 +17,35 @@
17#ifndef ANALYSIS_APPLICATION_SUMMARY_MANAGER_H17#ifndef ANALYSIS_APPLICATION_SUMMARY_MANAGER_H
18#define ANALYSIS_APPLICATION_SUMMARY_MANAGER_H18#define ANALYSIS_APPLICATION_SUMMARY_MANAGER_H
19 19 
20+#include <set>
20#include <string>21#include <string>
21#include <utility>22#include <utility>
22-#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h"23+#include <vector>
23 24 
24-namespace Analysis {25+#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h"
25-namespace Application {26+#include "analysis/csrc/infrastructure/process/include/topo_graph.h"
27+ 
28+namespace Analysis
29+{
30+namespace Application
31+{
26using namespace Analysis::Infra;32using namespace Analysis::Infra;
27 33 
28-class SummaryManager {34+class SummaryManager
29-public:35+{
36+ public:
30 explicit SummaryManager(const std::string& profPath, const std::string& outputPath)37 explicit SummaryManager(const std::string& profPath, const std::string& outputPath)
31 : profPath_(profPath), outputPath_(outputPath) {};38 : profPath_(profPath), outputPath_(outputPath) {};
32- bool Run(DataInventory& dataInventory);39+ static bool IsDeliverableSupported(const std::string& deliverableName);
33- const static std::set<std::string>& GetProcessList();40+ static TopoNodeCreatorFactory CreateSummaryAssembler(const std::string& name);
34-private:41+ static bool GetAssemblerList(const std::vector<std::string>& deliverableNames,
35- bool ProcessSummary(DataInventory& dataInventory);42+ std::vector<std::string>& assemblerNames);
36-private:43+ static bool GetTopologyRoots(const std::vector<std::string>& deliverableNames, std::vector<TopoNodeId>& roots);
44+ 
45+ private:
37 std::string profPath_;46 std::string profPath_;
38 std::string outputPath_;47 std::string outputPath_;
39};48};
40-}49+} // namespace Application
41-}50+} // namespace Analysis
42-#endif // ANALYSIS_APPLICATION_SUMMARY_MANAGER_H51+#endif // ANALYSIS_APPLICATION_SUMMARY_MANAGER_H
@@ -0,0 +1,94 @@
1+/* -------------------------------------------------------------------------
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This file is part of the MindStudio project.
4+ *
5+ * MindStudio is licensed under Mulan PSL v2.
6+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
7+ * You may obtain a copy of Mulan PSL v2 at:
8+ *
9+ * http://license.coscl.org.cn/MulanPSL2
10+ *
11+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14+ * See the Mulan PSL v2 for more details.
15+ * -------------------------------------------------------------------------*/
16+ 
17+#include <unordered_map>
18+ 
19+#include "analysis/csrc/application/database/db_constant.h"
20+#include "analysis/csrc/application/summary/summary_manager.h"
21+#include "analysis/csrc/domain/entities/hal/include/ascend_obj.h"
22+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/api_data.h"
23+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ascend_task_data.h"
24+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/communication_info_data.h"
25+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/fusion_op_data.h"
26+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/hccl_statistic_data.h"
27+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/metric_summary.h"
28+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/model_name_data.h"
29+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/op_statistic_data.h"
30+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/step_trace_data.h"
31+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/task_info_data.h"
32+#include "analysis/csrc/domain/entities/viewer_data/system/include/npu_mem_data.h"
33+#include "analysis/csrc/domain/entities/viewer_data/system/include/npu_module_mem_data.h"
34+#include "analysis/csrc/domain/entities/viewer_data/system/include/page_fault_data.h"
35+ 
36+namespace Analysis
37+{
38+namespace Application
39+{
40+namespace
41+{
42+using namespace Analysis::Domain;
43+using StringMap = std::unordered_map<std::string, std::string>;
44+ 
45+} // namespace
46+ 
47+REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_OP_SUMMARY), true,
48+ SummaryManager::CreateSummaryAssembler(PROCESSOR_OP_SUMMARY),
49+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO),
50+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK),
51+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMMUNICATION),
52+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_PMU)),
53+ nullptr);
54+REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_OP_SUMMARY), std::vector<TaskInfoData>,
55+ std::vector<AscendTaskData>, std::vector<CommunicationOpData>, MetricSummary);
56+ 
57+#define REGISTER_SIMPLE_SUMMARY_NODE(Name, DataType, Dependency) \
58+ REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(SUMMARY_GENERATION, Name), true, \
59+ SummaryManager::CreateSummaryAssembler(Name), \
60+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, Dependency)), nullptr); \
61+ REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(SUMMARY_GENERATION, Name), DataType)
62+ 
63+REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_COMM_STATISTIC, std::vector<HcclStatisticData>,
64+ PROCESSOR_NAME_COMM_STATISTIC);
65+REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_OP_STATISTIC, std::vector<OpStatisticData>, PROCESSOR_NAME_OP_STATISTIC);
66+REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_NPU_MEM, std::vector<NpuMemData>, PROCESSOR_NAME_NPU_MEM);
67+REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_NPU_MODULE_MEM, std::vector<NpuModuleMemData>,
68+ PROCESSOR_NAME_NPU_MODULE_MEM);
69+REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_API, std::vector<ApiData>, PROCESSOR_NAME_API);
70+REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_STEP_TRACE, std::vector<TrainTraceData>, PROCESSOR_NAME_STEP_TRACE);
hhz0
hhz0hhz08月10日

[review] 问题: 这里只登记了 std::vector,但 summary_step_trace_assembler.cpp (line 66)还读取 std::vector。逐层回收逻辑会删除未登记的数据。 影响: 仅导出 summary 时,AllReduceData 会在 Step Trace assembler 执行前被释放,最终 CSV 缺少 Reduce Start、Reduce Duration 等通信信息,并打印误导性的“未采集 all reduce”告警。 修改建议: 登记完整输入类型。

likedislike
71+REGISTER_SIMPLE_SUMMARY_NODE(PROCESSOR_NAME_PAGE_FAULT, std::vector<PageFaultData>, PROCESSOR_NAME_PAGE_FAULT);
72+ 
73+REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_NAME_FUSION_OP), true,
74+ SummaryManager::CreateSummaryAssembler(PROCESSOR_NAME_FUSION_OP),
75+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_FUSION_OP),
76+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MODEL_NAME),
77+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HASH)),
78+ nullptr);
79+REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_NAME_FUSION_OP), std::vector<FusionOpInfo>,
80+ std::vector<ModelName>, StringMap);
81+ 
82+REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_TASK_TIME_SUMMARY), true,
83+ SummaryManager::CreateSummaryAssembler(PROCESSOR_TASK_TIME_SUMMARY),
84+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO),
85+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_HOST_TASK),
86+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK)),
87+ nullptr);
88+REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(SUMMARY_GENERATION, PROCESSOR_TASK_TIME_SUMMARY), std::vector<TaskInfoData>,
89+ std::vector<HostTask>, std::vector<AscendTaskData>);
90+ 
91+#undef REGISTER_SIMPLE_SUMMARY_NODE
92+ 
93+} // namespace Application
94+} // namespace Analysis
@@ -16,6 +16,10 @@
16#ifndef ANALYSIS_APPLICATION_EXPORT_JSON_ENUM_H16#ifndef ANALYSIS_APPLICATION_EXPORT_JSON_ENUM_H
17#define ANALYSIS_APPLICATION_EXPORT_JSON_ENUM_H17#define ANALYSIS_APPLICATION_EXPORT_JSON_ENUM_H
18 18 
19+#include <string>
20+#include <unordered_map>
21+#include <vector>
22+ 
19namespace Analysis23namespace Analysis
20{24{
21namespace Application25namespace Application
@@ -18,7 +18,6 @@
18#include <set>18#include <set>
19 19 
20#include "analysis/csrc/application/database/db_constant.h"20#include "analysis/csrc/application/database/db_constant.h"
21-#include "analysis/csrc/domain/data_process/ai_task/overlap_analysis_processor.h"
22#include "analysis/csrc/domain/services/environment/context.h"21#include "analysis/csrc/domain/services/environment/context.h"
23#include "analysis/csrc/infrastructure/utils/time_logger.h"22#include "analysis/csrc/infrastructure/utils/time_logger.h"
24 23 
@@ -104,16 +103,6 @@ uint8_t OverlapAnalysisAssembler::AssembleData(DataInventory &dataInventory, Jso
104 const std::string &profPath)103 const std::string &profPath)
105{104{
106 auto overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>();105 auto overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>();
107- if (!overlapData)
108- {
109- OverlapAnalysisProcessor processor(profPath);
110- if (!processor.Run(dataInventory, PROCESSOR_NAME_OVERLAP_ANALYSIS))
111- {
112- ERROR("Process overlap analysis data failed.");
113- return ASSEMBLE_FAILED;
114- }
115- overlapData = dataInventory.GetPtr<std::vector<OverlapAnalysisData>>();
116- }
117 if (!overlapData || overlapData->empty())106 if (!overlapData || overlapData->empty())
118 {107 {
119 WARN("No overlap analysis data found.");108 WARN("No overlap analysis data found.");
@@ -16,12 +16,15 @@
16 16 
17#include "analysis/csrc/application/timeline/timeline_manager.h"17#include "analysis/csrc/application/timeline/timeline_manager.h"
18 18 
19-#include <atomic>19+#include <algorithm>
20+#include <set>
21+#include <string>
22+#include <unordered_map>
23+#include <vector>
20 24 
21#include "analysis/csrc/application/timeline/timeline_factory.h"25#include "analysis/csrc/application/timeline/timeline_factory.h"
22#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/msprof_tx_host_data.h"26#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/msprof_tx_host_data.h"
23-#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/step_trace_data.h"27+#include "analysis/csrc/infrastructure/process/include/topo_callback_process.h"
24-#include "analysis/csrc/infrastructure/utils/thread_pool.h"
25 28 
26namespace Analysis29namespace Analysis
27{30{
@@ -32,8 +35,9 @@ namespace
32const std::string PREFIX_CONTEXT = "[";35const std::string PREFIX_CONTEXT = "[";
33const std::string SUFFIX_CONTEXT = "]";36const std::string SUFFIX_CONTEXT = "]";
34const int JSON_FILE_OFFSET = -1;37const int JSON_FILE_OFFSET = -1;
35-// 数据中心中最少也会有hash类数据38+const std::string TIMELINE_PREFIX = "TIMELINE:";
36-const size_t MIN_NUM_FOR_IOC = std::set<std::string>{PROCESSOR_NAME_HASH}.size();39+const std::string TIMELINE_PRE_DUMP = TIMELINE_PREFIX + "PRE_DUMP";
40+const std::string TIMELINE_POST_DUMP = TIMELINE_PREFIX + "POST_DUMP";
37 41 
38const std::unordered_map<JsonProcess, std::string> JSON_TO_ASSEMBLER_TABLE{42const std::unordered_map<JsonProcess, std::string> JSON_TO_ASSEMBLER_TABLE{
39 {JsonProcess::ASCEND, PROCESS_TASK},43 {JsonProcess::ASCEND, PROCESS_TASK},
@@ -71,86 +75,8 @@ const std::unordered_map<JsonProcess, std::string> JSON_TO_ASSEMBLER_TABLE{
71 {JsonProcess::FUSION_TASK, PROCESS_FUSION_TASK},75 {JsonProcess::FUSION_TASK, PROCESS_FUSION_TASK},
72};76};
73 77 
74-std::set<std::string> TIMELINE_DATA_PROCESS_LIST{
75- PROCESSOR_NAME_API,
76- PROCESSOR_NAME_DPU,
77- PROCESSOR_NAME_FUSION_TASK,
78- PROCESSOR_NAME_COMMUNICATION,
79- PROCESSOR_NAME_CCU_MISSION,
80- PROCESSOR_NAME_COMPUTE_TASK_INFO,
81- PROCESSOR_NAME_KFC_TASK,
82- PROCESSOR_NAME_DEVICE_TX,
83- PROCESSOR_NAME_MSTX,
84- PROCESSOR_NAME_STEP_TRACE,
85- PROCESSOR_NAME_TASK,
86- PROCESSOR_NAME_ACC_PMU,
87- PROCESSOR_NAME_AICORE_FREQ,
88- PROCESSOR_NAME_CHIP_TRAINS,
89- PROCESSOR_NAME_DDR,
90- PROCESSOR_NAME_HBM,
91- PROCESSOR_NAME_HCCS,
92- PROCESSOR_NAME_CPU_USAGE,
93- PROCESSOR_NAME_MEM_USAGE,
94- PROCESSOR_NAME_DISK_USAGE,
95- PROCESSOR_NAME_NETWORK_USAGE,
96- PROCESSOR_NAME_OSRT_API,
97- PROCESSOR_NAME_LLC,
98- PROCESSOR_NAME_NPU_MEM,
99- PROCESSOR_NAME_PCIE,
100- PROCESSOR_NAME_SIO,
101- PROCESSOR_NAME_SOC,
102- PROCESSOR_NAME_NIC,
103- PROCESSOR_NAME_ROCE,
104- PROCESSOR_NAME_QOS,
105- PROCESSOR_MC2_COMM_INFO,
106- PROCESSOR_NAME_MEMCPY_INFO,
107- PROCESSOR_NAME_NPU_OP_MEM,
108- PROCESSOR_NAME_NPU_MODULE_MEM,
109- PROCESSOR_NAME_NIC_TIMELINE,
110- PROCESSOR_NAME_ROCE_TIMELINE,
111- PROCESSOR_NAME_LOW_POWER,
112- PROCESSOR_NAME_BIU_PERF,
113- PROCESSOR_NAME_UB,
114- PROCESSOR_NAME_BLOCK_DETAIL,
115-};
116} // namespace78} // namespace
117 79 
118-bool TimelineManager::ProcessTimeLine(DataInventory& dataInventory, const std::vector<JsonProcess>& jsonProcess)
119-{
120- const uint16_t tableProcessors = 10; // 最多有10个线程
121- Analysis::Utils::ThreadPool pool(tableProcessors);
122- pool.Start();
123- std::atomic<bool> retFlag(true);
124- std::vector<std::string> assemblerList = GetAssemblerList(jsonProcess);
125- for (const auto& name : assemblerList)
126- {
127- pool.AddTask(
128- [this, &name, &retFlag, &dataInventory]()
129- {
130- auto assembler = TimelineFactory::GetAssemblerByName(name);
131- if (assembler == nullptr)
132- {
133- ERROR("% is not defined", name);
134- retFlag = false;
135- return;
136- }
137- retFlag = assembler->Run(dataInventory, profPath_) && retFlag;
138- });
139- }
140- pool.WaitAllTasks();
141- pool.Stop();
142- if (!retFlag)
143- {
144- ERROR("The % for json assemble failed to be executed.", profPath_);
145- PRINT_ERROR(
146- "The % for json assemble failed to be executed. "
147- "Please check msprof_analysis_log in outputPath for more info.",
148- profPath_);
149- return false;
150- }
151- return true;
152-}
153- 
154void TimelineManager::WriteFile(const std::string& filePrefix, FileCategory category)80void TimelineManager::WriteFile(const std::string& filePrefix, FileCategory category)
155{81{
156 auto tempFile = filePrefix;82 auto tempFile = filePrefix;
@@ -160,18 +86,15 @@ void TimelineManager::WriteFile(const std::string& filePrefix, FileCategory cate
160 fileType_.emplace(category, filePath);86 fileType_.emplace(category, filePath);
161}87}
162 88 
163-bool TimelineManager::PreDumpJson(DataInventory& dataInventory)89+bool TimelineManager::PreDumpJson(const std::vector<JsonProcess>& jsonProcess, DataInventory& dataInventory)
164{90{
165- if (dataInventory.Size() <= MIN_NUM_FOR_IOC)
166- {
167- return false;
168- }
169 WriteFile(MSPROF_JSON_FILE, FileCategory::MSPROF);91 WriteFile(MSPROF_JSON_FILE, FileCategory::MSPROF);
170- if (dataInventory.GetPtr<std::vector<TrainTraceData>>())92+ if (std::find(jsonProcess.begin(), jsonProcess.end(), JsonProcess::STEP_TRACE) != jsonProcess.end())
171 {93 {
172 WriteFile(STEP_TRACE_FILE, FileCategory::STEP);94 WriteFile(STEP_TRACE_FILE, FileCategory::STEP);
173 }95 }
174- if (dataInventory.GetPtr<std::vector<MsprofTxHostData>>())96+ if (std::find(jsonProcess.begin(), jsonProcess.end(), JsonProcess::MSPROFTX) != jsonProcess.end() &&
97+ dataInventory.GetPtr<std::vector<MsprofTxHostData>>() != nullptr)
175 {98 {
176 WriteFile(MSPROF_TX_FILE, FileCategory::MSPROF_TX);99 WriteFile(MSPROF_TX_FILE, FileCategory::MSPROF_TX);
177 }100 }
@@ -184,44 +107,148 @@ void TimelineManager::PostDumpJson()
184 {107 {
185 // 此处需要覆盖文件末尾的",",实测必须使用in、out、ate三种模式打开文件,才可以实现覆盖写入108 // 此处需要覆盖文件末尾的",",实测必须使用in、out、ate三种模式打开文件,才可以实现覆盖写入
186 FileWriter writer(it.second, std::ios::in | std::ios::out | std::ios::ate);109 FileWriter writer(it.second, std::ios::in | std::ios::out | std::ios::ate);
187- writer.WriteTextBack(SUFFIX_CONTEXT, JSON_FILE_OFFSET);110+ if (File::Size(it.second) == PREFIX_CONTEXT.size())
111+ {
112+ writer.WriteText(SUFFIX_CONTEXT);
113+ }
114+ else
115+ {
116+ writer.WriteTextBack(SUFFIX_CONTEXT, JSON_FILE_OFFSET);
117+ }
188 }118 }
189}119}
190 120 
191-bool TimelineManager::Run(DataInventory& dataInventory, const std::vector<JsonProcess>& jsonProcess)
192-{
193- INFO("Start exporting timeline!");
194- PRINT_INFO("Start exporting the timeline!");
195- if (!PreDumpJson(dataInventory))
196- {
197- WARN("Can't Get data from dataInventory after data process");
198- PRINT_WARN("Can't export timeline, msprof_analysis_log in outputPath for more info");
199- return true;
200- }
201- bool runFlag = ProcessTimeLine(dataInventory, jsonProcess);
202- PostDumpJson();
203- if (!runFlag)
204- {
205- ERROR("The unified timeline process failed to be executed.");
206- PRINT_ERROR(
207- "The unified timeline process failed to be executed. "
208- "Please check msprof_analysis_log in outputPath for more info.");
209- return false;
210- }
211- PRINT_INFO("End exporting timeline output_file. The file is stored in the PROF file.");
212- return true;
213-}
214- 
215std::vector<std::string> TimelineManager::GetAssemblerList(const std::vector<JsonProcess>& jsonProcess)121std::vector<std::string> TimelineManager::GetAssemblerList(const std::vector<JsonProcess>& jsonProcess)
216{122{
217 std::vector<std::string> assemblerList;123 std::vector<std::string> assemblerList;
124+ std::set<std::string> assemblerSet;
218 for (const auto& jsonEnum : jsonProcess)125 for (const auto& jsonEnum : jsonProcess)
219 {126 {
220- assemblerList.push_back(JSON_TO_ASSEMBLER_TABLE.at(jsonEnum));127+ const auto& assemblerName = JSON_TO_ASSEMBLER_TABLE.at(jsonEnum);
128+ if (assemblerSet.insert(assemblerName).second)
129+ {
130+ assemblerList.push_back(assemblerName);
131+ }
221 }132 }
222 return assemblerList;133 return assemblerList;
223}134}
224 135 
225-const std::set<std::string>& TimelineManager::GetProcessList() { return TIMELINE_DATA_PROCESS_LIST; }136+bool TimelineManager::GetTopologyRoots(const std::vector<JsonProcess>& jsonProcesses, std::vector<TopoNodeId>& roots)
137+{
138+ const size_t rootsSize = roots.size();
139+ for (const auto& name : GetAssemblerList(jsonProcesses))
140+ {
141+ const TopoNodeId id{TopoNodeStage::TIMELINE_EXPORT, name};
142+ if (TopoNodeRegistry::Find(id) == nullptr)
143+ {
144+ ERROR("Timeline execution list node % has no static topology registration.", name);
145+ roots.resize(rootsSize);
146+ return false;
147+ }
148+ roots.push_back(id);
149+ }
150+ const TopoNodeId postDump{TopoNodeStage::FLOW_CONTROL, TIMELINE_POST_DUMP};
151+ if (TopoNodeRegistry::Find(postDump) == nullptr)
152+ {
153+ ERROR("Timeline post dump node has no static topology registration.");
154+ roots.resize(rootsSize);
155+ return false;
156+ }
157+ roots.push_back(postDump);
158+ return true;
159+}
160+ 
161+TopoNodeCreatorFactory TimelineManager::CreateTimelineAssembler(const std::string& name)
162+{
163+ return [name](const TopoBuildContext& context)
164+ {
165+ const std::string profPath = context.profPath;
166+ return [name, profPath]() -> std::unique_ptr<Infra::Process>
167+ {
168+ return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess(
169+ [name, profPath](DataInventory& dataInventory) -> bool
170+ {
171+ const auto assembler = TimelineFactory::GetAssemblerByName(name);
172+ if (assembler == nullptr)
173+ {
174+ ERROR("% is not defined", name);
175+ return false;
176+ }
177+ return assembler->Run(dataInventory, profPath);
178+ }));
179+ };
180+ };
181+}
182+ 
183+TopoNodeCreatorFactory TimelineManager::CreateTimelinePreDump()
184+{
185+ return [](const TopoBuildContext& context) -> Infra::ProcessCreator
186+ {
187+ const auto session = context.timelineSession;
188+ const std::vector<JsonProcess> processes = context.timelineProcesses;
189+ if (session == nullptr)
190+ {
191+ return Infra::ProcessCreator();
192+ }
193+ return [session, processes]() -> std::unique_ptr<Infra::Process>
194+ {
195+ return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess(
196+ [session, processes](DataInventory& dataInventory) -> bool
197+ {
198+ INFO("Start exporting timeline!");
199+ PRINT_INFO("Start exporting the timeline!");
200+ return session->PreDumpJson(processes, dataInventory);
201+ }));
202+ };
203+ };
204+}
205+ 
206+TopoNodeCreatorFactory TimelineManager::CreateTimelinePostDump()
207+{
208+ return [](const TopoBuildContext& context) -> Infra::ProcessCreator
209+ {
210+ const auto session = context.timelineSession;
211+ if (session == nullptr)
212+ {
213+ return Infra::ProcessCreator();
214+ }
215+ return [session]() -> std::unique_ptr<Infra::Process>
216+ {
217+ return std::unique_ptr<Infra::Process>(new (std::nothrow) TopoCallbackProcess(
218+ [session](DataInventory&) -> bool
219+ {
220+ session->PostDumpJson();
221+ PRINT_INFO("End exporting timeline output_file. The file is stored in the PROF file.");
222+ return true;
223+ }));
224+ };
225+ };
226+}
227+ 
228+std::vector<TopoNodeId> TimelineManager::ResolveSelectedTimelineNodes(const TopoBuildContext&,
229+ const std::vector<TopoNodeId>& roots)
230+{
231+ std::vector<TopoNodeId> dependencies;
232+ for (const auto& root : roots)
233+ {
234+ if (root.stage == TopoNodeStage::TIMELINE_EXPORT)
235+ {
236+ dependencies.push_back(root);
237+ }
238+ }
239+ return dependencies;
240+}
241+ 
242+std::vector<TopoNodeId> TimelineManager::ResolveTimelinePreDumpDependencies(const TopoBuildContext& context,
243+ const std::vector<TopoNodeId>&)
244+{
245+ std::vector<TopoNodeId> dependencies;
246+ if (std::find(context.timelineProcesses.begin(), context.timelineProcesses.end(), JsonProcess::MSPROFTX) !=
247+ context.timelineProcesses.end())
248+ {
249+ dependencies.push_back(TopoNodeId{TopoNodeStage::DATA_PROCESSING, PROCESSOR_NAME_MSTX});
250+ }
251+ return dependencies;
252+}
226} // namespace Application253} // namespace Application
227} // namespace Analysis254} // namespace Analysis
@@ -17,32 +17,47 @@
17#ifndef ANALYSIS_APPLICATION_TIMELINE_MANAGER_H17#ifndef ANALYSIS_APPLICATION_TIMELINE_MANAGER_H
18#define ANALYSIS_APPLICATION_TIMELINE_MANAGER_H18#define ANALYSIS_APPLICATION_TIMELINE_MANAGER_H
19 19 
20+#include <set>
20#include <string>21#include <string>
22+#include <unordered_map>
21#include <utility>23#include <utility>
24+#include <vector>
25+ 
26+#include "analysis/csrc/application/timeline/json_process_enum.h"
22#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h"27#include "analysis/csrc/infrastructure/data_inventory/include/data_inventory.h"
23#include "analysis/csrc/infrastructure/dump_tools/include/dump_tool.h"28#include "analysis/csrc/infrastructure/dump_tools/include/dump_tool.h"
24-#include "analysis/csrc/application/timeline/json_process_enum.h"29+#include "analysis/csrc/infrastructure/process/include/topo_graph.h"
25 30 
26-namespace Analysis {31+namespace Analysis
27-namespace Application {32+{
33+namespace Application
34+{
28using namespace Analysis::Infra;35using namespace Analysis::Infra;
29-class TimelineManager {36+class TimelineManager
30-public:37+{
38+ public:
31 explicit TimelineManager(const std::string &profPath, const std::string &outputPath)39 explicit TimelineManager(const std::string &profPath, const std::string &outputPath)
32 : profPath_(profPath), outputPath_(outputPath) {};40 : profPath_(profPath), outputPath_(outputPath) {};
33- bool Run(DataInventory &dataInventory, const std::vector<JsonProcess>& jsonProcess);41+ static bool GetTopologyRoots(const std::vector<JsonProcess> &jsonProcesses, std::vector<TopoNodeId> &roots);
34- const static std::set<std::string>& GetProcessList();42+ static TopoNodeCreatorFactory CreateTimelineAssembler(const std::string &name);
35-private:43+ static TopoNodeCreatorFactory CreateTimelinePreDump();
36- bool ProcessTimeLine(DataInventory &dataInventory, const std::vector<JsonProcess> &jsonEnum);44+ static TopoNodeCreatorFactory CreateTimelinePostDump();
37- bool PreDumpJson(DataInventory &dataInventory);45+ static std::vector<TopoNodeId> ResolveSelectedTimelineNodes(const TopoBuildContext &context,
46+ const std::vector<TopoNodeId> &roots);
47+ static std::vector<TopoNodeId> ResolveTimelinePreDumpDependencies(const TopoBuildContext &context,
48+ const std::vector<TopoNodeId> &roots);
49+ bool PreDumpJson(const std::vector<JsonProcess> &jsonProcess, DataInventory &dataInventory);
38 void PostDumpJson();50 void PostDumpJson();
51+ 
52+ private:
39 void WriteFile(const std::string &filePrefix, FileCategory category);53 void WriteFile(const std::string &filePrefix, FileCategory category);
40- std::vector<std::string> GetAssemblerList(const std::vector<JsonProcess>& jsonProcess);54+ static std::vector<std::string> GetAssemblerList(const std::vector<JsonProcess> &jsonProcess);
41-private:55+ 
56+ private:
42 std::string profPath_;57 std::string profPath_;
43 std::string outputPath_;58 std::string outputPath_;
44 std::unordered_map<FileCategory, std::string> fileType_;59 std::unordered_map<FileCategory, std::string> fileType_;
45};60};
46-}61+} // namespace Application
47-}62+} // namespace Analysis
48-#endif // ANALYSIS_APPLICATION_TIMELINE_MANAGER_H63+#endif // ANALYSIS_APPLICATION_TIMELINE_MANAGER_H
@@ -0,0 +1,183 @@
1+/* -------------------------------------------------------------------------
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This file is part of the MindStudio project.
4+ *
5+ * MindStudio is licensed under Mulan PSL v2.
6+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
7+ * You may obtain a copy of Mulan PSL v2 at:
8+ *
9+ * http://license.coscl.org.cn/MulanPSL2
10+ *
11+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14+ * See the Mulan PSL v2 for more details.
15+ * -------------------------------------------------------------------------*/
16+ 
17+#include <cstdint>
18+#include <string>
19+#include <typeinfo>
20+#include <unordered_map>
21+#include <vector>
22+ 
23+#include "analysis/csrc/application/database/db_constant.h"
24+#include "analysis/csrc/application/timeline/timeline_manager.h"
25+#include "analysis/csrc/domain/entities/json_trace/include/meta_data_event.h"
26+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/api_data.h"
27+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ascend_task_data.h"
28+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/block_detail_data.h"
29+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/ccu_mission_data.h"
30+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/communication_info_data.h"
31+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/dpu_data.h"
32+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/fusion_task_data.h"
33+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/kfc_turn_data.h"
34+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/memcpy_info_data.h"
35+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/msprof_tx_host_data.h"
36+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/step_trace_data.h"
37+#include "analysis/csrc/domain/entities/viewer_data/ai_task/include/task_info_data.h"
38+#include "analysis/csrc/domain/entities/viewer_data/system/include/acc_pmu_data.h"
39+#include "analysis/csrc/domain/entities/viewer_data/system/include/biu_perf_data.h"
40+#include "analysis/csrc/domain/entities/viewer_data/system/include/chip_trans_data.h"
41+#include "analysis/csrc/domain/entities/viewer_data/system/include/ddr_data.h"
42+#include "analysis/csrc/domain/entities/viewer_data/system/include/hbm_data.h"
43+#include "analysis/csrc/domain/entities/viewer_data/system/include/hccs_data.h"
44+#include "analysis/csrc/domain/entities/viewer_data/system/include/host_usage_data.h"
45+#include "analysis/csrc/domain/entities/viewer_data/system/include/llc_data.h"
46+#include "analysis/csrc/domain/entities/viewer_data/system/include/low_power_data.h"
47+#include "analysis/csrc/domain/entities/viewer_data/system/include/npu_mem_data.h"
48+#include "analysis/csrc/domain/entities/viewer_data/system/include/overlap_analysis_data.h"
49+#include "analysis/csrc/domain/entities/viewer_data/system/include/pcie_data.h"
50+#include "analysis/csrc/domain/entities/viewer_data/system/include/qos_data.h"
51+#include "analysis/csrc/domain/entities/viewer_data/system/include/sio_data.h"
52+#include "analysis/csrc/domain/entities/viewer_data/system/include/soc_bandwidth_data.h"
53+#include "analysis/csrc/domain/entities/viewer_data/system/include/sys_io_data.h"
54+#include "analysis/csrc/domain/entities/viewer_data/system/include/ub_data.h"
55+#include "analysis/csrc/infrastructure/process/include/topo_graph.h"
56+ 
57+namespace Analysis
58+{
59+namespace Application
60+{
61+using namespace Analysis::Domain;
62+ 
63+namespace
64+{
65+const std::string TIMELINE_PREFIX = "TIMELINE:";
66+const std::string TIMELINE_PRE_DUMP = TIMELINE_PREFIX + "PRE_DUMP";
67+const std::string TIMELINE_POST_DUMP = TIMELINE_PREFIX + "POST_DUMP";
68+} // namespace
69+ 
70+#define REGISTER_TIMELINE_NODE(Name, Dependencies) \
71+ REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(TIMELINE_EXPORT, Name), true, \
72+ TimelineManager::CreateTimelineAssembler(Name), Dependencies, nullptr)
73+ 
74+#define REGISTER_TIMELINE_NODE_WITH_DATA(Name, Dependencies, ...) \
75+ REGISTER_TIMELINE_NODE(Name, Dependencies); \
76+ REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(TIMELINE_EXPORT, Name), __VA_ARGS__)
77+ 
78+REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), true,
79+ TimelineManager::CreateTimelinePreDump(), TOPO_DEPS(),
80+ TimelineManager::ResolveTimelinePreDumpDependencies);
81+REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), std::vector<MsprofTxHostData>);
82+ 
83+REGISTER_TIMELINE_NODE_WITH_DATA(
84+ PROCESS_TASK,
85+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK),
86+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_KFC_TASK),
87+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO),
88+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_API), TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MEMCPY_INFO)),
89+ std::unordered_map<uint32_t, uint32_t>, std::vector<TaskInfoData>, std::vector<ApiData>,
90+ std::vector<MemcpyInfoData>, std::vector<AscendTaskData>, std::vector<KfcTurnData>);
91+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_ACC_PMU,
92+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
93+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_ACC_PMU)),
94+ std::vector<AccPmuData>);
95+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_API,
96+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
97+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_API),
98+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK)),
99+ std::vector<AscendTaskData>, std::vector<ApiData>);
100+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_DDR,
101+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
102+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DDR)),
103+ std::vector<DDRData>);
104+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_STARS_CHIP_TRANS,
105+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
106+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_CHIP_TRAINS),
107+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_PCIE)),
108+ std::vector<PaLinkInfoData>, std::vector<PcieInfoData>);
109+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_HBM,
110+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
111+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HBM)),
112+ std::vector<HbmData>);
113+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_HCCL,
114+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
115+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMMUNICATION),
116+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_KFC_TASK)),
117+ std::vector<CommunicationTaskData>, std::vector<CommunicationOpData>,
118+ std::vector<KfcTaskData>, std::vector<KfcOpData>);
119+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_CCU,
120+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
121+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_CCU_MISSION)),
122+ std::vector<CCUMissionTimelineData>);
123+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_HCCS,
124+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
125+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HCCS)),
126+ std::vector<HccsData>);
127+ 
128+#define REGISTER_SIMPLE_TIMELINE_NODE(Name, Processor, DataType) \
129+ REGISTER_TIMELINE_NODE_WITH_DATA( \
130+ Name, TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP), TOPO_NODE(DATA_PROCESSING, Processor)), DataType)
131+ 
132+REGISTER_SIMPLE_TIMELINE_NODE(PROCESSOR_NAME_OSRT_API, PROCESSOR_NAME_OSRT_API, std::vector<OSRuntimeApiData>);
133+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_NETWORK_USAGE, PROCESSOR_NAME_NETWORK_USAGE, std::vector<NetWorkUsageData>);
134+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_DISK_USAGE, PROCESSOR_NAME_DISK_USAGE, std::vector<DiskUsageData>);
135+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_MEMORY_USAGE, PROCESSOR_NAME_MEM_USAGE, std::vector<MemUsageData>);
136+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_CPU_USAGE, PROCESSOR_NAME_CPU_USAGE, std::vector<CpuUsageData>);
137+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_MSPROFTX, PROCESSOR_NAME_MSTX, std::vector<MsprofTxHostData>);
138+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_NPU_MEM, PROCESSOR_NAME_NPU_MEM, std::vector<NpuMemData>);
139+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_OVERLAP_ANALYSE, PROCESSOR_NAME_OVERLAP_ANALYSIS,
140+ std::vector<OverlapAnalysisData>);
141+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_PCIE, PROCESSOR_NAME_PCIE, std::vector<PCIeData>);
142+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_SIO, PROCESSOR_NAME_SIO, std::vector<SioData>);
143+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_STARS_SOC, PROCESSOR_NAME_SOC, std::vector<SocBandwidthData>);
144+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_LLC, PROCESSOR_NAME_LLC, std::vector<LLcData>);
145+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_NIC, PROCESSOR_NAME_NIC_TIMELINE, std::vector<NicReceiveSendData>);
146+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_ROCE, PROCESSOR_NAME_ROCE_TIMELINE, std::vector<RoceReceiveSendData>);
147+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_QOS, PROCESSOR_NAME_QOS, std::vector<QosData>);
148+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_BIU_PERF, PROCESSOR_NAME_BIU_PERF, std::vector<BiuPerfData>);
149+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_UB, PROCESSOR_NAME_UB, std::vector<UbData>);
150+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_DPU, PROCESSOR_NAME_DPU, std::vector<DPUData>);
151+REGISTER_SIMPLE_TIMELINE_NODE(PROCESS_FUSION_TASK, PROCESSOR_NAME_FUSION_TASK, std::vector<FusionTaskTimelineData>);
152+ 
153+#undef REGISTER_SIMPLE_TIMELINE_NODE
154+ 
155+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_STEP_TRACE,
156+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
157+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_STEP_TRACE)),
158+ std::vector<TrainTraceData>, std::vector<AllReduceData>, std::vector<GetNextData>);
159+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_LOW_POWER,
160+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
161+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_AICORE_FREQ),
162+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_LOW_POWER)),
163+ std::vector<LowPowerData>);
164+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_DEVICE_TX,
165+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
166+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_DEVICE_TX),
167+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_MSTX)),
168+ std::vector<MsprofTxDeviceData>, std::vector<MsprofTxHostData>);
169+REGISTER_TIMELINE_NODE_WITH_DATA(PROCESS_BLOCK_DETAIL,
170+ TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
171+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_BLOCK_DETAIL),
172+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO),
173+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK)),
174+ std::vector<BlockDetailData>, std::vector<TaskInfoData>, std::vector<AscendTaskData>);
175+ 
176+REGISTER_TOPO_NODE_SEQUENCE(typeid(void), TOPO_NODE(FLOW_CONTROL, TIMELINE_POST_DUMP), true,
177+ TimelineManager::CreateTimelinePostDump(), TOPO_DEPS(),
178+ TimelineManager::ResolveSelectedTimelineNodes);
179+ 
180+#undef REGISTER_TIMELINE_NODE_WITH_DATA
181+#undef REGISTER_TIMELINE_NODE
182+} // namespace Application
183+} // namespace Analysis
@@ -1,5 +1,5 @@
1/* -------------------------------------------------------------------------1/* -------------------------------------------------------------------------
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3 * This file is part of the MindStudio project.3 * This file is part of the MindStudio project.
4 *4 *
5 * MindStudio is licensed under Mulan PSL v2.5 * MindStudio is licensed under Mulan PSL v2.
@@ -16,167 +16,20 @@
16 16 
17#include "analysis/csrc/domain/data_process/include/data_processor_factory.h"17#include "analysis/csrc/domain/data_process/include/data_processor_factory.h"
18 18 
19-#include "analysis/csrc/application/database/db_constant.h"19+#include "analysis/csrc/infrastructure/dfx/error_code.h"
20-#include "analysis/csrc/domain/data_process/ai_task/api_processor.h"
21-#include "analysis/csrc/domain/data_process/ai_task/ccu_mission_processor.h"
22-#include "analysis/csrc/domain/data_process/ai_task/communication_info_processor.h"
23-#include "analysis/csrc/domain/data_process/ai_task/compute_task_info_processor.h"
24-#include "analysis/csrc/domain/data_process/ai_task/dpu_processor.h"
25-#include "analysis/csrc/domain/data_process/ai_task/fusion_op_processor.h"
26-#include "analysis/csrc/domain/data_process/ai_task/fusion_task_processor.h"
27-#include "analysis/csrc/domain/data_process/ai_task/hccl_statistic_processor.h"
28-#include "analysis/csrc/domain/data_process/ai_task/host_task_processor.h"
29-#include "analysis/csrc/domain/data_process/ai_task/kfc_task_processor.h"
30-#include "analysis/csrc/domain/data_process/ai_task/mc2_comm_info_processor.h"
31-#include "analysis/csrc/domain/data_process/ai_task/memcpy_info_processor.h"
32-#include "analysis/csrc/domain/data_process/ai_task/metric_processor.h"
33-#include "analysis/csrc/domain/data_process/ai_task/model_name_processor.h"
34-#include "analysis/csrc/domain/data_process/ai_task/msproftx_device_processor.h"
35-#include "analysis/csrc/domain/data_process/ai_task/msproftx_host_processor.h"
36-#include "analysis/csrc/domain/data_process/ai_task/op_statistic_processor.h"
37-#include "analysis/csrc/domain/data_process/ai_task/overlap_analysis_processor.h"
38-#include "analysis/csrc/domain/data_process/ai_task/step_trace_processor.h"
39-#include "analysis/csrc/domain/data_process/ai_task/task_processor.h"
40-#include "analysis/csrc/domain/data_process/ai_task/unified_pmu_processor.h"
41-#include "analysis/csrc/domain/data_process/system/acc_pmu_processor.h"
42-#include "analysis/csrc/domain/data_process/system/aicore_freq_processor.h"
43-#include "analysis/csrc/domain/data_process/system/biu_perf_processor.h"
44-#include "analysis/csrc/domain/data_process/system/block_detail_processor.h"
45-#include "analysis/csrc/domain/data_process/system/chip_trans_processor.h"
46-#include "analysis/csrc/domain/data_process/system/ddr_processor.h"
47-#include "analysis/csrc/domain/data_process/system/hbm_processor.h"
48-#include "analysis/csrc/domain/data_process/system/hccs_processor.h"
49-#include "analysis/csrc/domain/data_process/system/host_usage_processor.h"
50-#include "analysis/csrc/domain/data_process/system/llc_processor.h"
51-#include "analysis/csrc/domain/data_process/system/low_power_processor.h"
52-#include "analysis/csrc/domain/data_process/system/netdev_stats_processor.h"
53-#include "analysis/csrc/domain/data_process/system/npu_mem_processor.h"
54-#include "analysis/csrc/domain/data_process/system/npu_module_mem_processor.h"
55-#include "analysis/csrc/domain/data_process/system/npu_op_mem_processor.h"
56-#include "analysis/csrc/domain/data_process/system/page_fault_processor.h"
57-#include "analysis/csrc/domain/data_process/system/pcie_processor.h"
58-#include "analysis/csrc/domain/data_process/system/qos_processor.h"
59-#include "analysis/csrc/domain/data_process/system/sio_processor.h"
60-#include "analysis/csrc/domain/data_process/system/soc_bandwidth_processor.h"
61-#include "analysis/csrc/domain/data_process/system/sys_io_processor.h"
62-#include "analysis/csrc/domain/data_process/system/ub_processor.h"
63 20 
64namespace Analysis21namespace Analysis
65{22{
66namespace Domain23namespace Domain
67{24{
68-std::unordered_map<std::string, ProcessorCreator> DataProcessorFactory::processorTable_{25+uint32_t DataProcessorProcess::ProcessEntry(Infra::DataInventory& inventory, const Infra::Context&)
69- {PROCESSOR_NAME_API, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
70- { MAKE_SHARED_RETURN_VOID(processor, ApiProcessor, profPath); }},
71- {PROCESSOR_NAME_DPU, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
72- { MAKE_SHARED_RETURN_VOID(processor, DPUProcessor, profPath); }},
73- {PROCESSOR_NAME_COMMUNICATION, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
74- { MAKE_SHARED_RETURN_VOID(processor, CommunicationInfoProcessor, profPath); }},
75- {PROCESSOR_NAME_CCU_MISSION, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
76- { MAKE_SHARED_RETURN_VOID(processor, CCUMissionProcessor, profPath); }},
77- {PROCESSOR_NAME_COMPUTE_TASK_INFO, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
78- { MAKE_SHARED_RETURN_VOID(processor, ComputeTaskInfoProcessor, profPath); }},
79- {PROCESSOR_NAME_KFC_TASK, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
80- { MAKE_SHARED_RETURN_VOID(processor, KfcTaskProcessor, profPath); }},
81- {PROCESSOR_NAME_DEVICE_TX, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
82- { MAKE_SHARED_RETURN_VOID(processor, MsprofTxDeviceProcessor, profPath); }},
83- {PROCESSOR_NAME_MSTX, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
84- { MAKE_SHARED_RETURN_VOID(processor, MsprofTxHostProcessor, profPath); }},
85- {PROCESSOR_NAME_STEP_TRACE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
86- { MAKE_SHARED_RETURN_VOID(processor, StepTraceProcessor, profPath); }},
87- {PROCESSOR_NAME_TASK, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
88- { MAKE_SHARED_RETURN_VOID(processor, TaskProcessor, profPath); }},
89- {PROCESSOR_NAME_ACC_PMU, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
90- { MAKE_SHARED_RETURN_VOID(processor, AccPmuProcessor, profPath); }},
91- {PROCESSOR_NAME_AICORE_FREQ, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
92- { MAKE_SHARED_RETURN_VOID(processor, AicoreFreqProcessor, profPath); }},
93- {PROCESSOR_NAME_CHIP_TRAINS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
94- { MAKE_SHARED_RETURN_VOID(processor, ChipTransProcessor, profPath); }},
95- {PROCESSOR_NAME_DDR, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
96- { MAKE_SHARED_RETURN_VOID(processor, DDRProcessor, profPath); }},
97- {PROCESSOR_NAME_HBM, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
98- { MAKE_SHARED_RETURN_VOID(processor, HBMProcessor, profPath); }},
99- {PROCESSOR_NAME_HCCS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
100- { MAKE_SHARED_RETURN_VOID(processor, HCCSProcessor, profPath); }},
101- {PROCESSOR_NAME_NETDEV_STATS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
102- { MAKE_SHARED_RETURN_VOID(processor, NetDevStatsProcessor, profPath); }},
103- {PROCESSOR_NAME_CPU_USAGE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
104- { MAKE_SHARED_RETURN_VOID(processor, HostCpuUsageProcessor, profPath); }},
105- {PROCESSOR_NAME_MEM_USAGE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
106- { MAKE_SHARED_RETURN_VOID(processor, HostMemUsageProcessor, profPath); }},
107- {PROCESSOR_NAME_DISK_USAGE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
108- { MAKE_SHARED_RETURN_VOID(processor, HostDiskUsageProcessor, profPath); }},
109- {PROCESSOR_NAME_NETWORK_USAGE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
110- { MAKE_SHARED_RETURN_VOID(processor, HostNetworkUsageProcessor, profPath); }},
111- {PROCESSOR_NAME_OSRT_API, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
112- { MAKE_SHARED_RETURN_VOID(processor, OSRuntimeApiProcessor, profPath); }},
113- {PROCESSOR_NAME_LLC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
114- { MAKE_SHARED_RETURN_VOID(processor, LLcProcessor, profPath); }},
115- {PROCESSOR_NAME_NPU_MEM, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
116- { MAKE_SHARED_RETURN_VOID(processor, NpuMemProcessor, profPath); }},
117- {PROCESSOR_NAME_PCIE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
118- { MAKE_SHARED_RETURN_VOID(processor, PCIeProcessor, profPath); }},
119- {PROCESSOR_NAME_SIO, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
120- { MAKE_SHARED_RETURN_VOID(processor, SioProcessor, profPath); }},
121- {PROCESSOR_NAME_SOC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
122- { MAKE_SHARED_RETURN_VOID(processor, SocBandwidthProcessor, profPath); }},
123- {PROCESSOR_NAME_PAGE_FAULT, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
124- { MAKE_SHARED_RETURN_VOID(processor, PageFaultProcessor, profPath); }},
125- {PROCESSOR_NAME_NIC_TIMELINE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
126- { MAKE_SHARED_RETURN_VOID(processor, NicTimelineProcessor, profPath); }},
127- {PROCESSOR_NAME_ROCE_TIMELINE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
128- { MAKE_SHARED_RETURN_VOID(processor, RoCETimelineProcessor, profPath); }},
129- {PROCESSOR_NAME_NIC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
130- { MAKE_SHARED_RETURN_VOID(processor, NicProcessor, profPath); }},
131- {PROCESSOR_NAME_ROCE, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
132- { MAKE_SHARED_RETURN_VOID(processor, RoCEProcessor, profPath); }},
133- {PROCESSOR_NAME_QOS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
134- { MAKE_SHARED_RETURN_VOID(processor, QosProcessor, profPath); }},
135- {PROCESSOR_MC2_COMM_INFO, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
136- { MAKE_SHARED_RETURN_VOID(processor, Mc2CommInfoProcessor, profPath); }},
137- {PROCESSOR_PMU, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
138- { MAKE_SHARED_RETURN_VOID(processor, MetricProcessor, profPath); }},
139- {PROCESSOR_NAME_MEMCPY_INFO, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
140- { MAKE_SHARED_RETURN_VOID(processor, MemcpyInfoProcessor, profPath); }},
141- {PROCESSOR_NAME_NPU_OP_MEM, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
142- { MAKE_SHARED_RETURN_VOID(processor, NpuOpMemProcessor, profPath); }},
143- {PROCESSOR_NAME_NPU_MODULE_MEM, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
144- { MAKE_SHARED_RETURN_VOID(processor, NpuModuleMemProcessor, profPath); }},
145- {PROCESSOR_NAME_UNIFIED_PMU, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
146- { MAKE_SHARED_RETURN_VOID(processor, UnifiedPmuProcessor, profPath); }},
147- {PROCESSOR_NAME_FUSION_OP, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
148- { MAKE_SHARED_RETURN_VOID(processor, FusionOpProcessor, profPath); }},
149- {PROCESSOR_NAME_FUSION_TASK, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
150- { MAKE_SHARED_RETURN_VOID(processor, FusionTaskProcessor, profPath); }},
151- {PROCESSOR_NAME_MODEL_NAME, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
152- { MAKE_SHARED_RETURN_VOID(processor, ModelNameProcessor, profPath); }},
153- {PROCESSOR_NAME_COMM_STATISTIC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
154- { MAKE_SHARED_RETURN_VOID(processor, HcclStatisticProcessor, profPath); }},
155- {PROCESSOR_NAME_OP_STATISTIC, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
156- { MAKE_SHARED_RETURN_VOID(processor, OpStatisticProcessor, profPath); }},
157- {PROCESSOR_HOST_TASK, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
158- { MAKE_SHARED_RETURN_VOID(processor, HostTaskProcessor, profPath); }},
159- {PROCESSOR_NAME_OVERLAP_ANALYSIS, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
160- { MAKE_SHARED_RETURN_VOID(processor, OverlapAnalysisProcessor, profPath); }},
161- {PROCESSOR_NAME_LOW_POWER, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
162- { MAKE_SHARED_RETURN_VOID(processor, LowPowerProcessor, profPath); }},
163- {PROCESSOR_NAME_BIU_PERF, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
164- { MAKE_SHARED_RETURN_VOID(processor, BiuPerfProcessor, profPath); }},
165- {PROCESSOR_NAME_UB, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
166- { MAKE_SHARED_RETURN_VOID(processor, UbProcessor, profPath); }},
167- {PROCESSOR_NAME_BLOCK_DETAIL, [](const std::string &profPath, std::shared_ptr<DataProcessor> &processor)
168- { MAKE_SHARED_RETURN_VOID(processor, BlockDetailProcessor, profPath); }}};
169- 
170-std::shared_ptr<DataProcessor> DataProcessorFactory::GetDataProcessByName(const std::string &profPath,
171- const std::string &processName)
172{26{
173- std::shared_ptr<DataProcessor> processor = nullptr;27+ if (processor_ == nullptr)
174- auto it = processorTable_.find(processName);
175- if (it != processorTable_.end())
176 {28 {
177- it->second(profPath, processor);29+ ERROR("Create processor % failed.", name_);
30+ return ANALYSIS_ERROR;
178 }31 }
179- return processor;32+ return processor_->Run(inventory, name_) ? ANALYSIS_OK : ANALYSIS_ERROR;
180}33}
181 34 
182} // namespace Domain35} // namespace Domain
@@ -0,0 +1,147 @@
1+/* -------------------------------------------------------------------------
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This file is part of the MindStudio project.
4+ *
5+ * MindStudio is licensed under Mulan PSL v2.
6+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
7+ * You may obtain a copy of Mulan PSL v2 at:
8+ *
9+ * http://license.coscl.org.cn/MulanPSL2
10+ *
11+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12+ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13+ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14+ * See the Mulan PSL v2 for more details.
15+ * -------------------------------------------------------------------------*/
16+ 
17+#include "analysis/csrc/application/database/db_constant.h"
18+#include "analysis/csrc/domain/data_process/ai_task/api_processor.h"
19+#include "analysis/csrc/domain/data_process/ai_task/ccu_mission_processor.h"
20+#include "analysis/csrc/domain/data_process/ai_task/communication_info_processor.h"
21+#include "analysis/csrc/domain/data_process/ai_task/compute_task_info_processor.h"
22+#include "analysis/csrc/domain/data_process/ai_task/dpu_processor.h"
23+#include "analysis/csrc/domain/data_process/ai_task/fusion_op_processor.h"
24+#include "analysis/csrc/domain/data_process/ai_task/fusion_task_processor.h"
25+#include "analysis/csrc/domain/data_process/ai_task/hash_init_processor.h"
26+#include "analysis/csrc/domain/data_process/ai_task/hccl_statistic_processor.h"
27+#include "analysis/csrc/domain/data_process/ai_task/host_task_processor.h"
28+#include "analysis/csrc/domain/data_process/ai_task/kfc_task_processor.h"
29+#include "analysis/csrc/domain/data_process/ai_task/mc2_comm_info_processor.h"
30+#include "analysis/csrc/domain/data_process/ai_task/memcpy_info_processor.h"
31+#include "analysis/csrc/domain/data_process/ai_task/metric_processor.h"
32+#include "analysis/csrc/domain/data_process/ai_task/model_name_processor.h"
33+#include "analysis/csrc/domain/data_process/ai_task/msproftx_device_processor.h"
34+#include "analysis/csrc/domain/data_process/ai_task/msproftx_host_processor.h"
35+#include "analysis/csrc/domain/data_process/ai_task/op_statistic_processor.h"
36+#include "analysis/csrc/domain/data_process/ai_task/overlap_analysis_processor.h"
37+#include "analysis/csrc/domain/data_process/ai_task/step_trace_processor.h"
38+#include "analysis/csrc/domain/data_process/ai_task/task_processor.h"
39+#include "analysis/csrc/domain/data_process/ai_task/unified_pmu_processor.h"
40+#include "analysis/csrc/domain/data_process/include/data_processor_factory.h"
41+#include "analysis/csrc/domain/data_process/system/acc_pmu_processor.h"
42+#include "analysis/csrc/domain/data_process/system/aicore_freq_processor.h"
43+#include "analysis/csrc/domain/data_process/system/biu_perf_processor.h"
44+#include "analysis/csrc/domain/data_process/system/block_detail_processor.h"
45+#include "analysis/csrc/domain/data_process/system/chip_trans_processor.h"
46+#include "analysis/csrc/domain/data_process/system/ddr_processor.h"
47+#include "analysis/csrc/domain/data_process/system/hbm_processor.h"
48+#include "analysis/csrc/domain/data_process/system/hccs_processor.h"
49+#include "analysis/csrc/domain/data_process/system/host_usage_processor.h"
50+#include "analysis/csrc/domain/data_process/system/llc_processor.h"
51+#include "analysis/csrc/domain/data_process/system/low_power_processor.h"
52+#include "analysis/csrc/domain/data_process/system/netdev_stats_processor.h"
53+#include "analysis/csrc/domain/data_process/system/npu_mem_processor.h"
54+#include "analysis/csrc/domain/data_process/system/npu_module_mem_processor.h"
55+#include "analysis/csrc/domain/data_process/system/npu_op_mem_processor.h"
56+#include "analysis/csrc/domain/data_process/system/page_fault_processor.h"
57+#include "analysis/csrc/domain/data_process/system/pcie_processor.h"
58+#include "analysis/csrc/domain/data_process/system/qos_processor.h"
59+#include "analysis/csrc/domain/data_process/system/sio_processor.h"
60+#include "analysis/csrc/domain/data_process/system/soc_bandwidth_processor.h"
61+#include "analysis/csrc/domain/data_process/system/sys_io_processor.h"
62+#include "analysis/csrc/domain/data_process/system/ub_processor.h"
63+ 
64+namespace Analysis
65+{
66+namespace Domain
67+{
68+#define REGISTER_PROCESSOR(Processor, Name, Dependencies) \
69+ REGISTER_TOPO_NODE_SEQUENCE(typeid(Processor), TOPO_NODE(DATA_PROCESSING, Name), true, \
70+ CreateDataProcessorFactory<Processor>(Name), Dependencies, nullptr)
71+ 
72+#define REGISTER_PROCESSOR_WITH_DATA(Processor, Name, Dependencies, ...) \
73+ REGISTER_PROCESSOR(Processor, Name, Dependencies); \
74+ REGISTER_TOPO_NODE_DEPENDENT_DATA(TOPO_NODE(DATA_PROCESSING, Name), __VA_ARGS__)
75+ 
76+#define REGISTER_OPTIONAL_PROCESSOR(Processor, Name, Dependencies) \
77+ REGISTER_TOPO_NODE_SEQUENCE(typeid(Processor), TOPO_NODE(DATA_PROCESSING, Name), false, \
78+ CreateDataProcessorFactory<Processor>(Name), Dependencies, nullptr)
79+ 
80+REGISTER_PROCESSOR(HashInitProcessor, PROCESSOR_NAME_HASH, TOPO_DEPS());
81+REGISTER_PROCESSOR(ApiProcessor, PROCESSOR_NAME_API, TOPO_DEPS());
82+REGISTER_PROCESSOR(DPUProcessor, PROCESSOR_NAME_DPU, TOPO_DEPS());
83+REGISTER_PROCESSOR_WITH_DATA(CommunicationInfoProcessor, PROCESSOR_NAME_COMMUNICATION,
84+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HASH)), GeHashMap);
85+REGISTER_PROCESSOR(CCUMissionProcessor, PROCESSOR_NAME_CCU_MISSION, TOPO_DEPS());
86+REGISTER_PROCESSOR_WITH_DATA(ComputeTaskInfoProcessor, PROCESSOR_NAME_COMPUTE_TASK_INFO,
87+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HASH)), GeHashMap);
88+REGISTER_PROCESSOR(KfcTaskProcessor, PROCESSOR_NAME_KFC_TASK, TOPO_DEPS());
89+ 
90+REGISTER_PROCESSOR(MsprofTxDeviceProcessor, PROCESSOR_NAME_DEVICE_TX, TOPO_DEPS());
91+REGISTER_PROCESSOR(MsprofTxHostProcessor, PROCESSOR_NAME_MSTX, TOPO_DEPS());
92+REGISTER_PROCESSOR(StepTraceProcessor, PROCESSOR_NAME_STEP_TRACE, TOPO_DEPS());
93+REGISTER_PROCESSOR(TaskProcessor, PROCESSOR_NAME_TASK, TOPO_DEPS());
94+REGISTER_PROCESSOR(AccPmuProcessor, PROCESSOR_NAME_ACC_PMU, TOPO_DEPS());
95+REGISTER_PROCESSOR(AicoreFreqProcessor, PROCESSOR_NAME_AICORE_FREQ, TOPO_DEPS());
96+REGISTER_PROCESSOR(ChipTransProcessor, PROCESSOR_NAME_CHIP_TRAINS, TOPO_DEPS());
97+REGISTER_PROCESSOR(DDRProcessor, PROCESSOR_NAME_DDR, TOPO_DEPS());
98+REGISTER_PROCESSOR(HBMProcessor, PROCESSOR_NAME_HBM, TOPO_DEPS());
99+REGISTER_PROCESSOR(HCCSProcessor, PROCESSOR_NAME_HCCS, TOPO_DEPS());
100+REGISTER_OPTIONAL_PROCESSOR(NetDevStatsProcessor, PROCESSOR_NAME_NETDEV_STATS, TOPO_DEPS());
101+REGISTER_PROCESSOR(HostCpuUsageProcessor, PROCESSOR_NAME_CPU_USAGE, TOPO_DEPS());
102+REGISTER_PROCESSOR(HostMemUsageProcessor, PROCESSOR_NAME_MEM_USAGE, TOPO_DEPS());
103+REGISTER_PROCESSOR(HostDiskUsageProcessor, PROCESSOR_NAME_DISK_USAGE, TOPO_DEPS());
104+REGISTER_PROCESSOR(HostNetworkUsageProcessor, PROCESSOR_NAME_NETWORK_USAGE, TOPO_DEPS());
105+REGISTER_PROCESSOR(OSRuntimeApiProcessor, PROCESSOR_NAME_OSRT_API, TOPO_DEPS());
106+REGISTER_PROCESSOR(LLcProcessor, PROCESSOR_NAME_LLC, TOPO_DEPS());
107+REGISTER_PROCESSOR(NpuMemProcessor, PROCESSOR_NAME_NPU_MEM, TOPO_DEPS());
108+REGISTER_PROCESSOR(PCIeProcessor, PROCESSOR_NAME_PCIE, TOPO_DEPS());
109+REGISTER_PROCESSOR(SioProcessor, PROCESSOR_NAME_SIO, TOPO_DEPS());
110+REGISTER_PROCESSOR(SocBandwidthProcessor, PROCESSOR_NAME_SOC, TOPO_DEPS());
111+REGISTER_PROCESSOR(PageFaultProcessor, PROCESSOR_NAME_PAGE_FAULT, TOPO_DEPS());
112+REGISTER_PROCESSOR(NicTimelineProcessor, PROCESSOR_NAME_NIC_TIMELINE, TOPO_DEPS());
113+REGISTER_PROCESSOR(RoCETimelineProcessor, PROCESSOR_NAME_ROCE_TIMELINE, TOPO_DEPS());
114+REGISTER_PROCESSOR(NicProcessor, PROCESSOR_NAME_NIC, TOPO_DEPS());
115+REGISTER_PROCESSOR(RoCEProcessor, PROCESSOR_NAME_ROCE, TOPO_DEPS());
116+REGISTER_PROCESSOR(QosProcessor, PROCESSOR_NAME_QOS, TOPO_DEPS());
117+REGISTER_PROCESSOR(Mc2CommInfoProcessor, PROCESSOR_MC2_COMM_INFO, TOPO_DEPS());
118+REGISTER_PROCESSOR(MetricProcessor, PROCESSOR_PMU, TOPO_DEPS());
119+REGISTER_PROCESSOR(MemcpyInfoProcessor, PROCESSOR_NAME_MEMCPY_INFO, TOPO_DEPS());
120+REGISTER_PROCESSOR_WITH_DATA(NpuOpMemProcessor, PROCESSOR_NAME_NPU_OP_MEM,
121+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_HASH)), GeHashMap);
122+REGISTER_PROCESSOR(NpuModuleMemProcessor, PROCESSOR_NAME_NPU_MODULE_MEM, TOPO_DEPS());
123+REGISTER_PROCESSOR(UnifiedPmuProcessor, PROCESSOR_NAME_UNIFIED_PMU, TOPO_DEPS());
124+REGISTER_PROCESSOR(FusionOpProcessor, PROCESSOR_NAME_FUSION_OP, TOPO_DEPS());
125+REGISTER_PROCESSOR(FusionTaskProcessor, PROCESSOR_NAME_FUSION_TASK, TOPO_DEPS());
126+REGISTER_PROCESSOR(ModelNameProcessor, PROCESSOR_NAME_MODEL_NAME, TOPO_DEPS());
127+REGISTER_PROCESSOR(HcclStatisticProcessor, PROCESSOR_NAME_COMM_STATISTIC, TOPO_DEPS());
128+REGISTER_PROCESSOR(OpStatisticProcessor, PROCESSOR_NAME_OP_STATISTIC, TOPO_DEPS());
129+REGISTER_PROCESSOR(HostTaskProcessor, PROCESSOR_HOST_TASK, TOPO_DEPS());
130+REGISTER_PROCESSOR_WITH_DATA(OverlapAnalysisProcessor, PROCESSOR_NAME_OVERLAP_ANALYSIS,
131+ TOPO_DEPS(TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK),
132+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMPUTE_TASK_INFO),
133+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_COMMUNICATION),
134+ TOPO_NODE(DATA_PROCESSING, PROCESSOR_MC2_COMM_INFO)),
135+ std::vector<AscendTaskData>, std::vector<TaskInfoData>, std::vector<CommunicationOpData>,
136+ std::vector<MC2CommInfoData>);
137+REGISTER_PROCESSOR(LowPowerProcessor, PROCESSOR_NAME_LOW_POWER, TOPO_DEPS());
138+REGISTER_PROCESSOR(BiuPerfProcessor, PROCESSOR_NAME_BIU_PERF, TOPO_DEPS());
139+REGISTER_PROCESSOR(UbProcessor, PROCESSOR_NAME_UB, TOPO_DEPS());
140+REGISTER_PROCESSOR(BlockDetailProcessor, PROCESSOR_NAME_BLOCK_DETAIL, TOPO_DEPS());
141+ 
142+#undef REGISTER_PROCESSOR_WITH_DATA
143+#undef REGISTER_OPTIONAL_PROCESSOR
144+#undef REGISTER_PROCESSOR
145+ 
146+} // namespace Domain
147+} // namespace Analysis
@@ -17,19 +17,55 @@
17#ifndef ANALYSIS_DOMAIN_DATA_PROCESSOR_FACTORY_H17#ifndef ANALYSIS_DOMAIN_DATA_PROCESSOR_FACTORY_H
18#define ANALYSIS_DOMAIN_DATA_PROCESSOR_FACTORY_H18#define ANALYSIS_DOMAIN_DATA_PROCESSOR_FACTORY_H
19 19 
20-#include <functional>20+#include <memory>
21-#include "analysis/csrc/domain/data_process/data_processor.h"21+#include <new>
22+#include <string>
23+#include <typeindex>
22 24 
23-namespace Analysis {25+#include "analysis/csrc/domain/data_process/data_processor.h"
24-namespace Domain {26+#include "analysis/csrc/infrastructure/process/include/process.h"
25-using ProcessorCreator = std::function<void(const std::string&, std::shared_ptr<DataProcessor>&)>;27+#include "analysis/csrc/infrastructure/process/include/process_struct.h"
26-class DataProcessorFactory {28+#include "analysis/csrc/infrastructure/process/include/topo_graph.h"
27-public:29+ 
28- static std::shared_ptr<DataProcessor> GetDataProcessByName(const std::string &profPath,30+namespace Analysis
29- const std::string &processName);31+{
30-private:32+namespace Domain
31- static std::unordered_map<std::string, ProcessorCreator> processorTable_;33+{
34+class DataProcessorProcess final : public Infra::Process
35+{
36+ public:
37+ DataProcessorProcess(std::shared_ptr<DataProcessor> processor, std::string name)
38+ : processor_(std::move(processor)), name_(std::move(name))
39+ {
40+ }
41+ 
42+ const std::shared_ptr<DataProcessor>& GetProcessor() const { return processor_; }
43+ 
44+ private:
45+ uint32_t ProcessEntry(Infra::DataInventory& inventory, const Infra::Context&) override;
46+ 
47+ std::shared_ptr<DataProcessor> processor_;
48+ std::string name_;
32};49};
50+ 
51+template <typename Processor>
52+Application::TopoNodeCreatorFactory CreateDataProcessorFactory(const std::string& processName)
53+{
54+ return [processName](const Application::TopoBuildContext& context)
55+ {
56+ const std::string profPath = context.profPath;
57+ return [processName, profPath]() -> std::unique_ptr<Infra::Process>
58+ {
59+ std::shared_ptr<DataProcessor> processor(new (std::nothrow) Processor(profPath));
60+ if (processor == nullptr)
61+ {
62+ return nullptr;
63+ }
64+ return std::unique_ptr<Infra::Process>(new (std::nothrow) DataProcessorProcess(processor, processName));
65+ };
66+ };
33}67}
34-}68+ 
35-#endif // ANALYSIS_DOMAIN_DATA_PROCESSOR_FACTORY_H69+} // namespace Domain
70+} // namespace Analysis
71+#endif // ANALYSIS_DOMAIN_DATA_PROCESSOR_FACTORY_H
@@ -17,17 +17,20 @@
17 17 
18using namespace Analysis;18using namespace Analysis;
19 19 
20-namespace Analysis {20+namespace Analysis
21+{
21 22 
22-namespace Infra {23+namespace Infra
24+{
23 25 
24bool DataInventory::InputToData(std::type_index idx, BaseTypePtr ptr)26bool DataInventory::InputToData(std::type_index idx, BaseTypePtr ptr)
25{27{
26- if (ptr == nullptr) {28+ if (ptr == nullptr)
29+ {
27 ERROR("invalid ptr, type name: %", idx.name());30 ERROR("invalid ptr, type name: %", idx.name());
28 return false;31 return false;
29 }32 }
30- 33+ 
31 std::lock_guard<std::mutex> lg(mutex_);34 std::lock_guard<std::mutex> lg(mutex_);
32 auto ret = data_.emplace(idx, ptr);35 auto ret = data_.emplace(idx, ptr);
33 return ret.second;36 return ret.second;
@@ -37,9 +40,10 @@ std::set<std::type_index> DataInventory::RemoveRestData(const std::set<std::type
37{40{
38 std::set<std::type_index> removedTypes;41 std::set<std::type_index> removedTypes;
39 std::lock_guard<std::mutex> lg(mutex_);42 std::lock_guard<std::mutex> lg(mutex_);
40- for (auto it = data_.begin(); it != data_.end();) {43+ for (auto it = data_.begin(); it != data_.end();)
41- if (std::find(keepingDataType.begin(), keepingDataType.end(), it->first) ==44+ {
42- std::end(keepingDataType)) {45+ if (std::find(keepingDataType.begin(), keepingDataType.end(), it->first) == std::end(keepingDataType))
46+ {
43 removedTypes.insert(it->first);47 removedTypes.insert(it->first);
44 it = data_.erase(it);48 it = data_.erase(it);
45 continue;49 continue;
@@ -53,13 +57,14 @@ BaseTypePtr DataInventory::GetPtr(std::type_index idx) const
53{57{
54 std::lock_guard<std::mutex> lg(mutex_);58 std::lock_guard<std::mutex> lg(mutex_);
55 auto it = data_.find(idx);59 auto it = data_.find(idx);
56- if (it == data_.end()) {60+ if (it == data_.end())
61+ {
57 return {};62 return {};
58 }63 }
59 64 
60 return it->second;65 return it->second;
61}66}
62 67 
63-}68+} // namespace Infra
64 69 
65-}70+} // namespace Analysis
@@ -20,35 +20,42 @@
20#define ANALYSIS_DEVICE_TASK_DATAINVENTORY_DATA_INVENTORY_H20#define ANALYSIS_DEVICE_TASK_DATAINVENTORY_DATA_INVENTORY_H
21 21 
22#include <memory>22#include <memory>
23-#include <set>
24-#include <unordered_map>
25-#include <typeindex>
26#include <mutex>23#include <mutex>
24+#include <set>
25+#include <typeindex>
26+#include <unordered_map>
27+ 
27#include "analysis/csrc/infrastructure/utils/utils.h"28#include "analysis/csrc/infrastructure/utils/utils.h"
28 29 
29-using Analysis::Log;
30using Analysis::Format;30using Analysis::Format;
31+using Analysis::Log;
31 32 
32-namespace Analysis {33+namespace Analysis
33-namespace Infra {34+{
35+namespace Infra
36+{
34 37 
35-struct BaseType {38+struct BaseType
39+{
36 virtual ~BaseType() = default;40 virtual ~BaseType() = default;
37};41};
38using BaseTypePtr = std::shared_ptr<BaseType>;42using BaseTypePtr = std::shared_ptr<BaseType>;
39 43 
40template <typename T>44template <typename T>
41-struct CustomType : public BaseType {45+struct CustomType : public BaseType
46+{
42 std::shared_ptr<T> data;47 std::shared_ptr<T> data;
43};48};
44 49 
45-template<typename T>50+template <typename T>
46-struct SharedPtrType {51+struct SharedPtrType
52+{
47 using Type = std::shared_ptr<T>;53 using Type = std::shared_ptr<T>;
48};54};
49 55 
50-class DataInventory {56+class DataInventory
51-public:57+{
58+ public:
52 /**59 /**
53 * @brief 将数据存放入DataInventory60 * @brief 将数据存放入DataInventory
54 *61 *
@@ -57,14 +64,16 @@ public:
57 * @return 成功或失败64 * @return 成功或失败
58 * @note 非常重要:使用本接口缓存的数据,如果没有用REGISTER_PROCESS_DEPENDENT_DATA注册,会立即被释放65 * @note 非常重要:使用本接口缓存的数据,如果没有用REGISTER_PROCESS_DEPENDENT_DATA注册,会立即被释放
59 */66 */
60- template<typename T>67+ template <typename T>
61 bool Inject(std::shared_ptr<T> ptr)68 bool Inject(std::shared_ptr<T> ptr)
62 {69 {
63- if (ptr == nullptr) {70+ if (ptr == nullptr)
71+ {
64 return false;72 return false;
65 }73 }
66 74 
67- if (GetPtr<T>() != nullptr) { // 不支持注入相同类型数据75+ if (GetPtr<T>() != nullptr)
76+ { // 不支持注入相同类型数据
68 return false;77 return false;
69 }78 }
70 79 
@@ -73,7 +82,7 @@ public:
73 container->data = ptr;82 container->data = ptr;
74 return InputToData(typeid(T), container);83 return InputToData(typeid(T), container);
75 }84 }
76- template<typename T>85+ template <typename T>
77 std::shared_ptr<T> GetPtr() const86 std::shared_ptr<T> GetPtr() const
78 {87 {
79 return Cast<T>(GetPtr(typeid(T)));88 return Cast<T>(GetPtr(typeid(T)));
@@ -87,32 +96,30 @@ public:
87 */96 */
88 std::set<std::type_index> RemoveRestData(const std::set<std::type_index>& keepingDataType);97 std::set<std::type_index> RemoveRestData(const std::set<std::type_index>& keepingDataType);
89 98 
90- std::size_t Size()99+ std::size_t Size() { return data_.size(); }
91- {
92- return data_.size();
93- }
94 100 
95 DataInventory() = default;101 DataInventory() = default;
96 ~DataInventory() = default;102 ~DataInventory() = default;
97 DataInventory(const DataInventory&) = delete;103 DataInventory(const DataInventory&) = delete;
98 DataInventory& operator=(const DataInventory&) = delete;104 DataInventory& operator=(const DataInventory&) = delete;
99- DataInventory(DataInventory&& dataInventory) : data_(std::move(dataInventory.data_))105+ DataInventory(DataInventory&& dataInventory) : data_(std::move(dataInventory.data_)) {}
100- {
101- }
102 DataInventory& operator=(DataInventory&& dataInventory)106 DataInventory& operator=(DataInventory&& dataInventory)
103 {107 {
104- if (&dataInventory == this) {108+ if (&dataInventory == this)
109+ {
105 return *this;110 return *this;
106 }111 }
107 data_.swap(dataInventory.data_);112 data_.swap(dataInventory.data_);
108 dataInventory.data_.clear();113 dataInventory.data_.clear();
109 return *this;114 return *this;
110 }115 }
111-private:116+ 
112- template<typename T>117+ private:
118+ template <typename T>
113 std::shared_ptr<T> Cast(const BaseTypePtr& ptr) const119 std::shared_ptr<T> Cast(const BaseTypePtr& ptr) const
114 {120 {
115- if (ptr == nullptr) {121+ if (ptr == nullptr)
122+ {
116 return {};123 return {};
117 }124 }
118 auto customPtr = std::static_pointer_cast<CustomType<T>>(ptr);125 auto customPtr = std::static_pointer_cast<CustomType<T>>(ptr);
@@ -121,13 +128,13 @@ private:
121 bool InputToData(std::type_index idx, BaseTypePtr ptr);128 bool InputToData(std::type_index idx, BaseTypePtr ptr);
122 BaseTypePtr GetPtr(std::type_index idx) const;129 BaseTypePtr GetPtr(std::type_index idx) const;
123 130 
124-private:131+ private:
125 std::unordered_map<std::type_index, BaseTypePtr> data_;132 std::unordered_map<std::type_index, BaseTypePtr> data_;
126 mutable std::mutex mutex_;133 mutable std::mutex mutex_;
127};134};
128 135 
129-}136+} // namespace Infra
130 137 
131-}138+} // namespace Analysis
132 139 
133-#endif140+#endif
@@ -16,19 +16,22 @@
16#ifndef ANALYSIS_INFRASTRUCTURE_PROCESS_INCLUDE_PROCESS_CONTROL_H16#ifndef ANALYSIS_INFRASTRUCTURE_PROCESS_INCLUDE_PROCESS_CONTROL_H
17#define ANALYSIS_INFRASTRUCTURE_PROCESS_INCLUDE_PROCESS_CONTROL_H17#define ANALYSIS_INFRASTRUCTURE_PROCESS_INCLUDE_PROCESS_CONTROL_H
18 18 
19-#include <map>
20-#include <vector>
21#include <functional>19#include <functional>
20+#include <map>
22#include <memory>21#include <memory>
22+#include <vector>
23 23 
24#include "analysis/csrc/infrastructure/process/include/process_register.h"24#include "analysis/csrc/infrastructure/process/include/process_register.h"
25#include "analysis/csrc/infrastructure/utils/thread_pool.h"25#include "analysis/csrc/infrastructure/utils/thread_pool.h"
26 26 
27-namespace Analysis {27+namespace Analysis
28+{
28 29 
29-namespace Infra {30+namespace Infra
31+{
30 32 
31-struct ProcessStatistics {33+struct ProcessStatistics
34+{
32 std::string processName; // 以后升级到C++17或更高版本,可以使用std::string_view代替std::string35 std::string processName; // 以后升级到C++17或更高版本,可以使用std::string_view代替std::string
33 std::vector<std::string> dependProcessNames;36 std::vector<std::string> dependProcessNames;
34 uint32_t returnCode;37 uint32_t returnCode;
@@ -38,27 +41,35 @@ struct ProcessStatistics {
38 bool dfxStop; // DFX需求:可以指定执行完哪个Process停止41 bool dfxStop; // DFX需求:可以指定执行完哪个Process停止
39};42};
40 43 
41-struct OneLevelStat {44+struct OneLevelStat
45+{
42 bool generalResult;46 bool generalResult;
43 std::vector<ProcessStatistics> processStatistics;47 std::vector<ProcessStatistics> processStatistics;
44};48};
45 49 
46-struct ExecuteProcessStat {50+struct ExecuteProcessStat
51+{
47 uint32_t chipId;52 uint32_t chipId;
48 std::vector<OneLevelStat> allLevelStat;53 std::vector<OneLevelStat> allLevelStat;
49};54};
50 55 
56+struct ProcessControlOptions
57+{
58+ bool releaseUnusedData = true;
59+ // 0 selects min(10, hardware_concurrency()).
60+ uint32_t maxWorkerThreads = 0;
61+};
51 62 
52void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir, std::string& log);63void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir, std::string& log);
53 64 
54- 
55/**65/**
56 * @brief 流程控制类66 * @brief 流程控制类
57 * 本类用于控制用户通过Register注册的所有流程。支持同一个level并发运行,并提供一些DFX功能67 * 本类用于控制用户通过Register注册的所有流程。支持同一个level并发运行,并提供一些DFX功能
58 */68 */
59-class ProcessControl final {69+class ProcessControl final
60-public:70+{
61- explicit ProcessControl(ProcessCollection& processes);71+ public:
72+ explicit ProcessControl(ProcessCollection& processes, ProcessControlOptions options = {});
62 ~ProcessControl();73 ~ProcessControl();
63 74 
64 bool ExecuteProcess(DataInventory& dataInventory, const Context& context);75 bool ExecuteProcess(DataInventory& dataInventory, const Context& context);
@@ -68,13 +79,13 @@ public:
68 79 
69 bool VerifyProcess(const ProcessCollection& chipRelatedProcess) const;80 bool VerifyProcess(const ProcessCollection& chipRelatedProcess) const;
70 81 
71-private:82+ private:
72 class Impl;83 class Impl;
73 std::unique_ptr<Impl> impl_;84 std::unique_ptr<Impl> impl_;
74};85};
75 86 
76-}87+} // namespace Infra
77 88 
78-}89+} // namespace Analysis
79 90 
80-#endif91+#endif
@@ -0,0 +1,38 @@
1+/* -------------------------------------------------------------------------
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This file is part of the MindStudio project.
4+ * -------------------------------------------------------------------------*/
5+ 
6+#ifndef ANALYSIS_INFRASTRUCTURE_PROCESS_TOPO_CALLBACK_PROCESS_H
7+#define ANALYSIS_INFRASTRUCTURE_PROCESS_TOPO_CALLBACK_PROCESS_H
8+ 
9+#include <functional>
10+#include <utility>
11+ 
12+#include "analysis/csrc/infrastructure/dfx/error_code.h"
13+#include "analysis/csrc/infrastructure/process/include/process.h"
14+#include "analysis/csrc/infrastructure/process/include/topo_graph.h"
15+ 
16+namespace Analysis
17+{
18+namespace Application
19+{
20+using TopoProcessCallback = std::function<bool(Infra::DataInventory&)>;
21+ 
22+class TopoCallbackProcess final : public Infra::Process
23+{
24+ public:
25+ explicit TopoCallbackProcess(TopoProcessCallback callback) : callback_(std::move(callback)) {}
26+ 
27+ private:
28+ uint32_t ProcessEntry(Infra::DataInventory& dataInventory, const Infra::Context&) override
29+ {
30+ return callback_ != nullptr && callback_(dataInventory) ? ANALYSIS_OK : ANALYSIS_ERROR;
31+ }
32+ 
33+ TopoProcessCallback callback_;
34+};
35+} // namespace Application
36+} // namespace Analysis
37+ 
38+#endif // ANALYSIS_INFRASTRUCTURE_PROCESS_TOPO_CALLBACK_PROCESS_H
@@ -0,0 +1,212 @@
1+/* -------------------------------------------------------------------------
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This file is part of the MindStudio project.
4+ * -------------------------------------------------------------------------*/
5+ 
6+#ifndef ANALYSIS_INFRASTRUCTURE_PROCESS_TOPO_GRAPH_H
7+#define ANALYSIS_INFRASTRUCTURE_PROCESS_TOPO_GRAPH_H
8+ 
9+#include <cstddef>
10+#include <cstdint>
11+#include <functional>
12+#include <memory>
13+#include <string>
14+#include <typeindex>
15+#include <unordered_map>
16+#include <utility>
17+#include <vector>
18+ 
19+#include "analysis/csrc/application/timeline/json_process_enum.h"
20+#include "analysis/csrc/infrastructure/process/include/process.h"
21+#include "analysis/csrc/infrastructure/process/include/process_struct.h"
22+#include "analysis/csrc/infrastructure/resource/chip_id.h"
23+ 
24+namespace Analysis
25+{
26+namespace Application
27+{
28+class DBAssembler;
29+class TimelineManager;
30+constexpr size_t MAX_TOPO_NODE_COUNT = 64;
31+ 
32+enum class TopoNodeStage : uint8_t
33+{
34+ DATA_PROCESSING, // Domain data processing.
35+ SUMMARY_GENERATION, // Application summary generation.
36+ DATABASE_PERSISTENCE, // Application database persistence.
37+ TIMELINE_EXPORT, // Application timeline export.
38+ FLOW_CONTROL, // Topology lifecycle control.
39+};
40+ 
41+struct TopoNodeId
42+{
43+ TopoNodeStage stage;
44+ std::string name;
45+ 
46+ bool operator==(const TopoNodeId& other) const { return stage == other.stage && name == other.name; }
47+};
48+ 
49+struct TopoNodeIdHash
50+{
51+ size_t operator()(const TopoNodeId& id) const
52+ {
53+ return std::hash<uint8_t>()(static_cast<uint8_t>(id.stage)) ^ (std::hash<std::string>()(id.name) << 1U);
54+ }
55+};
56+ 
57+struct TopoBuildContext
58+{
59+ std::string profPath;
60+ std::string outputPath;
61+ std::vector<JsonProcess> timelineProcesses;
62+ std::shared_ptr<TimelineManager> timelineSession;
63+ std::shared_ptr<DBAssembler> dbSession;
64+};
65+ 
66+using TopoNodeCreatorFactory = std::function<Infra::ProcessCreator(const TopoBuildContext&)>;
67+using TopoDependencyResolver =
68+ std::function<std::vector<TopoNodeId>(const TopoBuildContext&, const std::vector<TopoNodeId>&)>;
69+ 
70+struct TopoNodeDefinition
71+{
72+ TopoNodeId id;
73+ std::vector<TopoNodeId> processDependencies;
74+ std::vector<std::type_index> inputDataTypes;
75+ bool mandatory{false};
76+ std::vector<uint32_t> chipIds;
77+ TopoNodeCreatorFactory creatorFactory;
78+ TopoDependencyResolver dependencyResolver;
79+ std::type_index runtimeType{typeid(void)};
80+};
81+ 
82+using TopoNodeCollection = std::unordered_map<TopoNodeId, TopoNodeDefinition, TopoNodeIdHash>;
83+ 
84+class TopoNodeRegistry
85+{
86+ public:
87+ static bool Register(TopoNodeDefinition definition);
88+ static const TopoNodeCollection& GetDefinitions();
89+ static const TopoNodeDefinition* Find(const TopoNodeId& id);
90+ static const TopoNodeDefinition* FindProcessorByName(const std::string& name);
91+ static const TopoNodeDefinition* FindProcessorByRuntimeType(std::type_index runtimeType);
92+ static TopoNodeCollection& MutableDefinitions();
93+};
94+ 
95+class TopoNodeSequenceRegister
96+{
97+ public:
98+ TopoNodeSequenceRegister(TopoNodeId id, std::type_index runtimeType, bool mandatory,
99+ std::vector<TopoNodeId> dependencies, TopoNodeCreatorFactory creatorFactory,
100+ TopoDependencyResolver dependencyResolver = nullptr);
101+};
102+ 
103+class TopoNodeDataRegister
104+{
105+ public:
106+ TopoNodeDataRegister(TopoNodeId id, std::vector<std::type_index> inputDataTypes);
107+};
108+ 
109+template <typename... T>
110+struct TopoNodeTypeIndexList
111+{
112+ TopoNodeTypeIndexList() : types{typeid(T)...} {}
113+ std::vector<std::type_index> types;
114+};
115+ 
116+class TopoGraphBuilder
117+{
118+ public:
119+ bool Build(const TopoBuildContext& context, const std::vector<TopoNodeId>& roots,
120+ Infra::ProcessCollection& processes);
121+ 
122+ private:
123+ bool AddNode(const TopoNodeId& id, std::type_index& key);
124+ bool ResolveDependencies(const TopoNodeDefinition& definition, std::vector<std::type_index>& dependencies);
125+ std::type_index AllocateSyntheticKey(TopoNodeStage stage);
126+ 
127+ private:
128+ const TopoBuildContext* context_{};
129+ const std::vector<TopoNodeId>* roots_{};
130+ Infra::ProcessCollection* processes_{};
131+ std::unordered_map<TopoNodeId, std::type_index, TopoNodeIdHash> nodeKeys_;
132+ std::unordered_map<TopoNodeStage, size_t> nextSyntheticIndex_;
133+ std::unordered_map<TopoNodeId, bool, TopoNodeIdHash> visiting_;
134+};
135+} // namespace Application
136+} // namespace Analysis
137+ 
138+/**
139+ *
140+ * TOPO_NODE(stage, name)
141+ * @param stage 节点所属业务阶段,取值为 TopoNodeStage 枚举值。
142+ * 例如 DATA_PROCESSING、SUMMARY_GENERATION、
143+ * DATABASE_PERSISTENCE、TIMELINE_EXPORT、FLOW_CONTROL。
144+ * @param name 阶段内稳定且唯一的业务节点名称。相同 stage 与 name
145+ * 共同组成 TopoNodeId,必须与依赖节点及数据注册中的节点标识保持一致。
146+ *
147+ * TOPO_DEPS(...)
148+ * @param ... 零个或多个由 TOPO_NODE(...) 构造的前置依赖节点。
149+ * 调度器会先执行全部依赖节点,再执行当前节点;依赖节点必须已注册,
150+ * 且依赖关系不能形成环。无依赖时使用 TOPO_DEPS()。
151+ *
152+ * REGISTER_TOPO_NODE_SEQUENCE(RuntimeType, NodeId, Mandatory, CreatorFactory,
153+ * Dependencies, Resolver)
154+ * @param RuntimeType DATA_PROCESSING 阶段节点对应具体处理器类型,
155+ * 使用 typeid(ProcessorType);其余阶段节点使用 typeid(void),
156+ * 由拓扑构建器生成 synthetic key。
157+ * @param NodeId 当前节点标识,使用 TOPO_NODE(stage, name) 构造。
158+ * @param Mandatory 是否为必需节点。true 表示节点执行失败会导致本次流程失败;
159+ * false 表示该节点失败后流程可继续执行。
160+ * @param CreatorFactory 节点创建工厂,接收 TopoBuildContext 并返回 ProcessCreator。
161+ * 工厂或其创建的 Process 为空时,节点构建失败。
162+ * @param Dependencies 静态依赖列表,使用 TOPO_DEPS(...) 构造。
163+ * @param Resolver 可选动态依赖解析器;根据 TopoBuildContext 和根节点列表
164+ * 补充依赖。没有动态依赖时传入 nullptr。
165+ *
166+ * REGISTER_TOPO_NODE_DEPENDENT_DATA(NodeId, ...)
167+ * @param NodeId 当前节点标识,必须与 REGISTER_TOPO_NODE_SEQUENCE 的 NodeId 完全一致。
168+ * @param ... 节点从 DataInventory 读取的输入数据类型,例如
169+ * std::vector<TaskInfoData>。类型必须与生产节点写入的类型一致。
170+ * 该宏必须定义在同一节点的 REGISTER_TOPO_NODE_SEQUENCE 之后。
171+ *
172+ * 示例:注册一个时间线导出节点。它依赖时间线预处理和任务数据处理,
173+ * 并声明运行时从 DataInventory 读取的输入类型。
174+ *
175+ * REGISTER_TOPO_NODE_SEQUENCE(
176+ * typeid(void),
177+ * TOPO_NODE(TIMELINE_EXPORT, PROCESS_TASK),
178+ * true,
179+ * TimelineManager::CreateTimelineAssembler(PROCESS_TASK),
180+ * TOPO_DEPS(TOPO_NODE(FLOW_CONTROL, TIMELINE_PRE_DUMP),
181+ * TOPO_NODE(DATA_PROCESSING, PROCESSOR_NAME_TASK)),
182+ * nullptr);
183+ *
184+ * REGISTER_TOPO_NODE_DEPENDENT_DATA(
185+ * TOPO_NODE(TIMELINE_EXPORT, PROCESS_TASK),
186+ * std::vector<TaskInfoData>,
187+ * std::vector<AscendTaskData>);
188+ */
189+ 
190+#define TOPO_NODE_REGISTER_CONCAT_INNER(left, right) left##right
W
Wwangzixuan8月7日

[review] 这里新增了较多的宏定义内容,对于宏定义方法来说,本身的可理解性相比一般业务代码会差。这里建议增加相关宏定义的介绍和示例说明。方便后续维护整体业务。避免相关宏在演进过程中逐渐丢失。

likedislike
Wangang Yu
Wangang Yu
8月11日 评论:
191+#define TOPO_NODE_REGISTER_CONCAT(left, right) TOPO_NODE_REGISTER_CONCAT_INNER(left, right)
192+ 
193+#define TOPO_NODE(stage, name) (Analysis::Application::TopoNodeId{Analysis::Application::TopoNodeStage::stage, name})
194+#define TOPO_DEPS(...) (std::vector<Analysis::Application::TopoNodeId>{__VA_ARGS__})
195+ 
196+#define REGISTER_TOPO_NODE_SEQUENCE(RuntimeType, NodeId, Mandatory, CreatorFactory, Dependencies, Resolver) \
197+ REGISTER_TOPO_NODE_SEQUENCE_IMPL(RuntimeType, NodeId, Mandatory, CreatorFactory, Dependencies, Resolver, __LINE__)
198+ 
199+#define REGISTER_TOPO_NODE_SEQUENCE_IMPL(RuntimeType, NodeId, Mandatory, CreatorFactory, Dependencies, Resolver, line) \
200+ static Analysis::Application::TopoNodeSequenceRegister TOPO_NODE_REGISTER_CONCAT(topoNodeSequenceRegister, line)( \
201+ NodeId, RuntimeType, Mandatory, Dependencies, CreatorFactory, Resolver)
202+ 
203+#define REGISTER_TOPO_NODE_DEPENDENT_DATA(NodeId, ...) \
204+ REGISTER_TOPO_NODE_DEPENDENT_DATA_IMPL(NodeId, __LINE__, __VA_ARGS__)
205+ 
206+#define REGISTER_TOPO_NODE_DEPENDENT_DATA_IMPL(NodeId, line, ...) \
207+ static Analysis::Application::TopoNodeTypeIndexList<__VA_ARGS__> TOPO_NODE_REGISTER_CONCAT(topoNodeDataHelper, \
208+ line); \
209+ static Analysis::Application::TopoNodeDataRegister TOPO_NODE_REGISTER_CONCAT(topoNodeDataRegister, line)( \
210+ NodeId, std::move(TOPO_NODE_REGISTER_CONCAT(topoNodeDataHelper, line).types))
211+ 
212+#endif // ANALYSIS_INFRASTRUCTURE_PROCESS_TOPO_GRAPH_H
@@ -14,24 +14,38 @@
14 * See the Mulan PSL v2 for more details.14 * See the Mulan PSL v2 for more details.
15 * -------------------------------------------------------------------------*/15 * -------------------------------------------------------------------------*/
16#include "analysis/csrc/infrastructure/process/include/process_control.h"16#include "analysis/csrc/infrastructure/process/include/process_control.h"
17+ 
17#include <algorithm>18#include <algorithm>
18-#include <iostream>
19#include <chrono>19#include <chrono>
20-#include <sstream>20+#include <condition_variable>
21+#include <exception>
22+#include <iostream>
23+#include <mutex>
21#include <set>24#include <set>
25+#include <sstream>
26+#include <thread>
27+#include <unordered_map>
28+#include <utility>
29+ 
30+#include "analysis/csrc/infrastructure/dfx/error_code.h"
22#include "analysis/csrc/infrastructure/process/process_topo.h"31#include "analysis/csrc/infrastructure/process/process_topo.h"
23 32 
24-namespace Analysis {33+namespace Analysis
34+{
25 35 
26-namespace Infra {36+namespace Infra
27-namespace {37+{
38+namespace
39+{
28 40 
29void GetDepProcessNames(const RegProcessInfo& procInfo, const ProcessCollection& allRegProcess,41void GetDepProcessNames(const RegProcessInfo& procInfo, const ProcessCollection& allRegProcess,
30 std::vector<std::string>& depProcNames)42 std::vector<std::string>& depProcNames)
31{43{
32- for (const auto& typeIndex : procInfo.processDependence) {44+ for (const auto& typeIndex : procInfo.processDependence)
45+ {
33 auto it = allRegProcess.find(typeIndex);46 auto it = allRegProcess.find(typeIndex);
34- if (it == allRegProcess.end()) {47+ if (it == allRegProcess.end())
48+ {
35 continue;49 continue;
36 }50 }
37 depProcNames.emplace_back(it->second.processName);51 depProcNames.emplace_back(it->second.processName);
@@ -40,28 +54,36 @@ void GetDepProcessNames(const RegProcessInfo& procInfo, const ProcessCollection&
40 54 
41void FillStatisticianDependence(const ProcessCollection& regProcess, std::vector<ProcessStatistics>& stat)55void FillStatisticianDependence(const ProcessCollection& regProcess, std::vector<ProcessStatistics>& stat)
42{56{
43- for (auto& node : stat) {57+ for (auto& node : stat)
44- for (const auto& regPair : regProcess) {58+ {
45- if (node.processName == regPair.second.processName) {59+ for (const auto& regPair : regProcess)
60+ {
61+ if (node.processName == regPair.second.processName)
62+ {
46 GetDepProcessNames(regPair.second, regProcess, node.dependProcessNames);63 GetDepProcessNames(regPair.second, regProcess, node.dependProcessNames);
47 }64 }
48 }65 }
49 }66 }
50}67}
51 68 
52-}69+} // namespace
53 70 
54-class ProcessControl::Impl final {71+class ProcessControl::Impl final
55-public:72+{
56- explicit Impl(ProcessCollection& processes)73+ public:
57- : allProcess_(std::move(processes)) { stat_.chipId = 0; }74+ explicit Impl(ProcessCollection& processes, ProcessControlOptions options)
75+ : allProcess_(std::move(processes)), options_(options)
76+ {
77+ stat_.chipId = 0;
78+ }
58 ~Impl() = default;79 ~Impl() = default;
59 80 
60 bool VerifyProcess(const ProcessCollection& chipRelatedProcess) const81 bool VerifyProcess(const ProcessCollection& chipRelatedProcess) const
61 {82 {
62 auto verifyProcess = chipRelatedProcess;83 auto verifyProcess = chipRelatedProcess;
63 auto preparedProcess = TakeAwayPreparedProcess(verifyProcess);84 auto preparedProcess = TakeAwayPreparedProcess(verifyProcess);
64- while (!preparedProcess.empty()) {85+ while (!preparedProcess.empty())
86+ {
65 preparedProcess = TakeAwayPreparedProcess(verifyProcess);87 preparedProcess = TakeAwayPreparedProcess(verifyProcess);
66 }88 }
67 return verifyProcess.empty();89 return verifyProcess.empty();
@@ -74,7 +96,8 @@ public:
74 96 
75 ProcessTopo processTopoBuilder(allProcess_);97 ProcessTopo processTopoBuilder(allProcess_);
76 auto chipRelatedProcess = processTopoBuilder.BuildProcessControlTopoByChip(chipId_);98 auto chipRelatedProcess = processTopoBuilder.BuildProcessControlTopoByChip(chipId_);
77- if (!VerifyProcess(chipRelatedProcess)) {99+ if (!VerifyProcess(chipRelatedProcess))
100+ {
78 ERROR("Topo Verify failed!");101 ERROR("Topo Verify failed!");
79 return false;102 return false;
80 }103 }
@@ -82,111 +105,226 @@ public:
82 return RunProcesses(chipRelatedProcess, dataInventory, context);105 return RunProcesses(chipRelatedProcess, dataInventory, context);
83 }106 }
84 107 
85- ExecuteProcessStat GetExecuteStat() const108+ ExecuteProcessStat GetExecuteStat() const { return stat_; }
86- {
87- return stat_;
88- }
89 109 
90-private:110+ private:
91 /**111 /**
92 * @brief 拓扑排序算法执行所有Process 使用的算法为卡恩算法112 * @brief 拓扑排序算法执行所有Process 使用的算法为卡恩算法
93 * @param chipRelatedProcess 相应Chip的Process集合113 * @param chipRelatedProcess 相应Chip的Process集合
94 */114 */
95- bool RunProcesses(ProcessCollection& chipRelatedProcess, DataInventory& dataInventory,115+ bool RunProcesses(ProcessCollection& chipRelatedProcess, DataInventory& dataInventory, const Context& context)
96- const Context& context)
97 {116 {
98- auto regProcessCopy = chipRelatedProcess; // 这里COPY一份是为了DFX中填dependProcess字段117+ const ProcessCollection regProcessCopy = chipRelatedProcess;
118+ if (chipRelatedProcess.empty())
119+ {
120+ return true;
121+ }
99 122 
100- size_t levelIndex = 0;123+ using ProcessKey = std::type_index;
101- auto preparedProcess = TakeAwayPreparedProcess(chipRelatedProcess);124+ struct CompletedProcess
102- while (!preparedProcess.empty()) {125+ {
103- std::vector<ProcessStatistics> stat(preparedProcess.size());126+ ProcessKey key;
104- Analysis::Utils::ThreadPool pool(preparedProcess.size());127+ size_t level;
105- pool.Start();128+ ProcessStatistics statistics;
106- RunPreparedProcess(preparedProcess, stat, pool, dataInventory, context);129+ };
107- pool.WaitAllTasks();
108- pool.Stop();
109 130 
110- // DFX131+ std::unordered_map<ProcessKey, size_t> unresolvedDependencies;
111- FillStatisticianDependence(regProcessCopy, stat);132+ std::unordered_map<ProcessKey, std::vector<ProcessKey>> dependents;
133+ std::unordered_map<ProcessKey, size_t> levels;
134+ std::vector<ProcessKey> readyProcesses;
135+ for (const auto& processPair : chipRelatedProcess)
136+ {
137+ const ProcessKey& key = processPair.first;
138+ unresolvedDependencies.emplace(key, processPair.second.processDependence.size());
139+ levels.emplace(key, 0UL);
140+ if (processPair.second.processDependence.empty())
141+ {
142+ readyProcesses.emplace_back(key);
143+ }
144+ for (const auto& dependency : processPair.second.processDependence)
145+ {
146+ dependents[dependency].emplace_back(key);
147+ }
148+ }
149+ 
150+ const uint32_t hardwareWorkerCount = std::thread::hardware_concurrency();
151+ const uint32_t defaultWorkerCount = hardwareWorkerCount == 0 ? 10U : std::min(10U, hardwareWorkerCount);
152+ const uint32_t configuredWorkerCount =
153+ options_.maxWorkerThreads == 0 ? defaultWorkerCount : options_.maxWorkerThreads;
154+ const uint32_t workerCount =
155+ std::max(1U, std::min(configuredWorkerCount, static_cast<uint32_t>(chipRelatedProcess.size())));
156+ Analysis::Utils::ThreadPool pool(workerCount);
157+ if (!pool.Start())
158+ {
159+ ERROR("Start process worker pool failed.");
160+ return false;
161+ }
162+ 
163+ std::mutex schedulerMutex;
164+ std::condition_variable schedulerDone;
165+ ProcessCollection remainingProcesses = chipRelatedProcess;
166+ std::vector<CompletedProcess> completedProcesses;
167+ size_t activeTaskCount = 0;
168+ size_t completedTaskCount = 0;
169+ size_t releaseIndex = 0;
170+ bool stopScheduling = false;
171+ 
172+ std::function<void(const ProcessKey&)> schedule;
173+ schedule = [&](const ProcessKey& key)
174+ {
175+ const auto processIter = chipRelatedProcess.find(key);
176+ if (processIter == chipRelatedProcess.end())
177+ {
178+ ERROR("Scheduled process is not registered.");
179+ stopScheduling = true;
180+ return;
181+ }
182+ ++activeTaskCount;
183+ const RegProcessInfo processInfo = processIter->second;
184+ const size_t level = levels.at(key);
185+ pool.AddTask(
186+ [&, key, level, processInfo]()
187+ {
188+ ProcessStatistics statistics{};
189+ const auto startTime = std::chrono::steady_clock::now();
190+ if (!processInfo.creator)
191+ {
192+ ERROR("creator==nullptr, process name: %", processInfo.processName);
193+ }
194+ else
195+ {
196+ try
197+ {
198+ auto proc = processInfo.creator();
199+ if (proc != nullptr)
200+ {
201+ statistics.returnCode = proc->Run(dataInventory, context);
202+ statistics.mandatory = processInfo.mandatory;
203+ }
204+ }
205+ catch (const std::exception& exception)
206+ {
207+ ERROR("Process % threw an exception: %", processInfo.processName, exception.what());
208+ statistics.returnCode = ANALYSIS_ERROR;
209+ statistics.mandatory = processInfo.mandatory;
210+ }
211+ catch (...)
212+ {
213+ ERROR("Process % threw an unknown exception.", processInfo.processName);
214+ statistics.returnCode = ANALYSIS_ERROR;
215+ statistics.mandatory = processInfo.mandatory;
216+ }
217+ }
218+ const auto endTime = std::chrono::steady_clock::now();
219+ statistics.startTime =
220+ std::chrono::duration_cast<std::chrono::microseconds>(startTime.time_since_epoch()).count();
221+ statistics.duration =
222+ std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
223+ statistics.processName = processInfo.processName;
224+ const std::string& stopProcessName = context.GetDfxStopAtName();
225+ statistics.dfxStop = !stopProcessName.empty() && stopProcessName == processInfo.processName;
226+ 
227+ std::unique_lock<std::mutex> lock(schedulerMutex);
228+ --activeTaskCount;
229+ ++completedTaskCount;
230+ completedProcesses.push_back({key, level, std::move(statistics)});
231+ const ProcessStatistics& completedStat = completedProcesses.back().statistics;
232+ remainingProcesses.erase(key);
233+ if (options_.releaseUnusedData)
234+ {
235+ ReleaseNoLongerUsedData(remainingProcesses, dataInventory, releaseIndex++);
236+ }
237+ 
238+ if ((completedStat.returnCode != ANALYSIS_OK && completedStat.mandatory) || completedStat.dfxStop)
239+ {
240+ stopScheduling = true;
241+ }
242+ if (!stopScheduling)
243+ {
244+ const auto dependentIter = dependents.find(key);
245+ if (dependentIter != dependents.end())
246+ {
247+ for (const auto& dependent : dependentIter->second)
248+ {
249+ size_t& pendingCount = unresolvedDependencies.at(dependent);
250+ levels.at(dependent) = std::max(levels.at(dependent), level + 1);
251+ if (--pendingCount == 0)
252+ {
253+ schedule(dependent);
254+ }
255+ }
256+ }
257+ }
258+ schedulerDone.notify_all();
259+ });
260+ };
261+ 
262+ {
263+ std::unique_lock<std::mutex> lock(schedulerMutex);
264+ for (const auto& readyProcess : readyProcesses)
265+ {
266+ schedule(readyProcess);
267+ }
268+ }
269+ {
270+ std::unique_lock<std::mutex> lock(schedulerMutex);
271+ schedulerDone.wait(lock,
272+ [&]() {
273+ return activeTaskCount == 0 &&
274+ (stopScheduling || completedTaskCount == chipRelatedProcess.size());
275+ });
276+ }
277+ pool.Stop();
278+ 
279+ std::map<size_t, std::vector<ProcessStatistics>> statisticsByLevel;
280+ for (auto& completed : completedProcesses)
281+ {
282+ statisticsByLevel[completed.level].emplace_back(std::move(completed.statistics));
283+ }
284+ bool overallResult = !stopScheduling;
285+ for (auto& levelStatistics : statisticsByLevel)
286+ {
287+ FillStatisticianDependence(regProcessCopy, levelStatistics.second);
112 bool dfxStop = false;288 bool dfxStop = false;
113- auto ret = GetStatistician(std::move(stat), dfxStop);289+ const bool levelResult = GetStatistician(std::move(levelStatistics.second), dfxStop);
114- if (!ret) {290+ overallResult = overallResult && levelResult && !dfxStop;
115- WARN("mandatory process failed!");
116- return false;
117- }
118- if (dfxStop) {
119- PRINT_INFO("!!!!!!! DFX Stops !!!!!!!!");
120- return false;
121- }
122- ReleaseNoLongerUsedData(chipRelatedProcess, dataInventory, levelIndex++);
123- preparedProcess = TakeAwayPreparedProcess(chipRelatedProcess);
124 }291 }
125- return true;292+ if (stopScheduling)
126- }293+ {
127- 294+ PRINT_INFO("!!!!!!! DFX Stops or a mandatory process failed !!!!!!!!");
128- void RunPreparedProcess(ProcessCollection &preparedProcess, std::vector<ProcessStatistics> &stat,
129- Analysis::Utils::ThreadPool &pool, DataInventory& dataInventory,
130- const Context& context) const
131- {
132- size_t concurrentIndex{};
133- for (const auto& processNode : preparedProcess) {
134- pool.AddTask([&processNode, &stat, &dataInventory, &context, concurrentIndex]() {
135- auto startTime = std::chrono::steady_clock::now();
136- if (!processNode.second.creator) {
137- ERROR("creator==nullptr, process name: %", processNode.second.processName);
138- return;
139- }
140- auto proc = processNode.second.creator();
141- if (proc != nullptr) {
142- stat[concurrentIndex].returnCode = proc->Run(dataInventory, context);
143- stat[concurrentIndex].mandatory = processNode.second.mandatory;
144- }
145- auto endTime = std::chrono::steady_clock::now();
146- 
147- stat[concurrentIndex].startTime = std::chrono::duration_cast<std::chrono::microseconds>(
148- startTime.time_since_epoch()).count();
149- stat[concurrentIndex].duration = std::chrono::duration_cast<std::chrono::microseconds>(
150- endTime - startTime).count();
151- stat[concurrentIndex].processName = processNode.second.processName;
152- stat[concurrentIndex].dfxStop = false;
153- const std::string& stopProcessName = context.GetDfxStopAtName();
154- if (!stopProcessName.empty() && stopProcessName == processNode.second.processName) {
155- stat[concurrentIndex].dfxStop = true;
156- }
157- });
158- ++concurrentIndex;
159 }295 }
296+ return overallResult && completedTaskCount == chipRelatedProcess.size();
160 }297 }
161 298 
162 bool GetStatistician(std::vector<ProcessStatistics>&& statistics, bool& dfxStop)299 bool GetStatistician(std::vector<ProcessStatistics>&& statistics, bool& dfxStop)
163 {300 {
164- auto generalResult = std::all_of(statistics.begin(), statistics.end(), [](ProcessStatistics& node) {301+ auto generalResult = std::all_of(statistics.begin(), statistics.end(), [](ProcessStatistics& node)
165- return (node.returnCode == 0 || !node.mandatory);302+ { return (node.returnCode == 0 || !node.mandatory); });
166- });303+ dfxStop =
167- dfxStop = std::any_of(statistics.begin(), statistics.end(), [](ProcessStatistics& node) {304+ std::any_of(statistics.begin(), statistics.end(), [](ProcessStatistics& node) { return node.dfxStop; });
168- return node.dfxStop;
169- });
170 stat_.allLevelStat.emplace_back();305 stat_.allLevelStat.emplace_back();
171 auto& oneLevelStat = stat_.allLevelStat.back();306 auto& oneLevelStat = stat_.allLevelStat.back();
172 oneLevelStat.generalResult = generalResult;307 oneLevelStat.generalResult = generalResult;
173 oneLevelStat.processStatistics = std::move(statistics);308 oneLevelStat.processStatistics = std::move(statistics);
174- return generalResult; // Stop on error 这里是否停止还与Process类注册时,注册宏中mandatory字段确定309+ return generalResult; // Stop on error 这里是否停止还与Process类注册时,注册宏中mandatory字段确定
175 }310 }
176 311 
177 void ReleaseNoLongerUsedData(const ProcessCollection& chipRelatedProcess, DataInventory& dataInventory,312 void ReleaseNoLongerUsedData(const ProcessCollection& chipRelatedProcess, DataInventory& dataInventory,
178 size_t levelIndex)313 size_t levelIndex)
179 {314 {
180 std::set<std::type_index> dataTobeUsing;315 std::set<std::type_index> dataTobeUsing;
181- for (const auto& processInfo : chipRelatedProcess) {316+ for (const auto& processInfo : chipRelatedProcess)
182- for (const auto& dataType : processInfo.second.paramTypes) {317+ {
318+ for (const auto& dataType : processInfo.second.paramTypes)
319+ {
183 dataTobeUsing.insert(dataType);320 dataTobeUsing.insert(dataType);
184 }321 }
185 }322 }
186 auto removedTypes = dataInventory.RemoveRestData(dataTobeUsing);323 auto removedTypes = dataInventory.RemoveRestData(dataTobeUsing);
187 324 
188 std::string typeStr;325 std::string typeStr;
189- for (const auto& typeInfo : removedTypes) {326+ for (const auto& typeInfo : removedTypes)
327+ {
190 typeStr += typeInfo.name();328 typeStr += typeInfo.name();
191 typeStr += " ";329 typeStr += " ";
192 }330 }
@@ -197,8 +335,10 @@ private:
197 {335 {
198 ProcessCollection preparedProcess;336 ProcessCollection preparedProcess;
199 // 先拿走已经没有前向依赖的,即入度为0的节点337 // 先拿走已经没有前向依赖的,即入度为0的节点
200- for (auto it = chipRelatedProcess.begin(); it != chipRelatedProcess.end();) {338+ for (auto it = chipRelatedProcess.begin(); it != chipRelatedProcess.end();)
201- if (it->second.processDependence.empty()) {339+ {
340+ if (it->second.processDependence.empty())
341+ {
202 preparedProcess.insert({it->first, it->second});342 preparedProcess.insert({it->first, it->second});
203 it = chipRelatedProcess.erase(it);343 it = chipRelatedProcess.erase(it);
204 continue;344 continue;
@@ -207,9 +347,11 @@ private:
207 }347 }
208 348 
209 // 再将其它节点中的前向依赖删除,即修正其它节点的入度349 // 再将其它节点中的前向依赖删除,即修正其它节点的入度
210- for (auto& process : chipRelatedProcess) {350+ for (auto& process : chipRelatedProcess)
351+ {
211 auto& processDep = process.second.processDependence;352 auto& processDep = process.second.processDependence;
212- for (const auto& preparedNode : preparedProcess) {353+ for (const auto& preparedNode : preparedProcess)
354+ {
213 processDep.erase(std::remove(processDep.begin(), processDep.end(), preparedNode.first),355 processDep.erase(std::remove(processDep.begin(), processDep.end(), preparedNode.first),
214 processDep.end());356 processDep.end());
215 }357 }
@@ -217,10 +359,11 @@ private:
217 return preparedProcess;359 return preparedProcess;
218 }360 }
219 361 
220-private:362+ private:
221 ProcessCollection allProcess_;363 ProcessCollection allProcess_;
364+ ProcessControlOptions options_;
222 ExecuteProcessStat stat_; // dfx: 统计运行结果365 ExecuteProcessStat stat_; // dfx: 统计运行结果
223- uint32_t chipId_{}; // dfx: 记录运行什么芯片ID366+ uint32_t chipId_{}; // dfx: 记录运行什么芯片ID
224};367};
225 368 
226void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir, std::string& log)369void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir, std::string& log)
@@ -232,36 +375,41 @@ void RecordProcessStat(const ExecuteProcessStat& stat, const std::string& subDir
232 375 
233 auto levelCount = stat.allLevelStat.size();376 auto levelCount = stat.allLevelStat.size();
234 ss << "chip id: " << stat.chipId << ", process levels:" << levelCount << std::endl;377 ss << "chip id: " << stat.chipId << ", process levels:" << levelCount << std::endl;
235- for (size_t i = 0; i < levelCount; ++i) {378+ for (size_t i = 0; i < levelCount; ++i)
379+ {
236 const auto& node = stat.allLevelStat[i];380 const auto& node = stat.allLevelStat[i];
237 ss << "-------------------------------------------------------------------------------" << std::endl;381 ss << "-------------------------------------------------------------------------------" << std::endl;
238 ss << "level[" << i << "] generalResult:" << std::boolalpha << node.generalResult << std::noboolalpha382 ss << "level[" << i << "] generalResult:" << std::boolalpha << node.generalResult << std::noboolalpha
239- << ", process num:" << node.processStatistics.size() << std::endl;383+ << ", process num:" << node.processStatistics.size() << std::endl;
240 size_t j = 0;384 size_t j = 0;
241- for (const auto& proc : node.processStatistics) {385+ for (const auto& proc : node.processStatistics)
242- ss << "\tprocess" << j++ << "[" << proc.processName << "]:" << "return: 0x"386+ {
243- << std::hex << proc.returnCode << std::dec << ", mandatory:"387+ ss << "\tprocess" << j++ << "[" << proc.processName << "]:" << "return: 0x" << std::hex << proc.returnCode
244- << std::boolalpha << proc.mandatory << std::noboolalpha << std::endl;388+ << std::dec << ", mandatory:" << std::boolalpha << proc.mandatory << std::noboolalpha << std::endl;
245 ss << "\t\tdependProcessNames: ";389 ss << "\t\tdependProcessNames: ";
246- for (const auto& depName : proc.dependProcessNames) {390+ for (const auto& depName : proc.dependProcessNames)
391+ {
247 ss << depName << ", ";392 ss << depName << ", ";
248 }393 }
249- ss << std::endl << "\t\tstartTime:" << proc.startTime << " us, duration: "394+ ss << std::endl
250- << proc.duration << " us" << std::endl;395+ << "\t\tstartTime:" << proc.startTime << " us, duration: " << proc.duration << " us" << std::endl;
251 }396 }
252 }397 }
253 ss << std::endl;398 ss << std::endl;
254 log += ss.str();399 log += ss.str();
255}400}
256 401 
257-ProcessControl::ProcessControl(ProcessCollection& processes)402+ProcessControl::ProcessControl(ProcessCollection& processes, ProcessControlOptions options)
258- : impl_(new(std::nothrow) Impl(processes)) {}403+ : impl_(new(std::nothrow) Impl(processes, options))
404+{
405+}
259 406 
260ProcessControl::~ProcessControl() = default;407ProcessControl::~ProcessControl() = default;
261 408 
262bool ProcessControl::ExecuteProcess(DataInventory& dataInventory, const Context& context)409bool ProcessControl::ExecuteProcess(DataInventory& dataInventory, const Context& context)
263{410{
264- if (!impl_) {411+ if (!impl_)
412+ {
265 ERROR("ProcessControl Impl create failed!");413 ERROR("ProcessControl Impl create failed!");
266 return false;414 return false;
267 };415 };
@@ -271,7 +419,8 @@ bool ProcessControl::ExecuteProcess(DataInventory& dataInventory, const Context&
271// 获取运行结果 key为level, value为统计结构419// 获取运行结果 key为level, value为统计结构
272ExecuteProcessStat ProcessControl::GetExecuteStat() const420ExecuteProcessStat ProcessControl::GetExecuteStat() const
273{421{
274- if (!impl_) {422+ if (!impl_)
423+ {
275 ERROR("ProcessControl Impl create failed!");424 ERROR("ProcessControl Impl create failed!");
276 return {};425 return {};
277 };426 };
@@ -280,13 +429,14 @@ ExecuteProcessStat ProcessControl::GetExecuteStat() const
280 429 
281bool ProcessControl::VerifyProcess(const ProcessCollection& chipRelatedProcess) const430bool ProcessControl::VerifyProcess(const ProcessCollection& chipRelatedProcess) const
282{431{
283- if (!impl_) {432+ if (!impl_)
433+ {
284 ERROR("ProcessControl Impl create failed!");434 ERROR("ProcessControl Impl create failed!");
285 return false;435 return false;
286 };436 };
287 return impl_->VerifyProcess(chipRelatedProcess);437 return impl_->VerifyProcess(chipRelatedProcess);
288}438}
289 439 
290-}440+} // namespace Infra
291 441 
292-}442+} // namespace Analysis
@@ -0,0 +1,243 @@
1+/* -------------------------------------------------------------------------
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This file is part of the MindStudio project.
4+ * -------------------------------------------------------------------------*/
5+ 
6+#include "analysis/csrc/infrastructure/process/include/topo_graph.h"
7+ 
8+#include <algorithm>
9+#include <memory>
10+#include <new>
11+ 
12+#include "analysis/csrc/infrastructure/dfx/error_code.h"
13+#include "analysis/csrc/infrastructure/process/include/process.h"
14+#include "analysis/csrc/infrastructure/resource/chip_id.h"
15+ 
16+namespace Analysis
17+{
18+namespace Application
19+{
20+namespace
21+{
22+template <TopoNodeStage Stage, size_t Index>
23+struct TopoNodeTag
24+{
25+};
26+ 
27+template <TopoNodeStage Stage, size_t Index>
28+struct TopoNodeTypeGetter
29+{
30+ static std::type_index Get(size_t index)
31+ {
32+ return index == Index ? std::type_index(typeid(TopoNodeTag<Stage, Index>))
33+ : TopoNodeTypeGetter<Stage, Index - 1>::Get(index);
34+ }
35+};
36+ 
37+template <TopoNodeStage Stage>
38+struct TopoNodeTypeGetter<Stage, 0>
39+{
40+ static std::type_index Get(size_t) { return std::type_index(typeid(TopoNodeTag<Stage, 0>)); }
41+};
42+ 
43+TopoNodeCollection& Definitions()
44+{
45+ static TopoNodeCollection definitions;
46+ return definitions;
47+}
48+} // namespace
49+ 
50+bool TopoNodeRegistry::Register(TopoNodeDefinition definition)
51+{
52+ if (definition.id.name.empty() || definition.creatorFactory == nullptr)
53+ {
54+ ERROR("Invalid topology node registration.");
55+ return false;
56+ }
57+ if (definition.chipIds.empty())
58+ {
59+ definition.chipIds = {CHIP_ID_ALL};
60+ }
61+ return Definitions().emplace(definition.id, std::move(definition)).second;
62+}
63+ 
64+const TopoNodeCollection& TopoNodeRegistry::GetDefinitions() { return Definitions(); }
65+ 
66+TopoNodeCollection& TopoNodeRegistry::MutableDefinitions() { return Definitions(); }
67+ 
68+TopoNodeSequenceRegister::TopoNodeSequenceRegister(TopoNodeId id, std::type_index runtimeType, bool mandatory,
69+ std::vector<TopoNodeId> dependencies,
70+ TopoNodeCreatorFactory creatorFactory,
71+ TopoDependencyResolver dependencyResolver)
72+{
73+ TopoNodeDefinition definition;
74+ definition.id = std::move(id);
75+ definition.runtimeType = runtimeType;
76+ definition.mandatory = mandatory;
77+ definition.processDependencies = std::move(dependencies);
78+ definition.creatorFactory = std::move(creatorFactory);
79+ definition.dependencyResolver = std::move(dependencyResolver);
80+ if (!TopoNodeRegistry::Register(std::move(definition)))
81+ {
82+ ERROR("Register topology sequence failed.");
83+ }
84+}
85+ 
86+TopoNodeDataRegister::TopoNodeDataRegister(TopoNodeId id, std::vector<std::type_index> inputDataTypes)
87+{
88+ const auto* definition = TopoNodeRegistry::Find(id);
89+ if (definition == nullptr)
90+ {
91+ ERROR("Register topology data before topology sequence.");
92+ return;
93+ }
94+ TopoNodeRegistry::MutableDefinitions().at(definition->id).inputDataTypes = std::move(inputDataTypes);
95+}
96+ 
97+const TopoNodeDefinition* TopoNodeRegistry::Find(const TopoNodeId& id)
98+{
99+ const auto iter = Definitions().find(id);
100+ return iter == Definitions().end() ? nullptr : &iter->second;
101+}
102+ 
103+const TopoNodeDefinition* TopoNodeRegistry::FindProcessorByName(const std::string& name)
104+{
105+ return Find({TopoNodeStage::DATA_PROCESSING, name});
106+}
107+ 
108+const TopoNodeDefinition* TopoNodeRegistry::FindProcessorByRuntimeType(std::type_index runtimeType)
109+{
110+ for (const auto& item : Definitions())
111+ {
112+ if (item.second.id.stage == TopoNodeStage::DATA_PROCESSING && item.second.runtimeType == runtimeType)
113+ {
114+ return &item.second;
115+ }
116+ }
117+ return nullptr;
118+}
119+ 
120+bool TopoGraphBuilder::Build(const TopoBuildContext& context, const std::vector<TopoNodeId>& roots,
121+ Infra::ProcessCollection& processes)
122+{
123+ if (roots.empty())
124+ {
125+ ERROR("Topology roots are empty.");
126+ return false;
127+ }
128+ context_ = &context;
129+ roots_ = &roots;
130+ processes_ = &processes;
131+ nodeKeys_.clear();
132+ nextSyntheticIndex_.clear();
133+ visiting_.clear();
134+ processes.clear();
135+ for (const auto& root : roots)
136+ {
137+ std::type_index key(typeid(void));
138+ if (!AddNode(root, key))
139+ {
140+ processes.clear();
141+ return false;
142+ }
143+ }
144+ return true;
145+}
146+ 
147+bool TopoGraphBuilder::ResolveDependencies(const TopoNodeDefinition& definition,
148+ std::vector<std::type_index>& dependencies)
149+{
150+ std::vector<TopoNodeId> ids = definition.processDependencies;
151+ if (definition.dependencyResolver != nullptr)
152+ {
153+ const auto dynamicDependencies = definition.dependencyResolver(*context_, *roots_);
154+ ids.insert(ids.end(), dynamicDependencies.begin(), dynamicDependencies.end());
155+ }
156+ for (const auto& id : ids)
157+ {
158+ std::type_index key(typeid(void));
159+ if (!AddNode(id, key))
160+ {
161+ return false;
162+ }
163+ if (std::find(dependencies.begin(), dependencies.end(), key) == dependencies.end())
164+ {
165+ dependencies.emplace_back(key);
166+ }
167+ }
168+ return true;
169+}
170+ 
171+bool TopoGraphBuilder::AddNode(const TopoNodeId& id, std::type_index& key)
172+{
173+ const auto keyIter = nodeKeys_.find(id);
174+ if (keyIter != nodeKeys_.end())
175+ {
176+ key = keyIter->second;
177+ return true;
178+ }
179+ if (visiting_[id])
180+ {
181+ ERROR("Topology contains a cycle at %.", id.name);
182+ return false;
183+ }
184+ const auto* definition = TopoNodeRegistry::Find(id);
185+ if (definition == nullptr)
186+ {
187+ ERROR("Topology contains an unregistered node %.", id.name);
188+ return false;
189+ }
190+ visiting_[id] = true;
Mrtutu
MrtutuMrtutu8月10日

严重程度: 提示

问题: AddNode 在行 198 设置 visiting_[id] = true 后,若行 200 的 ResolveDependencies 失败,行 202 直接 return false 而未清理 visiting_[id],导致该标记残留为 true

原因: 当前 Build 在首个失败后即 processes.clear() 并整体返回 false,残留的 visiting_ 标记不会被后续读取,因此无实际影响。但环检测状态在失败路径上不一致,若将来 Build 被改造为容忍部分失败或重试,残留的 true 标记会被误判为环,产生难以定位的假阳性。建议在失败路径统一清理以保持状态机自洽。

怎么改: 用 RAII 守卫或确保所有 early-return 前清理 visiting_

visiting_[id] = true;
std::vector<std::type_index> dependencies;
if (!ResolveDependencies(*definition, dependencies))
{
    visiting_.erase(id);
    return false;
}

或者用 scope guard 统一管理 visiting_ 的进入与退出。

likedislike
Wangang Yu
Wangang Yu
8月11日 评论:
191+ std::vector<std::type_index> dependencies;
192+ if (!ResolveDependencies(*definition, dependencies))
193+ {
194+ return false;
195+ }
196+ key = definition->id.stage == TopoNodeStage::DATA_PROCESSING ? definition->runtimeType
197+ : AllocateSyntheticKey(definition->id.stage);
198+ if (key == std::type_index(typeid(void)))
199+ {
200+ ERROR("Failed to allocate topology key for %.", definition->id.name);
201+ return false;
202+ }
203+ Infra::RegProcessInfo processInfo;
204+ processInfo.creator = definition->creatorFactory(*context_);
205+ processInfo.processDependence = std::move(dependencies);
206+ processInfo.paramTypes = definition->inputDataTypes;
207+ processInfo.chipIds = definition->chipIds;
208+ processInfo.processName = definition->id.name;
209+ processInfo.mandatory = definition->mandatory;
210+ if (processInfo.creator == nullptr || !processes_->emplace(key, std::move(processInfo)).second)
211+ {
212+ ERROR("Failed to append topology node %.", definition->id.name);
213+ return false;
214+ }
215+ nodeKeys_.emplace(id, key);
216+ visiting_.erase(id);
217+ return true;
218+}
219+ 
220+std::type_index TopoGraphBuilder::AllocateSyntheticKey(TopoNodeStage stage)
221+{
222+ const size_t index = nextSyntheticIndex_[stage]++;
223+ if (index >= MAX_TOPO_NODE_COUNT)
224+ {
225+ ERROR("Too many topology nodes in stage %.", static_cast<uint8_t>(stage));
226+ return std::type_index(typeid(void));
227+ }
228+ switch (stage)
229+ {
230+ case TopoNodeStage::SUMMARY_GENERATION:
231+ return TopoNodeTypeGetter<TopoNodeStage::SUMMARY_GENERATION, MAX_TOPO_NODE_COUNT - 1>::Get(index);
232+ case TopoNodeStage::DATABASE_PERSISTENCE:
233+ return TopoNodeTypeGetter<TopoNodeStage::DATABASE_PERSISTENCE, MAX_TOPO_NODE_COUNT - 1>::Get(index);
234+ case TopoNodeStage::TIMELINE_EXPORT:
235+ return TopoNodeTypeGetter<TopoNodeStage::TIMELINE_EXPORT, MAX_TOPO_NODE_COUNT - 1>::Get(index);
236+ case TopoNodeStage::FLOW_CONTROL:
237+ return TopoNodeTypeGetter<TopoNodeStage::FLOW_CONTROL, MAX_TOPO_NODE_COUNT - 1>::Get(index);
238+ default:
239+ return std::type_index(typeid(void));
240+ }
241+}
242+} // namespace Application
243+} // namespace Analysis
@@ -4,6 +4,7 @@ aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dump_tools/csv_tool
4aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dump_tools/json_tool SOURCES)4aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dump_tools/json_tool SOURCES)
5aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/utils SOURCES)5aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/utils SOURCES)
6aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dfx SOURCES)6aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/dfx SOURCES)
7+aux_source_directory(${TOP_DIR}/analysis/csrc/infrastructure/process SOURCES)
7aux_source_directory(${TOP_DIR}/analysis/csrc/domain/services/environment SOURCES)8aux_source_directory(${TOP_DIR}/analysis/csrc/domain/services/environment SOURCES)
8aux_source_directory(${TOP_DIR}/analysis/csrc/domain/entities/json_trace SOURCES)9aux_source_directory(${TOP_DIR}/analysis/csrc/domain/entities/json_trace SOURCES)
9aux_source_directory(${TOP_DIR}/analysis/csrc/domain/data_process SOURCES)10aux_source_directory(${TOP_DIR}/analysis/csrc/domain/data_process SOURCES)
@@ -29,4 +30,4 @@ target_link_libraries(export_assemble_utest PRIVATE
29 -lsqlite330 -lsqlite3
30)31)
31 32 
32-run_test(export_assemble_utest)33+run_test(export_assemble_utest)