1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mem_proc.h"
17 #ifdef SIMULATOR_MEMORY_ANALYSIS
18 #include <cstdio>
19 #include <windows.h>
20 #include <psapi.h>
21 #include "ace_log.h"
22 #include "gfx_utils/file.h"
23 #include "jerryscript-core.h"
24 #include "jerryscript.h"
25 #include "js_fwk_common.h"
26 #include "securec.h"
27 #include "time.h"
28 
29 namespace OHOS {
30 namespace ACELite {
31 constexpr uint8_t MSG_LENGTH = 100;
32 
33 constexpr uint32_t UNIT = 1024;
34 
GetInstance()35 AceMemProc *AceMemProc::GetInstance()
36 {
37     static AceMemProc instance;
38     return &instance;
39 }
40 
ClearUp()41 void AceMemProc::ClearUp()
42 {
43     if (!IsEnabled()) {
44         return;
45     }
46     // backup prev txt, create a new txt
47     struct stat fileStat;
48 
49     int32_t state = stat(MEM_LOG_FILE_PATH, &fileStat);
50     if ((state != 0) || (fileStat.st_size == 0)) {
51         HILOG_ERROR(HILOG_MODULE_ACE, "Back up file error.");
52         return;
53     }
54     // it exists and not empty
55     time_t seconds = time(NULL);
56     char markdata[MSG_LENGTH];
57     if (sprintf_s(markdata, MSG_LENGTH, "%ti.txt", seconds) < 0) {
58         close(state);
59         return;
60     }
61     char *fullPath = RelocateJSSourceFilePath(MEM_BACK_UP_LOG_FILE_PREFIX, markdata);
62     if (fullPath == nullptr) {
63         HILOG_ERROR(HILOG_MODULE_ACE, "Back up file error.");
64     } else {
65         rename(MEM_LOG_FILE_PATH, fullPath);
66         ace_free(fullPath);
67         fullPath = nullptr;
68     }
69     close(state);
70 }
71 
SysMemTracing()72 void AceMemProc::SysMemTracing()
73 {
74     if (!IsEnabled()) {
75         return;
76     }
77     HANDLE handle = GetCurrentProcess();
78     PROCESS_MEMORY_COUNTERS pmc = {0};
79     if (!GetProcessMemoryInfo(handle, reinterpret_cast<PROCESS_MEMORY_COUNTERS *>(&pmc), sizeof(pmc))) {
80         HILOG_ERROR(HILOG_MODULE_ACE, "Get process memory error.");
81         return;
82     }
83 
84     FILE *fp = fopen(MEM_LOG_FILE_PATH, "a+");
85     if (fp == nullptr) {
86         HILOG_ERROR(HILOG_MODULE_ACE, "Get file error.");
87         return;
88     }
89 
90     // physical memory
91     char markdata[MSG_LENGTH];
92     if (sprintf_s(markdata, MSG_LENGTH, "Phy:%d(KB)\n", uint32_t(pmc.WorkingSetSize / UNIT)) < 0) {
93         HILOG_ERROR(HILOG_MODULE_ACE, "Output file error.");
94         fclose(fp);
95         fp = nullptr;
96         return;
97     }
98     fputs(markdata, fp);
99 
100     // virtual memory
101     if (sprintf_s(markdata, MSG_LENGTH, "Vir:%d(KB)\n", uint32_t(pmc.PagefileUsage / UNIT)) < 0) {
102         HILOG_ERROR(HILOG_MODULE_ACE, "Output file error.");
103         fclose(fp);
104         fp = nullptr;
105         return;
106     }
107     fputs(markdata, fp);
108 
109     fflush(fp);
110     fclose(fp);
111     fp = nullptr;
112 }
113 
JerryMemTracing()114 void AceMemProc::JerryMemTracing()
115 {
116     if (!IsEnabled()) {
117         return;
118     }
119     jerry_heap_stats_t stats = {0};
120     if (!jerry_get_memory_stats(&stats)) {
121         HILOG_ERROR(HILOG_MODULE_ACE, "Get jerry heap stats error.");
122         return;
123     }
124 
125     FILE *fp = fopen(MEM_LOG_FILE_PATH, "a+");
126     if (fp == nullptr) {
127         HILOG_ERROR(HILOG_MODULE_ACE, "Get file error");
128         return;
129     }
130 
131     size_t total = stats.size;
132     size_t current = stats.allocated_bytes;
133     size_t peak = stats.peak_allocated_bytes;
134     // jerry total memory
135     char markdata[MSG_LENGTH];
136     if (sprintf_s(markdata, MSG_LENGTH, "jerry heap total:%d(KB)\n", uint32_t(total / UNIT)) < 0) {
137         HILOG_ERROR(HILOG_MODULE_ACE, "Output file error.");
138         fclose(fp);
139         fp = nullptr;
140         return;
141     }
142     fputs(markdata, fp);
143 
144     // jerry current memory
145     if (sprintf_s(markdata, MSG_LENGTH, "jerry heap current:%d(KB)\n", uint32_t(current / UNIT)) < 0) {
146         HILOG_ERROR(HILOG_MODULE_ACE, "Output file error.");
147         fclose(fp);
148         fp = nullptr;
149         return;
150     }
151     fputs(markdata, fp);
152 
153     // jerry peak memory
154     if (sprintf_s(markdata, MSG_LENGTH, "jerry heap peak:%d(KB)\n", uint32_t(peak / UNIT)) < 0) {
155         HILOG_ERROR(HILOG_MODULE_ACE, "Output file error.");
156         fclose(fp);
157         fp = nullptr;
158         return;
159     }
160     fputs(markdata, fp);
161 
162     fflush(fp);
163     fclose(fp);
164     fp = nullptr;
165 }
166 
IsEnabled()167 bool AceMemProc::IsEnabled()
168 {
169     return IsFileExisted(MEM_PROC_ENABLE_FLAG_FILE);
170 }
171 } // namespace ACELite
172 } // namespace OHOS
173 #endif // SIMULATOR_MEMORY_ANALYSIS
174