Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2259fdf7 authored by Sandeep Patil's avatar Sandeep Patil
Browse files

libmeminfo: Add support for counting swap pages



Adds procmeminfo API to get the vector of swap_offsets
if SWAP is enabled on the device.

Bug: 114325007
Bug: 111694435
Test: libmeminfo_test 1
Change-Id: If0b52d042749a5bcb2c87aa2cb1595190d4769b1
Signed-off-by: default avatarSandeep Patil <sspatil@google.com>
parent 5cd79691
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ struct MemUsage {
    uint64_t pss;
    uint64_t uss;

    uint64_t swap;

    uint64_t private_clean;
    uint64_t private_dirty;
    uint64_t shared_clean;
@@ -41,6 +43,7 @@ struct MemUsage {
          rss(0),
          pss(0),
          uss(0),
          swap(0),
          private_clean(0),
          private_dirty(0),
          shared_clean(0),
@@ -49,7 +52,7 @@ struct MemUsage {
    ~MemUsage() = default;

    void clear() {
        vss = rss = pss = uss = 0;
        vss = rss = pss = uss = swap = 0;
        private_clean = private_dirty = shared_clean = shared_dirty = 0;
    }
};
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ class ProcMemInfo final {
    const std::vector<Vma>& Maps();
    const MemUsage& Usage();
    const MemUsage& Wss();
    const std::vector<uint16_t>& SwapOffsets() const;

    bool WssReset();
    ~ProcMemInfo() = default;
@@ -49,6 +50,7 @@ class ProcMemInfo final {

    MemUsage usage_;
    MemUsage wss_;
    std::vector<uint16_t> swap_offsets_;
};

}  // namespace meminfo
+31 −15
Original line number Diff line number Diff line
@@ -28,6 +28,22 @@ namespace meminfo {
class SysMemInfo final {
    // System or Global memory accounting
  public:
    static constexpr const char* kMemTotal = "MemTotal:";
    static constexpr const char* kMemFree = "MemFree:";
    static constexpr const char* kMemBuffers = "Buffers:";
    static constexpr const char* kMemCached = "Cached:";
    static constexpr const char* kMemShmem = "Shmem:";
    static constexpr const char* kMemSlab = "Slab:";
    static constexpr const char* kMemSReclaim = "SReclaimable:";
    static constexpr const char* kMemSUnreclaim = "SUnreclaim:";
    static constexpr const char* kMemSwapTotal = "SwapTotal:";
    static constexpr const char* kMemSwapFree = "SwapFree:";
    static constexpr const char* kMemZram = "Zram:";
    static constexpr const char* kMemMapped = "Mapped:";
    static constexpr const char* kMemVmallocUsed = "VmallocUsed:";
    static constexpr const char* kMemPageTables = "PageTables:";
    static constexpr const char* kMemKernelStack = "KernelStack:";

    static const std::vector<std::string> kDefaultSysMemInfoTags;

    SysMemInfo() = default;
@@ -38,21 +54,21 @@ class SysMemInfo final {
                     const std::string& path = "/proc/meminfo");

    // getters
    uint64_t mem_total_kb() { return mem_in_kb_["MemTotal:"]; }
    uint64_t mem_free_kb() { return mem_in_kb_["MemFree:"]; }
    uint64_t mem_buffers_kb() { return mem_in_kb_["Buffers:"]; }
    uint64_t mem_cached_kb() { return mem_in_kb_["Cached:"]; }
    uint64_t mem_shmem_kb() { return mem_in_kb_["Shmem:"]; }
    uint64_t mem_slab_kb() { return mem_in_kb_["Slab:"]; }
    uint64_t mem_slab_reclailmable_kb() { return mem_in_kb_["SReclaimable:"]; }
    uint64_t mem_slab_unreclaimable_kb() { return mem_in_kb_["SUnreclaim:"]; }
    uint64_t mem_swap_kb() { return mem_in_kb_["SwapTotal:"]; }
    uint64_t mem_free_swap_kb() { return mem_in_kb_["SwapFree:"]; }
    uint64_t mem_zram_kb() { return mem_in_kb_["Zram:"]; }
    uint64_t mem_mapped_kb() { return mem_in_kb_["Mapped:"]; }
    uint64_t mem_vmalloc_used_kb() { return mem_in_kb_["VmallocUsed:"]; }
    uint64_t mem_page_tables_kb() { return mem_in_kb_["PageTables:"]; }
    uint64_t mem_kernel_stack_kb() { return mem_in_kb_["KernelStack:"]; }
    uint64_t mem_total_kb() { return mem_in_kb_[kMemTotal]; }
    uint64_t mem_free_kb() { return mem_in_kb_[kMemFree]; }
    uint64_t mem_buffers_kb() { return mem_in_kb_[kMemBuffers]; }
    uint64_t mem_cached_kb() { return mem_in_kb_[kMemCached]; }
    uint64_t mem_shmem_kb() { return mem_in_kb_[kMemShmem]; }
    uint64_t mem_slab_kb() { return mem_in_kb_[kMemSlab]; }
    uint64_t mem_slab_reclailmable_kb() { return mem_in_kb_[kMemSReclaim]; }
    uint64_t mem_slab_unreclaimable_kb() { return mem_in_kb_[kMemSUnreclaim]; }
    uint64_t mem_swap_kb() { return mem_in_kb_[kMemSwapTotal]; }
    uint64_t mem_swap_free_kb() { return mem_in_kb_[kMemSwapFree]; }
    uint64_t mem_zram_kb() { return mem_in_kb_[kMemZram]; }
    uint64_t mem_mapped_kb() { return mem_in_kb_[kMemMapped]; }
    uint64_t mem_vmalloc_used_kb() { return mem_in_kb_[kMemVmallocUsed]; }
    uint64_t mem_page_tables_kb() { return mem_in_kb_[kMemPageTables]; }
    uint64_t mem_kernel_stack_kb() { return mem_in_kb_[kMemPageTables]; }

  private:
    std::map<std::string, uint64_t> mem_in_kb_;
+25 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ TEST_F(ValidateProcMemInfo, TestMapsEquality) {
    }
}

TEST_F(ValidateProcMemInfo, TestMapsUsage) {
TEST_F(ValidateProcMemInfo, TestMaps) {
    const std::vector<Vma>& maps = proc_mem->Maps();
    ASSERT_FALSE(maps.empty());
    ASSERT_EQ(proc->num_maps, maps.size());
@@ -96,6 +96,30 @@ TEST_F(ValidateProcMemInfo, TestMapsUsage) {
    EXPECT_EQ(proc_usage.uss, proc_mem->Usage().uss);
}

TEST_F(ValidateProcMemInfo, TestSwapUsage) {
    const std::vector<Vma>& maps = proc_mem->Maps();
    ASSERT_FALSE(maps.empty());
    ASSERT_EQ(proc->num_maps, maps.size());

    pm_memusage_t map_usage, proc_usage;
    pm_memusage_zero(&map_usage);
    pm_memusage_zero(&proc_usage);
    for (size_t i = 0; i < maps.size(); i++) {
        ASSERT_EQ(0, pm_map_usage(proc->maps[i], &map_usage));
        EXPECT_EQ(map_usage.swap, maps[i].usage.swap) << "SWAP mismatch for map: " << maps[i].name;
        pm_memusage_add(&proc_usage, &map_usage);
    }

    EXPECT_EQ(proc_usage.swap, proc_mem->Usage().swap);
}

TEST_F(ValidateProcMemInfo, TestSwapOffsets) {
    const MemUsage& proc_usage = proc_mem->Usage();
    const std::vector<uint16_t>& swap_offsets = proc_mem->SwapOffsets();

    EXPECT_EQ(proc_usage.swap / getpagesize(), swap_offsets.size());
}

class ValidateProcMemInfoWss : public ::testing::Test {
  protected:
    void SetUp() override {
+10 −3
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ static void add_mem_usage(MemUsage* to, const MemUsage& from) {
    to->pss += from.pss;
    to->uss += from.uss;

    to->swap += from.swap;

    to->private_clean += from.private_clean;
    to->private_dirty += from.private_dirty;

@@ -76,6 +78,10 @@ const MemUsage& ProcMemInfo::Wss() {
    return wss_;
}

const std::vector<uint16_t>& ProcMemInfo::SwapOffsets() const {
    return swap_offsets_;
}

bool ProcMemInfo::WssReset() {
    if (!get_wss_) {
        LOG(ERROR) << "Trying to reset working set from a memory usage counting object";
@@ -115,8 +121,8 @@ bool ProcMemInfo::ReadMaps(bool get_wss) {

    for (auto& vma : maps_) {
        if (!ReadVmaStats(pagemap_fd.get(), vma, get_wss)) {
            LOG(ERROR) << "Failed to read page map for vma " << vma.name << "[" << vma.start
                       << "-" << vma.end << "]";
            LOG(ERROR) << "Failed to read page map for vma " << vma.name << "[" << vma.start << "-"
                       << vma.end << "]";
            maps_.clear();
            return false;
        }
@@ -153,7 +159,8 @@ bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss) {
        if (!PAGE_PRESENT(p) && !PAGE_SWAPPED(p)) continue;

        if (PAGE_SWAPPED(p)) {
            // TODO: do what's needed for swapped pages
            vma.usage.swap += pagesz;
            swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(p));
            continue;
        }

Loading