1 /*
2 * Copyright (c) 2021 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 "base/memory/memory_monitor.h"
17
18 #include <map>
19 #include <mutex>
20 #include <memory>
21
22 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) and !defined(IOS_PLATFORM) and !defined(LINUX_PLATFORM)
23 #include <malloc.h>
24 #endif
25 #include "base/log/dump_log.h"
26
27 namespace OHOS::Ace {
28
PurgeMallocCache()29 void PurgeMallocCache()
30 {
31 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) and !defined(IOS_PLATFORM) and !defined(LINUX_PLATFORM)
32 #if defined(__BIONIC__)
33 mallopt(M_PURGE, 0);
34 #endif
35 #endif
36 }
37
38 bool MemoryMonitor::isEnable_ = SystemProperties::GetIsUseMemoryMonitor();
39
40 class MemoryMonitorImpl : public MemoryMonitor {
41 public:
Add(void * ptr)42 void Add(void* ptr) final
43 {
44 std::lock_guard<std::mutex> lock(mutex_);
45 auto result = memoryMap_.emplace(ptr, MemInfo());
46 if (!result.second) {
47 return;
48 }
49
50 count_++;
51 }
52
Remove(void * ptr)53 void Remove(void* ptr) final
54 {
55 std::lock_guard<std::mutex> lock(mutex_);
56 auto it = memoryMap_.find(ptr);
57 if (it == memoryMap_.end()) {
58 return;
59 }
60 count_--;
61
62 if (it->second.size > 0) {
63 total_ -= it->second.size;
64 auto& info = typeMap_[it->second.typeName];
65 info.count--;
66 info.total -= it->second.size;
67 }
68 memoryMap_.erase(it);
69 }
70
Update(void * ptr,size_t size,const std::string & typeName)71 void Update(void* ptr, size_t size, const std::string& typeName) final
72 {
73 std::lock_guard<std::mutex> lock(mutex_);
74 auto it = memoryMap_.find(ptr);
75 if (it == memoryMap_.end()) {
76 return;
77 }
78
79 it->second.size = size;
80 it->second.typeName = typeName;
81
82 total_ += size;
83 auto& info = typeMap_[typeName];
84 info.count++;
85 info.total += size;
86 }
87
Dump() const88 void Dump() const final
89 {
90 if (!IsEnable()) {
91 DumpLog::GetInstance().Print(0, "Set `persist.ace.memorymonitor.enabled = 1` to enable this feature");
92 return;
93 }
94 std::lock_guard<std::mutex> lock(mutex_);
95 std::string out = "total = " + std::to_string(total_) + ", count = " + std::to_string(count_);
96 DumpLog::GetInstance().Print(0, out);
97 for (auto&& [typeName, info] : typeMap_) {
98 if (info.total == 0) {
99 continue;
100 }
101 out = typeName + ": total = " + std::to_string(info.total) + ", count = " + std::to_string(info.count);
102 DumpLog::GetInstance().Print(1, out);
103 }
104 }
105
106 private:
107 struct MemInfo {
108 size_t size = 0;
109 std::string typeName = "Unknown";
110 };
111
112 struct TypeInfo {
113 size_t count = 0;
114 size_t total = 0;
115 };
116
117 std::map<void*, MemInfo> memoryMap_;
118 std::map<std::string, TypeInfo> typeMap_;
119 size_t total_ = 0;
120 size_t count_ = 0;
121
122 mutable std::mutex mutex_;
123 };
124
GetInstance()125 MemoryMonitor& MemoryMonitor::GetInstance()
126 {
127 static MemoryMonitorImpl instance;
128 return instance;
129 }
130
131 } // namespace OHOS::Ace
132