Changeset 244244 in webkit


Ignore:
Timestamp:
Apr 13, 2019 11:46:17 PM (5 years ago)
Author:
zandobersek@gmail.com
Message:

[bmalloc][Linux] Add support for memory status calculation
https://bugs.webkit.org/show_bug.cgi?id=195938

Reviewed by Carlos Garcia Campos.

Memory status and under-memory-pressure capabilities in bmalloc can be
implemented on Linux by reading and parsing the statm file under the
proc filesystem.

We retrieve the resident set size from the statm file and multiply it
with the page size. This gives an upper-bound estimate of the memory
that's being consumed by the process.

The statm-based estimate seems preferable to other alternatives. One
such alternative would be reading and parsing more-detailed smaps file,
also exposed under the proc filesystem. This is at the moment being done
in WTF's MemoryFootprint implementation for Linux systems, but on Linux
ports this operation is being throttled to only execute once per second
because of the big computing expense required to read and parse out the
data. A future MemoryFootprint implementation could simply retrieve the
memory footprint value from bmalloc.

Another alternative is the Linux taskstats interface. This one would
require utilizing a netlink socket to retrieve the necessary statistics,
but it requires the process to have elevated privileges, which is a
blocker.

  • bmalloc/AvailableMemory.cpp:

(bmalloc::LinuxMemory::singleton):
(bmalloc::LinuxMemory::footprint const):
(bmalloc::computeAvailableMemory):
(bmalloc::memoryStatus):

  • bmalloc/AvailableMemory.h:

(bmalloc::isUnderMemoryPressure):

  • bmalloc/bmalloc.h:
Location:
trunk/Source/bmalloc
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/bmalloc/ChangeLog

    r243887 r244244  
     12019-04-13  Zan Dobersek  <zdobersek@igalia.com>
     2
     3        [bmalloc][Linux] Add support for memory status calculation
     4        https://bugs.webkit.org/show_bug.cgi?id=195938
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        Memory status and under-memory-pressure capabilities in bmalloc can be
     9        implemented on Linux by reading and parsing the statm file under the
     10        proc filesystem.
     11
     12        We retrieve the resident set size from the statm file and multiply it
     13        with the page size. This gives an upper-bound estimate of the memory
     14        that's being consumed by the process.
     15
     16        The statm-based estimate seems preferable to other alternatives. One
     17        such alternative would be reading and parsing more-detailed smaps file,
     18        also exposed under the proc filesystem. This is at the moment being done
     19        in WTF's MemoryFootprint implementation for Linux systems, but on Linux
     20        ports this operation is being throttled to only execute once per second
     21        because of the big computing expense required to read and parse out the
     22        data. A future MemoryFootprint implementation could simply retrieve the
     23        memory footprint value from bmalloc.
     24
     25        Another alternative is the Linux taskstats interface. This one would
     26        require utilizing a netlink socket to retrieve the necessary statistics,
     27        but it requires the process to have elevated privileges, which is a
     28        blocker.
     29
     30        * bmalloc/AvailableMemory.cpp:
     31        (bmalloc::LinuxMemory::singleton):
     32        (bmalloc::LinuxMemory::footprint const):
     33        (bmalloc::computeAvailableMemory):
     34        (bmalloc::memoryStatus):
     35        * bmalloc/AvailableMemory.h:
     36        (bmalloc::isUnderMemoryPressure):
     37        * bmalloc/bmalloc.h:
     38
    1392019-04-04  Yusuke Suzuki  <ysuzuki@apple.com>
    240
  • trunk/Source/bmalloc/bmalloc/AvailableMemory.cpp

    r237399 r244244  
    4444#import <math.h>
    4545#elif BOS(UNIX)
     46#if BOS(LINUX)
     47#include <algorithm>
     48#include <fcntl.h>
     49#endif
    4650#include <unistd.h>
    4751#endif
     
    8993#endif
    9094
     95#if BOS(UNIX)
     96struct LinuxMemory {
     97    static const LinuxMemory& singleton()
     98    {
     99        static LinuxMemory s_singleton;
     100        static std::once_flag s_onceFlag;
     101        std::call_once(s_onceFlag,
     102            [] {
     103                long numPages = sysconf(_SC_PHYS_PAGES);
     104                s_singleton.pageSize = sysconf(_SC_PAGE_SIZE);
     105                if (numPages == -1 || s_singleton.pageSize == -1)
     106                    s_singleton.availableMemory = availableMemoryGuess;
     107                else
     108                    s_singleton.availableMemory = numPages * s_singleton.pageSize;
     109
     110                s_singleton.statmFd = open("/proc/self/statm", O_RDONLY | O_CLOEXEC);
     111            });
     112        return s_singleton;
     113    }
     114
     115    size_t footprint() const
     116    {
     117        if (statmFd == -1)
     118            return 0;
     119
     120        std::array<char, 256> statmBuffer;
     121        ssize_t numBytes = pread(statmFd, statmBuffer.data(), statmBuffer.size(), 0);
     122        if (numBytes <= 0)
     123            return 0;
     124
     125        std::array<char, 32> rssBuffer;
     126        {
     127            auto begin = std::find(statmBuffer.begin(), statmBuffer.end(), ' ');
     128            if (begin == statmBuffer.end())
     129                return 0;
     130
     131            std::advance(begin, 1);
     132            auto end = std::find(begin, statmBuffer.end(), ' ');
     133            if (end == statmBuffer.end())
     134                return 0;
     135
     136            auto last = std::copy_n(begin, std::min<size_t>(31, std::distance(begin, end)), rssBuffer.begin());
     137            *last = '\0';
     138        }
     139
     140        unsigned long dirtyPages = strtoul(rssBuffer.data(), nullptr, 10);
     141        return dirtyPages * pageSize;
     142    }
     143
     144    long pageSize { 0 };
     145    size_t availableMemory { 0 };
     146
     147    int statmFd { -1 };
     148};
     149#endif
     150
    91151static size_t computeAvailableMemory()
    92152{
     
    101161    // (for example) and we have code that depends on those boundaries.
    102162    return ((sizeAccordingToKernel + multiple - 1) / multiple) * multiple;
     163#elif BOS(LINUX)
     164    return LinuxMemory::singleton().availableMemory;
    103165#elif BOS(UNIX)
    104166    long pages = sysconf(_SC_PHYS_PAGES);
     
    122184}
    123185
    124 #if BPLATFORM(IOS_FAMILY)
     186#if BPLATFORM(IOS_FAMILY) || BOS(LINUX)
    125187MemoryStatus memoryStatus()
    126188{
     189#if BPLATFORM(IOS_FAMILY)
    127190    task_vm_info_data_t vmInfo;
    128191    mach_msg_type_number_t vmSize = TASK_VM_INFO_COUNT;
     
    133196
    134197    double percentInUse = static_cast<double>(memoryFootprint) / static_cast<double>(availableMemory());
     198#elif BOS(LINUX)
     199    auto& memory = LinuxMemory::singleton();
     200    size_t memoryFootprint = memory.footprint();
     201    double percentInUse = static_cast<double>(memoryFootprint) / static_cast<double>(memory.availableMemory);
     202#endif
     203
    135204    double percentAvailableMemoryInUse = std::min(percentInUse, 1.0);
    136    
    137205    return MemoryStatus(memoryFootprint, percentAvailableMemoryInUse);
    138206}
  • trunk/Source/bmalloc/bmalloc/AvailableMemory.h

    r237399 r244244  
    3333size_t availableMemory();
    3434
    35 #if BPLATFORM(IOS_FAMILY)
     35#if BPLATFORM(IOS_FAMILY) || BOS(LINUX)
    3636struct MemoryStatus {
    3737    MemoryStatus(size_t memoryFootprint, double percentAvailableMemoryInUse)
     
    6262inline bool isUnderMemoryPressure()
    6363{
    64 #if BPLATFORM(IOS_FAMILY)
     64#if BPLATFORM(IOS_FAMILY) || BOS(LINUX)
    6565    return percentAvailableMemoryInUse() > memoryPressureThreshold;
    6666#else
  • trunk/Source/bmalloc/bmalloc/bmalloc.h

    r237577 r244244  
    112112}
    113113   
    114 #if BPLATFORM(IOS_FAMILY)
     114#if BPLATFORM(IOS_FAMILY) || BOS(LINUX)
    115115inline size_t memoryFootprint()
    116116{
Note: See TracChangeset for help on using the changeset viewer.