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