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