summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorAryaman Gupta <aryaman.gupta@windriver.com>2022-08-16 15:13:44 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-08-23 15:57:11 +0100
commitafd213cc8e71976f2e52177927563a6868a2bed7 (patch)
tree13cfd1937e3e85a0a3ee148ddee82d056133271a /bitbake
parenteaf8d5efa0c2472dbaf0df962c0e516191bde1a5 (diff)
downloadpoky-afd213cc8e71976f2e52177927563a6868a2bed7.tar.gz
bitbake: bitbake: runqueue: add memory pressure regulation
Prevent new tasks from being scheduled if the memory pressure is above a certain threshold, specified through the "BB_MAX_PRESSURE_MEMORY" variable in the conf/local.conf file. This is an extension to the following commit and hence regulates pressure in the same way: 48a6d84de1 bitbake: runqueue: add cpu/io pressure regulation Memory pressure is experienced when time is spent swapping, refaulting pages from the page cache or performing direct reclaim. This is why memory pressure is rarely seen but might be useful as a last resort to prevent OOM errors. (Bitbake rev: 44c395434c7be8dab968630a610c8807f512920c) (Bitbake rev: 82b683f8c7a559f4fcab68f6a0fa7dc3dc20fa05) Signed-off-by: Aryaman Gupta <aryaman.gupta@windriver.com> Signed-off-by: Randy Macleod <Randy.Macleod@windriver.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/runqueue.py27
1 files changed, 22 insertions, 5 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index 9aa99ef4a1..13965796eb 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -151,11 +151,15 @@ class RunQueueScheduler(object):
151 openSUSE /proc/pressure/* files have readable file permissions but when read the error EOPNOTSUPP (Operation not supported) 151 openSUSE /proc/pressure/* files have readable file permissions but when read the error EOPNOTSUPP (Operation not supported)
152 is returned. 152 is returned.
153 """ 153 """
154 if self.rq.max_cpu_pressure or self.rq.max_io_pressure: 154 if self.rq.max_cpu_pressure or self.rq.max_io_pressure or self.rq.max_memory_pressure:
155 try: 155 try:
156 with open("/proc/pressure/cpu") as cpu_pressure_fds, open("/proc/pressure/io") as io_pressure_fds: 156 with open("/proc/pressure/cpu") as cpu_pressure_fds, \
157 open("/proc/pressure/io") as io_pressure_fds, \
158 open("/proc/pressure/memory") as memory_pressure_fds:
159
157 self.prev_cpu_pressure = cpu_pressure_fds.readline().split()[4].split("=")[1] 160 self.prev_cpu_pressure = cpu_pressure_fds.readline().split()[4].split("=")[1]
158 self.prev_io_pressure = io_pressure_fds.readline().split()[4].split("=")[1] 161 self.prev_io_pressure = io_pressure_fds.readline().split()[4].split("=")[1]
162 self.prev_memory_pressure = memory_pressure_fds.readline().split()[4].split("=")[1]
159 self.prev_pressure_time = time.time() 163 self.prev_pressure_time = time.time()
160 self.check_pressure = True 164 self.check_pressure = True
161 except: 165 except:
@@ -167,21 +171,26 @@ class RunQueueScheduler(object):
167 def exceeds_max_pressure(self): 171 def exceeds_max_pressure(self):
168 """ 172 """
169 Monitor the difference in total pressure at least once per second, if 173 Monitor the difference in total pressure at least once per second, if
170 BB_PRESSURE_MAX_{CPU|IO} are set, return True if above threshold. 174 BB_PRESSURE_MAX_{CPU|IO|MEMORY} are set, return True if above threshold.
171 """ 175 """
172 if self.check_pressure: 176 if self.check_pressure:
173 with open("/proc/pressure/cpu") as cpu_pressure_fds, open("/proc/pressure/io") as io_pressure_fds: 177 with open("/proc/pressure/cpu") as cpu_pressure_fds, \
178 open("/proc/pressure/io") as io_pressure_fds, \
179 open("/proc/pressure/memory") as memory_pressure_fds:
174 # extract "total" from /proc/pressure/{cpu|io} 180 # extract "total" from /proc/pressure/{cpu|io}
175 curr_cpu_pressure = cpu_pressure_fds.readline().split()[4].split("=")[1] 181 curr_cpu_pressure = cpu_pressure_fds.readline().split()[4].split("=")[1]
176 curr_io_pressure = io_pressure_fds.readline().split()[4].split("=")[1] 182 curr_io_pressure = io_pressure_fds.readline().split()[4].split("=")[1]
183 curr_memory_pressure = memory_pressure_fds.readline().split()[4].split("=")[1]
177 exceeds_cpu_pressure = self.rq.max_cpu_pressure and (float(curr_cpu_pressure) - float(self.prev_cpu_pressure)) > self.rq.max_cpu_pressure 184 exceeds_cpu_pressure = self.rq.max_cpu_pressure and (float(curr_cpu_pressure) - float(self.prev_cpu_pressure)) > self.rq.max_cpu_pressure
178 exceeds_io_pressure = self.rq.max_io_pressure and (float(curr_io_pressure) - float(self.prev_io_pressure)) > self.rq.max_io_pressure 185 exceeds_io_pressure = self.rq.max_io_pressure and (float(curr_io_pressure) - float(self.prev_io_pressure)) > self.rq.max_io_pressure
186 exceeds_memory_pressure = self.rq.max_memory_pressure and (float(curr_memory_pressure) - float(self.prev_memory_pressure)) > self.rq.max_memory_pressure
179 now = time.time() 187 now = time.time()
180 if now - self.prev_pressure_time > 1.0: 188 if now - self.prev_pressure_time > 1.0:
181 self.prev_cpu_pressure = curr_cpu_pressure 189 self.prev_cpu_pressure = curr_cpu_pressure
182 self.prev_io_pressure = curr_io_pressure 190 self.prev_io_pressure = curr_io_pressure
191 self.prev_memory_pressure = curr_memory_pressure
183 self.prev_pressure_time = now 192 self.prev_pressure_time = now
184 return (exceeds_cpu_pressure or exceeds_io_pressure) 193 return (exceeds_cpu_pressure or exceeds_io_pressure or exceeds_memory_pressure)
185 return False 194 return False
186 195
187 def next_buildable_task(self): 196 def next_buildable_task(self):
@@ -1749,6 +1758,7 @@ class RunQueueExecute:
1749 self.scheduler = self.cfgData.getVar("BB_SCHEDULER") or "speed" 1758 self.scheduler = self.cfgData.getVar("BB_SCHEDULER") or "speed"
1750 self.max_cpu_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_CPU") 1759 self.max_cpu_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_CPU")
1751 self.max_io_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_IO") 1760 self.max_io_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_IO")
1761 self.max_memory_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_MEMORY")
1752 1762
1753 self.sq_buildable = set() 1763 self.sq_buildable = set()
1754 self.sq_running = set() 1764 self.sq_running = set()
@@ -1800,6 +1810,13 @@ class RunQueueExecute:
1800 if self.max_io_pressure > upper_limit: 1810 if self.max_io_pressure > upper_limit:
1801 bb.warn("Your build will be largely unregulated since BB_PRESSURE_MAX_IO is set to %s. It is very unlikely that such high pressure will be experienced." % (self.max_io_pressure)) 1811 bb.warn("Your build will be largely unregulated since BB_PRESSURE_MAX_IO is set to %s. It is very unlikely that such high pressure will be experienced." % (self.max_io_pressure))
1802 1812
1813 if self.max_memory_pressure:
1814 self.max_memory_pressure = float(self.max_memory_pressure)
1815 if self.max_memory_pressure < lower_limit:
1816 bb.fatal("Invalid BB_PRESSURE_MAX_MEMORY %s, minimum value is %s." % (self.max_memory_pressure, lower_limit))
1817 if self.max_memory_pressure > upper_limit:
1818 bb.warn("Your build will be largely unregulated since BB_PRESSURE_MAX_MEMORY is set to %s. It is very unlikely that such high pressure will be experienced." % (self.max_io_pressure))
1819
1803 # List of setscene tasks which we've covered 1820 # List of setscene tasks which we've covered
1804 self.scenequeue_covered = set() 1821 self.scenequeue_covered = set()
1805 # List of tasks which are covered (including setscene ones) 1822 # List of tasks which are covered (including setscene ones)