From 0caf243da88eb25f0ad3aad937b2fab9501a367d Mon Sep 17 00:00:00 2001 From: sakura_pc Date: Mon, 12 Jun 2023 17:27:22 +0800 Subject: [PATCH] add libmeminfo, provide memory information query interface Signed-off-by: sakura_pc Signed-off-by: sakura_pc --- bundle.json | 12 ++ libmeminfo/BUILD.gn | 31 +++++ libmeminfo/include/meminfo.h | 34 +++++ libmeminfo/src/meminfo.cpp | 143 ++++++++++++++++++++++ libmeminfo/test/BUILD.gn | 30 +++++ libmeminfo/test/unittest/meminfo_test.cpp | 86 +++++++++++++ 6 files changed, 336 insertions(+) create mode 100644 libmeminfo/BUILD.gn create mode 100644 libmeminfo/include/meminfo.h create mode 100644 libmeminfo/src/meminfo.cpp create mode 100644 libmeminfo/test/BUILD.gn create mode 100644 libmeminfo/test/unittest/meminfo_test.cpp diff --git a/bundle.json b/bundle.json index 5a0e7e4..0de7244 100644 --- a/bundle.json +++ b/bundle.json @@ -19,6 +19,7 @@ "deps": { "components": [ "c_utils", + "drivers_interface_memorytracker", "hiviewdfx_hilog_native" ], "third_party": [] @@ -26,6 +27,7 @@ "build": { "sub_component": [ "//commonlibrary/memory_utils/libdmabufheap:libdmabufheap", + "//commonlibrary/memory_utils/libmeminfo:libmeminfo", "//commonlibrary/memory_utils/libpurgeablemem:libpurgeablemem", "//commonlibrary/memory_utils/libpurgeablemem:purgeable_memory_ndk", "//commonlibrary/memory_utils/purgeable_builder:pixelmap_builder" @@ -40,6 +42,15 @@ "header_base": "//commonlibrary/memory_utils/libdmabufheap/include" } }, + { + "name": "//commonlibrary/memory_utils/libmeminfo:libmeminfo", + "header": { + "header_files": [ + "meminfo.h" + ], + "header_base": "//commonlibrary/memory_utils/libmeminfo/include" + } + }, { "name": "//commonlibrary/memory_utils/libpurgeablemem:libpurgeablemem", "header": { @@ -67,6 +78,7 @@ ], "test": [ "//commonlibrary/memory_utils/libdmabufheap/test:unittest", + "//commonlibrary/memory_utils/libmeminfo/test:libmeminfo_test", "//commonlibrary/memory_utils/libpurgeablemem/test:libpurgeablemem_test" ] } diff --git a/libmeminfo/BUILD.gn b/libmeminfo/BUILD.gn new file mode 100644 index 0000000..3597694 --- /dev/null +++ b/libmeminfo/BUILD.gn @@ -0,0 +1,31 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") + +config("libmeminfo_config") { + include_dirs = [ "include" ] +} + +ohos_shared_library("libmeminfo") { + sources = [ "src/meminfo.cpp" ] + include_dirs = [ "include" ] + external_deps = [ + "c_utils:utils", + "drivers_interface_memorytracker:libmemorytracker_proxy_1.0", + "hiviewdfx_hilog_native:libhilog", + ] + public_configs = [ ":libmeminfo_config" ] + subsystem_name = "commonlibrary" + part_name = "memory_utils" +} diff --git a/libmeminfo/include/meminfo.h b/libmeminfo/include/meminfo.h new file mode 100644 index 0000000..34aeb38 --- /dev/null +++ b/libmeminfo/include/meminfo.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_MEM_INFO_H +#define LIB_MEM_INFO_H + +#include +#include + +namespace OHOS { +namespace MemInfo { +// get rss refer to memmgr +uint64_t GetRssByPid(const int pid); + +// get pss from smaps_rollup, include graphics memory +uint64_t GetPssByPid(const int pid); + +// get graphics memory from hdi +bool GetGraphicsMemory(const int pid, uint64_t &gl, uint64_t &graph); +} /* namespace MemInfo */ +} /* namespace OHOS */ +#endif /* LIB_MEM_INFO_H */ \ No newline at end of file diff --git a/libmeminfo/src/meminfo.cpp b/libmeminfo/src/meminfo.cpp new file mode 100644 index 0000000..9bdd398 --- /dev/null +++ b/libmeminfo/src/meminfo.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "file_ex.h" // LoadStringFromFile +#include "hilog/log.h" +#include "meminfo.h" + +namespace OHOS { +namespace MemInfo { +using namespace OHOS::HDI::Memorytracker::V1_0; +constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001799, "MemInfo" }; +constexpr int PAGE_TO_KB = 4; +constexpr int BYTE_PER_KB = 1024; + +// get rss refer to memmgr +uint64_t GetRssByPid(const int pid) +{ + uint64_t size = 0; + std::string stat; + std::string statm; + std::string statPid; + std::string vss; + std::string rss; + std::string name; + std::string status; + std::string statPath = "/proc/" + std::to_string(pid) + "/stat"; + // format like: + // 1 (init) S 0 0 0 0 -1 4210944 1 ... + if (!OHOS::LoadStringFromFile(statPath, stat)) { + HiviewDFX::HiLog::Error(LABEL, "stat file error!"); + return size; + } + std::istringstream isStat(stat); + isStat >> statPid >> name >> status; + + if (statPid != std::to_string(pid)) { + HiviewDFX::HiLog::Error(LABEL, "pid error!"); + return size; + } + + std::string statmPath = "/proc/" + std::to_string(pid) + "/statm"; + // format like: + // 640 472 369 38 0 115 0 + if (!OHOS::LoadStringFromFile(statmPath, statm)) { + HiviewDFX::HiLog::Error(LABEL, "statm file error!"); + return size; + } + std::istringstream isStatm(statm); + isStatm >> vss >> rss; // pages + + size = atoi(rss.c_str()) * PAGE_TO_KB; + return size; +} + +// get pss from smaps_rollup, include graphics memory +uint64_t GetPssByPid(const int pid) +{ + uint64_t size = 0; + std::string filename = "/proc/" + std::to_string(pid) + "/smaps_rollup"; + std::ifstream in(filename); + if (!in) { + HiviewDFX::HiLog::Error(LABEL, "File %{public}s not found.\n", filename.c_str()); + return size; + } + + std::string content; + while (getline(in, content)) { + std::string::size_type typePos = content.find(":"); + if (typePos != content.npos) { + std::string type = content.substr(0, typePos); + if (type == "Pss") { + std::string valueStr = content.substr(typePos + 1); + const int base = 10; + size = strtoull(valueStr.c_str(), nullptr, base); + break; + } + } + } + in.close(); + + uint64_t gl = 0; + uint64_t graph = 0; + bool ret = GetGraphicsMemory(pid, gl, graph); + if (ret) { + size += gl; + size += graph; + } + return size; +} + +// get graphics memory from hdi +bool GetGraphicsMemory(const int pid, uint64_t &gl, uint64_t &graph) +{ + bool ret = false; + sptr memtrack = IMemoryTrackerInterface::Get(true); + if (memtrack == nullptr) { + HiviewDFX::HiLog::Error(LABEL, "memtrack service is null"); + return ret; + } + const std::vector> MEMORY_TRACKER_TYPES = { + {MEMORY_TRACKER_TYPE_GL, "GL"}, {MEMORY_TRACKER_TYPE_GRAPH, "Graph"}, + {MEMORY_TRACKER_TYPE_OTHER, "Other"} + }; + + for (const auto &memTrackerType : MEMORY_TRACKER_TYPES) { + std::vector records; + if (memtrack->GetDevMem(pid, memTrackerType.first, records) == HDF_SUCCESS) { + uint64_t value = 0; + for (const auto &record : records) { + if ((static_cast(record.flags) & FLAG_UNMAPPED) == FLAG_UNMAPPED) { + value = static_cast(record.size / BYTE_PER_KB); + break; + } + } + if (memTrackerType.first == MEMORY_TRACKER_TYPE_GL) { + gl = value; + ret = true; + } else if (memTrackerType.first == MEMORY_TRACKER_TYPE_GRAPH) { + graph = value; + ret = true; + } + } + } + return ret; +} +} /* namespace MemInfo */ +} /* namespace OHOS */ diff --git a/libmeminfo/test/BUILD.gn b/libmeminfo/test/BUILD.gn new file mode 100644 index 0000000..f83b2cb --- /dev/null +++ b/libmeminfo/test/BUILD.gn @@ -0,0 +1,30 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/test.gni") + +module_output_path = "libmeminfo/" + +ohos_unittest("MemInfoTest") { + module_out_path = module_output_path + sources = [ "unittest/meminfo_test.cpp" ] + external_deps = [ + "c_utils:utils", + "memory_utils:libmeminfo", + ] +} + +group("libmeminfo_test") { + testonly = true + deps = [ ":MemInfoTest" ] +} diff --git a/libmeminfo/test/unittest/meminfo_test.cpp b/libmeminfo/test/unittest/meminfo_test.cpp new file mode 100644 index 0000000..c6d3df5 --- /dev/null +++ b/libmeminfo/test/unittest/meminfo_test.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "gtest/gtest.h" +#include "meminfo.h" + +namespace OHOS { +namespace MemInfo { +using namespace testing; +using namespace testing::ext; + +class MemInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void MemInfoTest::SetUpTestCase() +{ +} + +void MemInfoTest::TearDownTestCase() +{ +} + +void MemInfoTest::SetUp() +{ +} + +void MemInfoTest::TearDown() +{ +} + +HWTEST_F(MemInfoTest, GetRssByPid_Test_001, TestSize.Level1) +{ + int pid = 1; + uint64_t size = 0; + size = GetRssByPid(pid); + std::cout << "size = " << size << std::endl; + ASSERT_EQ(size > 0, true); +} + +HWTEST_F(MemInfoTest, GetRssByPid_Test_002, TestSize.Level1) +{ + int pid = -1; + uint64_t size = 0; + size = GetRssByPid(pid); + ASSERT_EQ(size == 0, true); +} + +HWTEST_F(MemInfoTest, GetPssByPid_Test_001, TestSize.Level1) +{ + int pid = 1; + uint64_t size = 0; + size = GetPssByPid(pid); + std::cout << "size = " << size << std::endl; + system("hidumper --mem 1"); + system("cat /proc/1/smaps_rollup"); + ASSERT_EQ(size > 0, true); +} + +HWTEST_F(MemInfoTest, GetPssByPid_Test_002, TestSize.Level1) +{ + int pid = -1; + uint64_t size = 0; + size = GetPssByPid(pid); + ASSERT_EQ(size == 0, true); +} +} +} -- Gitee