Skip to content

Commit 6bf518d

Browse files
committed
adjust what to build when available resource is limited
1 parent a9911d5 commit 6bf518d

File tree

3 files changed

+58
-10
lines changed

3 files changed

+58
-10
lines changed

lilac

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ from lilac2.cmd import (
4040
run_cmd, git_pull_override, git_push, pkgrel_changed,
4141
git_reset_hard, get_git_branch,
4242
)
43-
from lilac2.tools import read_config
43+
from lilac2 import tools
4444
from lilac2.repo import Repo
4545
from lilac2.const import mydir, _G, PACMAN_DB_DIR
4646
from lilac2.nvchecker import packages_need_update, nvtake, NvResults
@@ -56,7 +56,7 @@ except ImportError:
5656
class db: # type: ignore
5757
USE = False
5858

59-
config = read_config()
59+
config = tools.read_config()
6060

6161
# Setting up environment variables
6262
os.environ.update(config.get('envvars', ()))
@@ -260,6 +260,7 @@ def start_build(
260260
buildsorter, failed,
261261
running = frozenset(futures.values()),
262262
limit = max_concurrency - len(futures),
263+
starving = not bool(futures),
263264
)
264265
for pkg in pkgs:
265266
if pkg.pkgbase not in nvdata:
@@ -292,20 +293,47 @@ def try_pick_some(
292293
failed: dict[str, tuple[str, ...]],
293294
running: Set[str],
294295
limit: int,
296+
starving: bool,
295297
) -> list[PkgToBuild]:
296-
ret: list[PkgToBuild] = []
297-
298298
if not buildsorter.is_active():
299-
return ret
299+
return []
300300

301301
ready = buildsorter.get_ready()
302302
if not ready:
303-
return ret
303+
return []
304+
305+
cpu_avail_percent = tools.get_avail_cpu_percent()
306+
memory_avail = tools.get_avail_memory()
307+
308+
ready_to_build = [pkg for pkg in ready if pkg not in running]
309+
if not ready_to_build:
310+
return []
311+
312+
rusages = db.get_pkgs_last_rusage(ready_to_build)
313+
ready2 = [pkg for pkg in ready_to_build
314+
if (r := rusages.get(pkg)) and r.memory < memory_avail]
315+
if not ready2:
316+
if starving:
317+
ready2 = sorted(
318+
ready_to_build,
319+
key=lambda pkg: rusages.get(pkg) and r.memory or 10 * 1024**3, # type: ignore
320+
)
321+
limit = 1
322+
logger.info('insufficient memory, starting only one build')
323+
else:
324+
logger.info('insufficient memory, not starting another concurrent build')
325+
return []
304326

305-
for pkg in ready:
306-
if pkg in running:
307-
continue
327+
ready2.sort(key=lambda pkg: rusages.get(pkg) and r.cputime or 3600) # type: ignore
328+
if cpu_avail_percent < 0.5:
329+
# low cpu usage, build a big package
330+
ready2.insert(0, ready2.pop())
331+
else:
332+
logger.info('high cpu usage, preferring low-cpu-usage builds')
333+
334+
ret: list[PkgToBuild] = []
308335

336+
for pkg in ready2:
309337
to_build = PkgToBuild(pkg)
310338

311339
if pkg in failed:

lilac2/db.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def connect_with_schema(schema, dsn):
2424
return conn
2525

2626
def setup(dsn, schema):
27-
global USE, Pool, SCHEMA
27+
global USE, Pool
2828
Pool = psycopg2.pool.ThreadedConnectionPool(
2929
1, 10, dsn, partial(connect_with_schema, schema))
3030
USE = True

lilac2/tools.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,23 @@ def reap_zombies() -> None:
2929
with suppress(ChildProcessError):
3030
while os.waitid(os.P_ALL, 0, os.WEXITED | os.WNOHANG) is not None:
3131
pass
32+
33+
def get_avail_cpu_percent() -> float:
34+
ncpu = os.process_cpu_count()
35+
running = 0
36+
with open('/proc/stat') as f:
37+
for l in f:
38+
if l.startswith('procs_running '):
39+
running = int(l.split()[1])
40+
break
41+
if ncpu and running:
42+
return running / ncpu
43+
else:
44+
return 0.0
45+
46+
def get_avail_memory() -> int:
47+
with open('/proc/stat') as f:
48+
for l in f:
49+
if l.startswith('MemAvailable:'):
50+
return int(l.split()[1]) * 1024
51+
return 10 * 1024 ** 3

0 commit comments

Comments
 (0)