Changeset 244244 in webkit
- Timestamp:
- Apr 13, 2019 11:46:17 PM (5 years ago)
- Location:
- trunk/Source/bmalloc
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/bmalloc/ChangeLog
r243887 r244244 1 2019-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 1 39 2019-04-04 Yusuke Suzuki <ysuzuki@apple.com> 2 40 -
trunk/Source/bmalloc/bmalloc/AvailableMemory.cpp
r237399 r244244 44 44 #import <math.h> 45 45 #elif BOS(UNIX) 46 #if BOS(LINUX) 47 #include <algorithm> 48 #include <fcntl.h> 49 #endif 46 50 #include <unistd.h> 47 51 #endif … … 89 93 #endif 90 94 95 #if BOS(UNIX) 96 struct 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 91 151 static size_t computeAvailableMemory() 92 152 { … … 101 161 // (for example) and we have code that depends on those boundaries. 102 162 return ((sizeAccordingToKernel + multiple - 1) / multiple) * multiple; 163 #elif BOS(LINUX) 164 return LinuxMemory::singleton().availableMemory; 103 165 #elif BOS(UNIX) 104 166 long pages = sysconf(_SC_PHYS_PAGES); … … 122 184 } 123 185 124 #if BPLATFORM(IOS_FAMILY) 186 #if BPLATFORM(IOS_FAMILY) || BOS(LINUX) 125 187 MemoryStatus memoryStatus() 126 188 { 189 #if BPLATFORM(IOS_FAMILY) 127 190 task_vm_info_data_t vmInfo; 128 191 mach_msg_type_number_t vmSize = TASK_VM_INFO_COUNT; … … 133 196 134 197 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 135 204 double percentAvailableMemoryInUse = std::min(percentInUse, 1.0); 136 137 205 return MemoryStatus(memoryFootprint, percentAvailableMemoryInUse); 138 206 } -
trunk/Source/bmalloc/bmalloc/AvailableMemory.h
r237399 r244244 33 33 size_t availableMemory(); 34 34 35 #if BPLATFORM(IOS_FAMILY) 35 #if BPLATFORM(IOS_FAMILY) || BOS(LINUX) 36 36 struct MemoryStatus { 37 37 MemoryStatus(size_t memoryFootprint, double percentAvailableMemoryInUse) … … 62 62 inline bool isUnderMemoryPressure() 63 63 { 64 #if BPLATFORM(IOS_FAMILY) 64 #if BPLATFORM(IOS_FAMILY) || BOS(LINUX) 65 65 return percentAvailableMemoryInUse() > memoryPressureThreshold; 66 66 #else -
trunk/Source/bmalloc/bmalloc/bmalloc.h
r237577 r244244 112 112 } 113 113 114 #if BPLATFORM(IOS_FAMILY) 114 #if BPLATFORM(IOS_FAMILY) || BOS(LINUX) 115 115 inline size_t memoryFootprint() 116 116 {
Note: See TracChangeset
for help on using the changeset viewer.