Skip to content

Commit 7d1f4d7

Browse files
authored
Merge pull request #479 from nix-community/better-cached-builds
buildbot-dev: fix on macOS
2 parents 52606e3 + 2dbba83 commit 7d1f4d7

File tree

3 files changed

+118
-31
lines changed

3 files changed

+118
-31
lines changed

packages/buildbot-dev.nix

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,41 @@
1515
openssh,
1616
python,
1717
writeShellScriptBin,
18+
stdenv,
19+
darwin,
1820
}:
1921
let
20-
pythonEnv = python.withPackages (ps: [
21-
ps.twisted
22-
(ps.toPythonModule buildbot)
23-
(ps.toPythonModule buildbot-worker)
24-
buildbot-nix
25-
buildbot-gitea
26-
buildbot-effects
27-
buildbot-plugins.www
28-
]);
22+
pythonEnv = python.withPackages (
23+
ps:
24+
[
25+
ps.twisted
26+
(ps.toPythonModule buildbot)
27+
(ps.toPythonModule buildbot-worker)
28+
buildbot-gitea
29+
buildbot-nix
30+
buildbot-plugins.www
31+
]
32+
++ lib.optional stdenv.isLinux buildbot-effects
33+
);
2934
in
3035
writeShellScriptBin "buildbot-dev" ''
3136
set -xeuo pipefail
3237
git_root=$(git rev-parse --show-toplevel)
3338
export PATH=${
34-
lib.makeBinPath [
35-
nix-eval-jobs
36-
cachix
37-
git
38-
openssh
39-
nix
40-
bash
41-
coreutils
42-
buildbot-effects
43-
]
39+
lib.makeBinPath (
40+
[
41+
nix-eval-jobs
42+
cachix
43+
git
44+
openssh
45+
nix
46+
bash
47+
coreutils
48+
buildbot-effects
49+
]
50+
++ lib.optional stdenv.isLinux buildbot-effects
51+
++ lib.optional stdenv.isDarwin darwin.system_cmds
52+
)
4453
}
4554
mkdir -p "$git_root/.buildbot-dev"
4655
cd "$git_root/.buildbot-dev"

packages/flake-module.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
buildbot-dev = pkgs.python3.pkgs.callPackage ./buildbot-dev.nix {
1414
inherit (self'.packages)
1515
buildbot-gitea
16-
buildbot-effects
1716
buildbot-nix
1817
buildbot
1918
;
19+
buildbot-effects = self'.packages.buildbot-effects or null;
2020
inherit (pkgs) buildbot-worker buildbot-plugins;
2121
};
2222
buildbot-nix = pkgs.python3.pkgs.callPackage ./buildbot-nix.nix { };

packages/master.cfg.py

Lines changed: 89 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
)
66
import getpass
77
import os
8+
import platform
9+
import subprocess
810
import multiprocessing
911
from buildbot.plugins import util
1012
from buildbot.process.factory import BuildFactory
@@ -17,20 +19,76 @@ class EvalWorkerConfig:
1719
max_memory_mib: int
1820

1921

20-
def calculate_eval_workers() -> EvalWorkerConfig:
21-
"""Calculate optimal eval workers based on system resources."""
22-
# Get system resources
23-
cpu_count = multiprocessing.cpu_count()
22+
@dataclass
23+
class MemoryInfo:
24+
total_memory_mib: int
25+
available_memory_mib: int
26+
zfs_arc_used: int = 0
27+
28+
29+
def get_memory_info_macos() -> MemoryInfo:
30+
"""Get memory information on macOS using vm_stat and sysctl."""
31+
try:
32+
# Use vm_stat to get memory information on macOS
33+
result = subprocess.run(["vm_stat"], capture_output=True, text=True, check=True)
34+
35+
# Parse vm_stat output
36+
lines = result.stdout.strip().split("\n")
37+
page_size = None
38+
free_pages = 0
39+
inactive_pages = 0
40+
41+
for line in lines:
42+
if "page size of" in line:
43+
# Extract page size from "Mach Virtual Memory Statistics: (page size of 4096 bytes)"
44+
page_size = int(line.split("page size of ")[1].split(" bytes")[0])
45+
elif line.startswith("Pages free:"):
46+
free_pages = int(line.split(":")[1].strip().rstrip("."))
47+
elif line.startswith("Pages inactive:"):
48+
inactive_pages = int(line.split(":")[1].strip().rstrip("."))
49+
50+
if page_size is None:
51+
raise ValueError("Could not determine page size from vm_stat")
52+
53+
# Available memory is free + inactive pages
54+
available_memory_bytes = (free_pages + inactive_pages) * page_size
55+
available_memory_mib = available_memory_bytes // (1024 * 1024)
56+
57+
# Get total memory using sysctl
58+
result = subprocess.run(
59+
["sysctl", "-n", "hw.memsize"], capture_output=True, text=True, check=True
60+
)
61+
total_memory_bytes = int(result.stdout.strip())
62+
total_memory_mib = total_memory_bytes // (1024 * 1024)
63+
64+
return MemoryInfo(total_memory_mib, available_memory_mib)
65+
66+
except (subprocess.CalledProcessError, ValueError, IndexError) as e:
67+
print(f"Warning: Could not get accurate memory info on macOS: {e}")
68+
# Fallback to conservative estimates
69+
return MemoryInfo(8192, 4096) # 8GB total, 4GB available
70+
71+
72+
def get_memory_info_linux() -> MemoryInfo:
73+
"""Get memory information on Linux using os.sysconf and ZFS ARC detection."""
74+
try:
75+
# Try Linux-specific methods first
76+
total_pages = os.sysconf("SC_PHYS_PAGES")
77+
page_size = os.sysconf("SC_PAGE_SIZE")
78+
available_pages = os.sysconf("SC_AVPHYS_PAGES")
2479

25-
# Get memory using os.sysconf()
26-
total_pages = os.sysconf("SC_PHYS_PAGES")
27-
page_size = os.sysconf("SC_PAGE_SIZE")
28-
available_pages = os.sysconf("SC_AVPHYS_PAGES")
80+
total_memory_mib = (total_pages * page_size) // (1024 * 1024)
81+
available_memory_mib = (available_pages * page_size) // (1024 * 1024)
2982

30-
total_memory_mib = (total_pages * page_size) // (1024 * 1024)
31-
available_memory_mib = (available_pages * page_size) // (1024 * 1024)
83+
except (ValueError, OSError):
84+
# Fallback for other systems
85+
print(
86+
"Warning: Could not get memory info via sysconf, using conservative estimates"
87+
)
88+
total_memory_mib = 8192 # 8GB default
89+
available_memory_mib = 4096 # 4GB available
3290

33-
# Check for ZFS ARC usage
91+
# Check for ZFS ARC usage on Linux
3492
zfs_arc_used = 0
3593
try:
3694
with open("/proc/spl/kstat/zfs/arcstats", "r") as f:
@@ -45,6 +103,26 @@ def calculate_eval_workers() -> EvalWorkerConfig:
45103
# Not a ZFS system or can't read ARC stats
46104
pass
47105

106+
return MemoryInfo(total_memory_mib, available_memory_mib, zfs_arc_used)
107+
108+
109+
def calculate_eval_workers() -> EvalWorkerConfig:
110+
"""Calculate optimal eval workers based on system resources."""
111+
# Get system resources
112+
cpu_count = multiprocessing.cpu_count()
113+
114+
# Get memory using platform-specific methods
115+
system = platform.system()
116+
117+
if system == "Darwin": # macOS
118+
memory_info = get_memory_info_macos()
119+
else: # Linux and other Unix-like systems
120+
memory_info = get_memory_info_linux()
121+
122+
total_memory_mib = memory_info.total_memory_mib
123+
available_memory_mib = memory_info.available_memory_mib
124+
zfs_arc_used = memory_info.zfs_arc_used
125+
48126
# If ZFS is present, account for ARC cache which can be reclaimed
49127
effective_available_memory = available_memory_mib
50128
if zfs_arc_used > 0:

0 commit comments

Comments
 (0)