1 /*
2  * Copyright (c) 2024 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 "concurrent_helper.h"
17 #include "tools/log.h"
18 
19 namespace Commonlibrary::Concurrent::Common::Helper {
20 using SystemMemoryLevel = ConcurrentHelper::SystemMemoryLevel;
21 
22 static constexpr double LOW_MEMORY_RATIO = 0.2;
23 static constexpr double MODERATE_MEMORY_RATIO = 0.5;
24 static const char* AVAILABLE_MEM = "MemAvailable:";
25 static const char* MEM_INFO = "/proc/meminfo";
26 static const char* TOTAL_MEM = "MemTotal:";
27 
28 #if defined(OHOS_PLATFORM)
ParseLine(const std::string & line)29 uint64_t ConcurrentHelper::ParseLine(const std::string& line)
30 {
31     std::istringstream iss(line);
32     std::string key;
33     uint64_t value;
34     std::string unit;
35     if (iss >> key >> value >> unit) {
36         return value;
37     }
38     return 0;
39 }
40 
GetSystemMemoryRatio()41 std::optional<double> ConcurrentHelper::GetSystemMemoryRatio()
42 {
43     uint64_t totalMemory = 0;
44     uint64_t availableMemory = 0;
45     std::ifstream meminfo(MEM_INFO);
46     if (!meminfo.is_open()) {
47         HILOG_ERROR("ConcurrentHelper:: Open %{public}s failed", MEM_INFO);
48         return std::nullopt;
49     }
50     std::string line;
51     while (std::getline(meminfo, line)) {
52         if (line.find(TOTAL_MEM) == 0) {
53             totalMemory = ParseLine(line);
54         } else if (line.find(AVAILABLE_MEM) == 0) {
55             availableMemory = ParseLine(line);
56         }
57     }
58     if (totalMemory == 0) {
59         HILOG_ERROR("ConcurrentHelper:: Failed to read the MemTotal.");
60         return std::nullopt;
61     }
62     return static_cast<double>(availableMemory) / static_cast<double>(totalMemory);
63 }
64 
GetMemoryLevel()65 SystemMemoryLevel ConcurrentHelper::GetMemoryLevel()
66 {
67     const auto ratio = GetSystemMemoryRatio();
68     if (!ratio.has_value()) { // error happens when read memory info, just return the MEMORY_LEVEL_LOW
69         return SystemMemoryLevel::MEMORY_LEVEL_LOW;
70     }
71     if (ratio.value() > MODERATE_MEMORY_RATIO) {
72         return SystemMemoryLevel::MEMORY_LEVEL_NORMAL;
73     } else if (ratio.value() > LOW_MEMORY_RATIO) {
74         return SystemMemoryLevel::MEMORY_LEVEL_MODERATE;
75     } else {
76         return SystemMemoryLevel::MEMORY_LEVEL_LOW;
77     }
78 }
79 #endif
80 
IsLowMemory()81 bool ConcurrentHelper::IsLowMemory()
82 {
83 #if defined(OHOS_PLATFORM)
84     return GetMemoryLevel() == SystemMemoryLevel::MEMORY_LEVEL_LOW;
85 #else
86     return false;
87 #endif
88 }
89 
IsModerateMemory()90 bool ConcurrentHelper::IsModerateMemory()
91 {
92 #if defined(OHOS_PLATFORM)
93     return GetMemoryLevel() == SystemMemoryLevel::MEMORY_LEVEL_MODERATE;
94 #else
95     return false;
96 #endif
97 }
98 } // namespace Commonlibrary::Concurrent::TaskPoolModule