Changeset 258835 in webkit


Ignore:
Timestamp:
Mar 23, 2020 6:33:51 AM (4 years ago)
Author:
Pablo Saavedra
Message:

[GTK][WPE] Check the cgroups memory limits (v1 and v2) to calculate the systemMemoryUsedAsPercentage() in the MemoryPressureMonitor
https://bugs.webkit.org/show_bug.cgi?id=209186

Reviewed by Carlos Alberto Lopez Perez.

Modifies the systemMemoryUsedAsPercentage() function adding the logic
to read the memory limits and the current memory used in the cgroup
associated to the WebKit process:

  • memory.memsw.usage_in_bytes (or memory.memsw.max in cgroupV2): current usage for memory+Swap
  • memory.limit_in_bytes (or memory.current in cgroupV2): limit of memory usage
  • memory.memsw.limit_in_bytes (or memory.max in cgroupV2): limit of memory+Swap usage

In case of the WK processes are associated to a cgroup with memory
controller, the function reads the memory.limit_in_bytes or
the memory.memsw.limit_in_bytes and the and memory.usage_in_bytes
from the cgroup mount point and calculates the percentage of
memory used.

In other cases (no cgroup memory controller associated or limits
higher than the real memory available), the function will return the
percentage based on the real memory available and real total memory
in the system.

The logic supports supports both cgroupV1 and cgroupV2

  • UIProcess/linux/MemoryPressureMonitor.cpp:

(WebKit::getMemoryTotalWithCgroup):
(WebKit::getMemoryUsageWithCgroup):
(WebKit::getCgroupController):
(WebKit::systemMemoryUsedAsPercentage):

Location:
trunk/Source/WebKit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r258831 r258835  
     12020-03-23  Pablo Saavedra  <psaavedra@igalia.com>
     2
     3        [GTK][WPE] Check the cgroups memory limits (v1 and v2) to calculate the systemMemoryUsedAsPercentage() in the MemoryPressureMonitor
     4        https://bugs.webkit.org/show_bug.cgi?id=209186
     5
     6        Reviewed by Carlos Alberto Lopez Perez.
     7
     8        Modifies the systemMemoryUsedAsPercentage() function adding the logic
     9        to read the memory limits and the current memory used in the cgroup
     10        associated to the WebKit process:
     11
     12        - memory.memsw.usage_in_bytes (or memory.memsw.max in cgroupV2):
     13          current usage for memory+Swap
     14        - memory.limit_in_bytes (or memory.current in cgroupV2):
     15          limit of memory usage
     16        - memory.memsw.limit_in_bytes (or memory.max in cgroupV2):
     17          limit of memory+Swap usage
     18
     19        In case of the WK processes are associated to a cgroup with memory
     20        controller, the function reads the memory.limit_in_bytes or
     21        the memory.memsw.limit_in_bytes and the and memory.usage_in_bytes
     22        from the cgroup mount point and calculates the percentage of
     23        memory used.
     24
     25        In other cases (no cgroup memory controller associated or limits
     26        higher than the real memory available), the function will return the
     27        percentage based on the real memory available and real total memory
     28        in the system.
     29
     30        The logic supports supports both cgroupV1 and cgroupV2
     31
     32        * UIProcess/linux/MemoryPressureMonitor.cpp:
     33        (WebKit::getMemoryTotalWithCgroup):
     34        (WebKit::getMemoryUsageWithCgroup):
     35        (WebKit::getCgroupController):
     36        (WebKit::systemMemoryUsedAsPercentage):
     37
    1382020-03-23  Chris Lord  <clord@igalia.com>
    239
  • trunk/Source/WebKit/UIProcess/linux/MemoryPressureMonitor.cpp

    r248264 r258835  
    3636#include <wtf/Threading.h>
    3737#include <wtf/UniStdExtras.h>
     38#include <wtf/text/CString.h>
    3839
    3940namespace WebKit {
     
    4748static const int s_memoryPresurePercentageThreshold = 90;
    4849static const int s_memoryPresurePercentageThresholdCritical = 95;
     50// cgroups.7: The usual place for such mounts is under a tmpfs(5)
     51// filesystem mounted at /sys/fs/cgroup.
     52static const char* s_cgroupMemoryPath = "/sys/fs/cgroup/memory/%s/%s";
     53static const char* s_cgroupController = "/proc/self/cgroup";
     54static const unsigned maxCgroupPath = 4096; // PATH_MAX = 4096 from (Linux) include/uapi/linux/limits.h
    4955
    5056static size_t lowWatermarkPages()
     
    127133}
    128134
     135size_t getMemoryTotalWithCgroup(CString memoryControllerName)
     136{
     137    char buffer[128];
     138    char cgroupPath[maxCgroupPath];
     139    char* token;
     140    FILE* file;
     141
     142    // Check memory limits in cgroupV2
     143    snprintf(cgroupPath, maxCgroupPath, s_cgroupMemoryPath, memoryControllerName.data(), "memory.memsw.max");
     144    file = fopen(cgroupPath, "r");
     145    if (file) {
     146        token = fgets(buffer, 128, file);
     147        fclose(file);
     148        return atoll(token);
     149    }
     150    snprintf(cgroupPath, maxCgroupPath, s_cgroupMemoryPath, memoryControllerName.data(), "memory.max");
     151    file = fopen(cgroupPath, "r");
     152    if (file) {
     153        token = fgets(buffer, 128, file);
     154        fclose(file);
     155        return atoll(token);
     156    }
     157
     158    // Check memory limits in cgroupV1
     159    snprintf(cgroupPath, maxCgroupPath, s_cgroupMemoryPath, memoryControllerName.data(), "memory.memsw.limit_in_bytes");
     160    file = fopen(cgroupPath, "r");
     161    if (file) {
     162        token = fgets(buffer, 128, file);
     163        fclose(file);
     164        return atoll(token);
     165    }
     166    snprintf(cgroupPath, maxCgroupPath, s_cgroupMemoryPath, memoryControllerName.data(), "memory.limit_in_bytes");
     167    file = fopen(cgroupPath, "r");
     168    if (file) {
     169        token = fgets(buffer, 128, file);
     170        fclose(file);
     171        return atoll(token);
     172    }
     173    return 0;
     174}
     175
     176static size_t getMemoryUsageWithCgroup(CString memoryControllerName)
     177{
     178    char buffer[128];
     179    char cgroupPath[maxCgroupPath];
     180    char* token;
     181    char* line;
     182    FILE* fileCgroupPathUsageBytes;
     183
     184    // Check memory limits in cgroupV2
     185    snprintf(cgroupPath, maxCgroupPath, s_cgroupMemoryPath, memoryControllerName.data(), "memory.current");
     186    fileCgroupPathUsageBytes = fopen(cgroupPath, "r");
     187    if (fileCgroupPathUsageBytes) {
     188        line = fgets(buffer, 128, fileCgroupPathUsageBytes);
     189        token = strtok(line, " ");
     190        fclose(fileCgroupPathUsageBytes);
     191        return atoll(token);
     192    }
     193
     194    // Check memory limits in cgroupV1
     195    snprintf(cgroupPath, maxCgroupPath, s_cgroupMemoryPath, memoryControllerName.data(), "memory.usage_in_bytes");
     196    fileCgroupPathUsageBytes = fopen(cgroupPath, "r");
     197    if (fileCgroupPathUsageBytes) {
     198        line = fgets(buffer, 128, fileCgroupPathUsageBytes);
     199        token = strtok(line, " ");
     200        fclose(fileCgroupPathUsageBytes);
     201        return atoll(token);
     202    }
     203    return 0;
     204}
     205
     206// This file describes control groups to which the process with
     207// the corresponding PID belongs. The displayed information differs
     208// for cgroups version 1 and version 2 hierarchies.
     209//
     210// Example:
     211//
     212// $ cat /proc/self/cgroup
     213// 12:hugetlb:/
     214// 11:rdma:/
     215// 10:net_cls,net_prio:/
     216// 9:devices:/user.slice
     217// 8:memory:/user.slice
     218// 7:freezer:/user/psaavedra/0
     219// 6:pids:/user.slice/user-1000.slice/user@1000.service
     220// 5:blkio:/user.slice
     221// 4:perf_event:/
     222// 3:cpu,cpuacct:/user.slice
     223// 2:cpuset:/
     224// 1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
     225// 0::/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
     226static CString getCgroupController(const char* controllerName)
     227{
     228    CString memoryControllerName;
     229    FILE* file = fopen(s_cgroupController, "r");
     230    if (!file)
     231        return CString();
     232
     233    char buffer[maxCgroupPath];
     234    while (char* line = fgets(buffer, maxCgroupPath, file)) {
     235        char* token = strtok(line, "\n");
     236        if (!token)
     237            break;
     238
     239        token = strtok(token, ":");
     240        token = strtok(nullptr, ":");
     241        if (!strcmp(token, controllerName)) {
     242            token = strtok(nullptr, ":");
     243            memoryControllerName = CString(token);
     244            fclose(file);
     245            return memoryControllerName;
     246        }
     247    }
     248    fclose(file);
     249    return CString();
     250}
     251
     252
    129253static int systemMemoryUsedAsPercentage()
    130254{
     
    191315        return -1;
    192316
    193     return ((memoryTotal - memoryAvailable) * 100) / memoryTotal;
     317    int memoryUsagePercentage = ((memoryTotal - memoryAvailable) * 100) / memoryTotal;
     318    CString memoryControllerName = getCgroupController("memory");
     319    if (!memoryControllerName.isNull()) {
     320        memoryTotal = getMemoryTotalWithCgroup(memoryControllerName);
     321        size_t memoryUsage = getMemoryUsageWithCgroup(memoryControllerName);
     322        if (memoryTotal) {
     323            int memoryUsagePercentageWithCgroup = 100 * ((float) memoryUsage / (float) memoryTotal);
     324            if (memoryUsagePercentageWithCgroup > memoryUsagePercentage)
     325                memoryUsagePercentage = memoryUsagePercentageWithCgroup;
     326        }
     327    }
     328    return memoryUsagePercentage;
    194329}
    195330
Note: See TracChangeset for help on using the changeset viewer.