Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "aicpusd_proc_mem_statistic.h"
12 :
13 : #include <string>
14 : #include <fstream>
15 : #include "aicpusd_util.h"
16 :
17 : namespace AicpuSchedule {
18 : namespace {
19 : constexpr const char *VM_RSS_NAME = "VmRSS:";
20 : constexpr const char *VM_HWM_NAME = "VmHWM:";
21 : constexpr const char *XSMEME_NAME = "summary:";
22 : const std::string SVM_STAT_NAME = "peak_page_cnt=";
23 : constexpr const uint64_t DEFAULT_PAGE_SIZE = 4 * 1024UL;
24 : constexpr const uint64_t H_PAGE_SIZE = 2 * 1024 * 1024UL;
25 : constexpr const uint64_t BYTE_TO_KBYTE = 1024UL;
26 : constexpr const int32_t SVM_VALUE_CNT = 2;
27 : constexpr const int32_t XSMEM_VALUE_CNT = 2;
28 : }
29 12 : AicpuSdProcMemStatistic::AicpuSdProcMemStatistic() : deployCtx_(DeployContext::HOST), curPid_(0)
30 : {
31 12 : }
32 :
33 12 : AicpuSdProcMemStatistic::~AicpuSdProcMemStatistic()
34 : {
35 12 : }
36 :
37 5 : void AicpuSdProcMemStatistic::StatisticProcSvmMemInfo()
38 : {
39 5 : if (deployCtx_ != DeployContext::DEVICE) {
40 4 : return;
41 : }
42 4 : uint64_t svmValue = 0UL;
43 4 : if (!GetSvmInfoFromFile(svmValue)) {
44 3 : return;
45 : }
46 1 : if (svmValue > svmMem_.memHwm) {
47 1 : svmMem_.memHwm = svmValue;
48 : }
49 1 : svmMem_.memTotal += svmValue;
50 1 : svmMem_.statCnt++;
51 : }
52 :
53 4 : bool AicpuSdProcMemStatistic::GetSvmInfoFromFile(uint64_t &svmValue)
54 : {
55 4 : std::ifstream inFile(svmMemCfgFile_);
56 4 : if (!inFile) {
57 1 : aicpusd_info("Opening svmMem file was not successful, pid=%d, errno=%d, reason:%s", static_cast<int32_t>(curPid_),
58 : errno, strerror(errno));
59 1 : return false;
60 : }
61 6 : const ScopeGuard fileGuard([&inFile] () { inFile.close(); });
62 3 : std::string summaryStr;
63 3 : std::string inputLine;
64 4 : while (getline(inFile, inputLine)) {
65 3 : const size_t pos = inputLine.find(SVM_STAT_NAME);
66 3 : if (pos != std::string::npos) {
67 2 : summaryStr = inputLine.substr(pos);
68 2 : break;
69 : }
70 : }
71 :
72 3 : if (summaryStr.empty()) {
73 1 : aicpusd_warn("summaryStr is empty");
74 1 : return false;
75 : }
76 :
77 2 : uint64_t peakPgCnt = 0;
78 2 : uint64_t peakHPgCnt = 0;
79 2 : const int32_t ret = sscanf_s(summaryStr.c_str(), "peak_page_cnt=%llu; peak_hpage_cnt=%llu",
80 : &peakPgCnt, &peakHPgCnt);
81 2 : if (ret < SVM_VALUE_CNT) {
82 1 : aicpusd_warn("read summaryStr:%s failed, ret:%d, peakHPgCnt:%llu, peakHPgCnt:%llu", summaryStr.c_str(), ret,
83 : peakPgCnt, peakHPgCnt);
84 1 : return false;
85 : }
86 :
87 1 : aicpusd_info("peakPgCnt:%lu, peakHPgCnt:%lu summary:%s.", peakPgCnt, peakHPgCnt, summaryStr.c_str());
88 1 : if ((peakPgCnt == 0) && (peakHPgCnt == 0UL)) {
89 0 : return false;
90 : }
91 1 : svmValue = peakPgCnt * DEFAULT_PAGE_SIZE + peakHPgCnt + H_PAGE_SIZE;
92 1 : return true;
93 4 : }
94 :
95 4 : bool AicpuSdProcMemStatistic::GetXsMemInfoFromFile(uint64_t &xsMemValue)
96 : {
97 4 : std::ifstream inFile(xsMemCfgFile_);
98 4 : if (!inFile) {
99 1 : aicpusd_info("Opening xsMem file was not successful, pid=%d, errno=%d, reason:%s", static_cast<int32_t>(curPid_),
100 : errno, strerror(errno));
101 1 : return false;
102 : }
103 6 : const ScopeGuard fileGuard([&inFile] () { inFile.close(); });
104 3 : std::string summaryStr;
105 3 : std::string inputLine;
106 4 : while (getline(inFile, inputLine)) {
107 3 : if (inputLine.compare(0, strlen(XSMEME_NAME), XSMEME_NAME) == 0) {
108 2 : summaryStr = std::move(inputLine);
109 2 : break;
110 : }
111 : }
112 :
113 3 : if (summaryStr.empty()) {
114 1 : aicpusd_warn("summaryStr is empty");
115 1 : return false;
116 : }
117 :
118 2 : uint64_t allocSize = 0;
119 2 : uint64_t realSize = 0;
120 2 : const int32_t ret = sscanf_s(summaryStr.c_str(), "summary: %llu %llu", &allocSize, &realSize);
121 2 : if (ret < XSMEM_VALUE_CNT) {
122 1 : aicpusd_warn("read summaryStr:%s failed, ret:%d, allocsize:%llu, real size:%llu", summaryStr.c_str(), ret,
123 : allocSize, realSize);
124 1 : return false;
125 : }
126 :
127 1 : aicpusd_info("allocsize:%lu B, real size:%lu B, %s.", allocSize, realSize, summaryStr.c_str());
128 1 : if (realSize == 0) {
129 0 : return false;
130 : }
131 1 : xsMemValue = realSize;
132 1 : return true;
133 4 : }
134 :
135 4 : void AicpuSdProcMemStatistic::StatisticProcXsMemInfo()
136 : {
137 4 : uint64_t xsMemValue = 0UL;
138 4 : if (!GetXsMemInfoFromFile(xsMemValue)) {
139 3 : return;
140 : }
141 1 : if (xsMemValue > xsMem_.memHwm) {
142 1 : xsMem_.memHwm = xsMemValue;
143 : }
144 1 : xsMem_.memTotal += xsMemValue;
145 1 : xsMem_.statCnt++;
146 : }
147 :
148 4 : bool AicpuSdProcMemStatistic::GetOsMemInfoFromFile(uint64_t &rssValue, uint64_t &hwmValue)
149 : {
150 4 : std::ifstream ifFile(rssMemCfgFile_);
151 4 : if (!ifFile) {
152 1 : aicpusd_info("Opening rss file was not successful, pid=%d, errno=%d, reason:%s", static_cast<int32_t>(curPid_),
153 : errno, strerror(errno));
154 1 : return false;
155 : }
156 6 : const ScopeGuard fileGuard([&ifFile] () { ifFile.close(); });
157 3 : std::string vmRssStr;
158 3 : std::string vmHwmStr;
159 3 : std::string inputLine;
160 26 : while (getline(ifFile, inputLine)) {
161 25 : if (inputLine.compare(0, strlen(VM_RSS_NAME), VM_RSS_NAME) == 0) {
162 2 : vmRssStr = std::move(inputLine);
163 23 : } else if (inputLine.compare(0, strlen(VM_HWM_NAME), VM_HWM_NAME) == 0) {
164 2 : vmHwmStr = std::move(inputLine);
165 : } else {
166 21 : continue;
167 : }
168 4 : if ((!vmRssStr.empty()) && (!vmHwmStr.empty())) {
169 2 : break;
170 : }
171 : }
172 :
173 3 : if ((vmRssStr.empty()) || (vmHwmStr.empty())) {
174 1 : aicpusd_run_info("cannot get vmrss or vmhwm");
175 1 : return false;
176 : }
177 :
178 2 : if (!AicpuUtil::TransStrToull(vmRssStr.substr(strlen(VM_RSS_NAME)), rssValue)) {
179 1 : aicpusd_warn("get vmRssError:%s failed", vmRssStr.c_str());
180 1 : return false;
181 : }
182 :
183 1 : if (!AicpuUtil::TransStrToull(vmHwmStr.substr(strlen(VM_HWM_NAME)), hwmValue)) {
184 0 : aicpusd_warn("get vmHwmError:%s failed", vmHwmStr.c_str());
185 0 : return false;
186 : }
187 1 : aicpusd_info("vmRss:%llu KB, vmHwm:%llu KB.", rssValue, hwmValue);
188 1 : return true;
189 4 : }
190 :
191 3 : void AicpuSdProcMemStatistic::StatisticProcOsMemInfo()
192 : {
193 3 : uint64_t rssValue = 0UL;
194 3 : uint64_t hwmValue = 0UL;
195 3 : if (!GetOsMemInfoFromFile(rssValue, hwmValue)) {
196 2 : aicpusd_warn("get os meminfo failed");
197 2 : return;
198 : }
199 1 : rssMem_.memHwm = hwmValue;
200 1 : rssMem_.memTotal += rssValue;
201 1 : rssMem_.statCnt++;
202 : }
203 :
204 1 : void AicpuSdProcMemStatistic::StatisticProcMemInfo()
205 : {
206 1 : StatisticProcOsMemInfo();
207 1 : StatisticProcXsMemInfo();
208 1 : StatisticProcSvmMemInfo();
209 1 : }
210 :
211 1 : bool AicpuSdProcMemStatistic::InitProcMemStatistic()
212 : {
213 1 : auto ret = memset_s(&rssMem_, sizeof(rssMem_), 0x00, sizeof(rssMem_));
214 1 : if (ret != EOK) {
215 0 : aicpusd_err("memset rssMem failed ret:%d", ret);
216 0 : return false;
217 : }
218 :
219 1 : ret = memset_s(&svmMem_, sizeof(svmMem_), 0x00, sizeof(svmMem_));
220 1 : if (ret != EOK) {
221 0 : aicpusd_err("memset svmMem_ failed ret:%d", ret);
222 0 : return false;
223 : }
224 :
225 1 : ret = memset_s(&xsMem_, sizeof(xsMem_), 0x00, sizeof(xsMem_));
226 1 : if (ret != EOK) {
227 0 : aicpusd_err("memset xsMem_ failed ret:%d", ret);
228 0 : return false;
229 : }
230 1 : (void)GetAicpuDeployContext(deployCtx_);
231 1 : curPid_ = getpid();
232 1 : if (curPid_ < 0) {
233 0 : aicpusd_err("get pid error:%d", curPid_);
234 0 : return false;
235 : }
236 1 : rssMemCfgFile_ = "/proc/" + std::to_string(curPid_) + "/status";
237 1 : xsMemCfgFile_ = "/proc/xsmem/task/" + std::to_string(curPid_) + "/summary";
238 1 : svmMemCfgFile_ = "/proc/svm/task/" + std::to_string(curPid_) + "/summary";
239 1 : return true;
240 : }
241 :
242 5 : void AicpuSdProcMemStatistic::PrintOutProcMemInfo(const uint32_t hostPid)
243 : {
244 5 : uint64_t rssavg = 0UL;
245 5 : if (rssMem_.statCnt > 0) {
246 2 : rssavg = rssMem_.memTotal / rssMem_.statCnt;
247 : }
248 5 : aicpusd_info("rssavg:%llu KB, rsstotal:%llu KB, rsscnt:%llu", rssavg, rssMem_.memTotal, rssMem_.statCnt);
249 5 : uint64_t xsmAvg = 0UL;
250 5 : if (xsMem_.statCnt > 0) {
251 1 : xsmAvg = xsMem_.memTotal / xsMem_.statCnt;
252 : }
253 5 : aicpusd_info("xsmAvg:%llu B, xsmtotal:%llu B, xsmcnt:%llu", xsmAvg, xsMem_.memTotal, xsMem_.statCnt);
254 5 : if (deployCtx_ == DeployContext::DEVICE) {
255 3 : uint64_t svmAvg = 0UL;
256 3 : if (svmMem_.statCnt > 0) {
257 1 : svmAvg = svmMem_.memTotal / svmMem_.statCnt;
258 : }
259 3 : aicpusd_info("svmAvg:%llu B, svmtotal:%llu B, svmcnt:%llu", svmAvg, svmMem_.memTotal, svmMem_.statCnt);
260 3 : aicpusd_run_info("proc_metrics:pid=%u, rssavg=%lu B, rsshwm=%llu B, xsmemavg=%llu B, xsmemhwm=%lu B, "
261 : "svmmemavg=%llu B, svmmemhwm=%lu B", hostPid, rssavg * BYTE_TO_KBYTE,
262 : rssMem_.memHwm * BYTE_TO_KBYTE, xsmAvg, xsMem_.memHwm, svmAvg, svmMem_.memHwm);
263 : } else {
264 2 : aicpusd_run_info("proc_metrics:pid=%u, rssavg=%lu B, rsshwm=%llu B, xsmemavg=%llu B, xsmemhwm=%lu B",
265 : hostPid, rssavg * BYTE_TO_KBYTE, rssMem_.memHwm * BYTE_TO_KBYTE, xsmAvg, xsMem_.memHwm);
266 : }
267 5 : }
268 : }
|