summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/runqueue.py
diff options
context:
space:
mode:
authorAryaman Gupta <aryaman.gupta@windriver.com>2022-08-04 14:52:32 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-08-12 11:49:29 +0100
commitf5c616d5aff31814c0fe2a4b16e3e89bebf1c10a (patch)
treefef5ac866d634f706bb4dd039d8a99123c31bd14 /bitbake/lib/bb/runqueue.py
parent0f6817f2a4552c82f2eb58602b28959a1792c0d4 (diff)
downloadpoky-f5c616d5aff31814c0fe2a4b16e3e89bebf1c10a.tar.gz
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) 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/lib/bb/runqueue.py')
-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 bc1cbb360f..d0ffe3932c 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -168,11 +168,15 @@ class RunQueueScheduler(object):
168 openSUSE /proc/pressure/* files have readable file permissions but when read the error EOPNOTSUPP (Operation not supported) 168 openSUSE /proc/pressure/* files have readable file permissions but when read the error EOPNOTSUPP (Operation not supported)
169 is returned. 169 is returned.
170 """ 170 """
171 if self.rq.max_cpu_pressure or self.rq.max_io_pressure: 171 if self.rq.max_cpu_pressure or self.rq.max_io_pressure or self.rq.max_memory_pressure:
172 try: 172 try:
173 with open("/proc/pressure/cpu") as cpu_pressure_fds, open("/proc/pressure/io") as io_pressure_fds: 173 with open("/proc/pressure/cpu") as cpu_pressure_fds, \
174 open("/proc/pressure/io") as io_pressure_fds, \
175 open("/proc/pressure/memory") as memory_pressure_fds:
176
174 self.prev_cpu_pressure = cpu_pressure_fds.readline().split()[4].split("=")[1] 177 self.prev_cpu_pressure = cpu_pressure_fds.readline().split()[4].split("=")[1]
175 self.prev_io_pressure = io_pressure_fds.readline().split()[4].split("=")[1] 178 self.prev_io_pressure = io_pressure_fds.readline().split()[4].split("=")[1]
179 self.prev_memory_pressure = memory_pressure_fds.readline().split()[4].split("=")[1]
176 self.prev_pressure_time = time.time() 180 self.prev_pressure_time = time.time()
177 self.check_pressure = True 181 self.check_pressure = True
178 except: 182 except:
@@ -184,21 +188,26 @@ class RunQueueScheduler(object):
184 def exceeds_max_pressure(self): 188 def exceeds_max_pressure(self):
185 """ 189 """
186 Monitor the difference in total pressure at least once per second, if 190 Monitor the difference in total pressure at least once per second, if
187 BB_PRESSURE_MAX_{CPU|IO} are set, return True if above threshold. 191 BB_PRESSURE_MAX_{CPU|IO|MEMORY} are set, return True if above threshold.
188 """ 192 """
189 if self.check_pressure: 193 if self.check_pressure:
190 with open("/proc/pressure/cpu") as cpu_pressure_fds, open("/proc/pressure/io") as io_pressure_fds: 194 with open("/proc/pressure/cpu") as cpu_pressure_fds, \
195 open("/proc/pressure/io") as io_pressure_fds, \
196 open("/proc/pressure/memory") as memory_pressure_fds:
191 # extract "total" from /proc/pressure/{cpu|io} 197 # extract "total" from /proc/pressure/{cpu|io}
192 curr_cpu_pressure = cpu_pressure_fds.readline().split()[4].split("=")[1] 198 curr_cpu_pressure = cpu_pressure_fds.readline().split()[4].split("=")[1]
193 curr_io_pressure = io_pressure_fds.readline().split()[4].split("=")[1] 199 curr_io_pressure = io_pressure_fds.readline().split()[4].split("=")[1]
200 curr_memory_pressure = memory_pressure_fds.readline().split()[4].split("=")[1]
194 exceeds_cpu_pressure = self.rq.max_cpu_pressure and (float(curr_cpu_pressure) - float(self.prev_cpu_pressure)) > self.rq.max_cpu_pressure 201 exceeds_cpu_pressure = self.rq.max_cpu_pressure and (float(curr_cpu_pressure) - float(self.prev_cpu_pressure)) > self.rq.max_cpu_pressure
195 exceeds_io_pressure = self.rq.max_io_pressure and (float(curr_io_pressure) - float(self.prev_io_pressure)) > self.rq.max_io_pressure 202 exceeds_io_pressure = self.rq.max_io_pressure and (float(curr_io_pressure) - float(self.prev_io_pressure)) > self.rq.max_io_pressure
203 exceeds_memory_pressure = self.rq.max_memory_pressure and (float(curr_memory_pressure) - float(self.prev_memory_pressure)) > self.rq.max_memory_pressure
196 now = time.time() 204 now = time.time()
197 if now - self.prev_pressure_time > 1.0: 205 if now - self.prev_pressure_time > 1.0:
198 self.prev_cpu_pressure = curr_cpu_pressure 206 self.prev_cpu_pressure = curr_cpu_pressure
199 self.prev_io_pressure = curr_io_pressure 207 self.prev_io_pressure = curr_io_pressure
208 self.prev_memory_pressure = curr_memory_pressure
200 self.prev_pressure_time = now 209 self.prev_pressure_time = now
201 return (exceeds_cpu_pressure or exceeds_io_pressure) 210 return (exceeds_cpu_pressure or exceeds_io_pressure or exceeds_memory_pressure)
202 return False 211 return False
203 212
204 def next_buildable_task(self): 213 def next_buildable_task(self):
@@ -1748,6 +1757,7 @@ class RunQueueExecute:
1748 self.scheduler = self.cfgData.getVar("BB_SCHEDULER") or "speed" 1757 self.scheduler = self.cfgData.getVar("BB_SCHEDULER") or "speed"
1749 self.max_cpu_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_CPU") 1758 self.max_cpu_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_CPU")
1750 self.max_io_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_IO") 1759 self.max_io_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_IO")
1760 self.max_memory_pressure = self.cfgData.getVar("BB_PRESSURE_MAX_MEMORY")
1751 1761
1752 self.sq_buildable = set() 1762 self.sq_buildable = set()
1753 self.sq_running = set() 1763 self.sq_running = set()
@@ -1798,6 +1808,13 @@ class RunQueueExecute:
1798 if self.max_io_pressure > upper_limit: 1808 if self.max_io_pressure > upper_limit:
1799 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)) 1809 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))
1800 1810
1811 if self.max_memory_pressure:
1812 self.max_memory_pressure = float(self.max_memory_pressure)
1813 if self.max_memory_pressure < lower_limit:
1814 bb.fatal("Invalid BB_PRESSURE_MAX_MEMORY %s, minimum value is %s." % (self.max_memory_pressure, lower_limit))
1815 if self.max_memory_pressure > upper_limit:
1816 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))
1817
1801 # List of setscene tasks which we've covered 1818 # List of setscene tasks which we've covered
1802 self.scenequeue_covered = set() 1819 self.scenequeue_covered = set()
1803 # List of tasks which are covered (including setscene ones) 1820 # List of tasks which are covered (including setscene ones)