Files
darling-lol/tools/install-riot-memory-runtime.py
T
lucannez64andClaude Opus 5.5 4370f375cd Cut Darling overhead in League fights and add passive match capture
Game process (ARAM Hexgate: 84 -> 127 FPS average, slowest stretches ~110):
- Local pthread mutexes, condition variables and Mach semaphores are on by
  default in the game process only, with /tmp/rclol-no-local-* opt-outs.
  The main thread's darlingserver waits fell from 1.36 to 0.10 ms per frame.
- Local semaphores: the count and the slot generation change in one
  compare-exchange, a destroy leaves a negative marker, the table is reset
  after fork, and names the table did not create go to the server.
- Metal: drop identical re-binds (keyed on the Indium object, depth-stencil
  retained), pass blit resources by reference, and stop resetting vertex
  descriptors twice.
- Core isolation of the main thread is opt-in (/tmp/rclol-core-isolation);
  it lowered FPS in its only match.
- Optimized libc/libc++/Foundation overlays, AVX2 string primitives, real CPU
  topology and their installers and offline checks.

Tools and docs:
- tools/riot-match-capture: passive /proc sampler, user-space IP profiler and
  reports, plus a comparison against the game's netstats.
- tools/riot-lsem-model and tools/riot-metal-bind-model: host models that
  extract the shipped code and check it.
- tools/install-riot-metal-pair.sh installs Metal and Indium together.
- Status, setup, testing and troubleshooting docs updated with the measured
  matches and the switch table; manifest file counts match the patches.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:48:34 +02:00

132 lines
6.1 KiB
Python

#!/usr/bin/env python3
"""Install the tested reclamation library atomically, without restarting clients."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import re
import shutil
import stat
import tempfile
ROOT = Path(__file__).resolve().parent.parent
# The optimized relink from tools/build-riot-kqueue-runtime.py is the library the
# client runtime is supposed to run; the plain CMake build (no -O flag) is not.
DEFAULT_ARTIFACT = ROOT / "build/riot-libsystem_kernel.dylib"
def digest(path):
with path.open("rb") as input:
return hashlib.file_digest(input, "sha256").hexdigest()
def install(binary, destinations, backup_folder):
with binary.open("rb") as input:
if input.read(4) != b"\xcf\xfa\xed\xfe":
raise ValueError("Expected the tested 64-bit Mach-O kernel library")
version = re.match(r"(\d+)\.(\d+)", os.uname().release)
if not version or tuple(map(int, version.groups())) < (5, 14):
raise ValueError("The reuse translation requires Linux 5.14 or newer")
expected = digest(binary)
records, staged = [], []
# Prepare every backup and replacement before changing any destination.
try:
for index, destination in enumerate(destinations):
if destination.is_symlink() or not destination.is_file():
raise ValueError("Expected a regular installed library: " + str(destination))
metadata = destination.stat()
old_hash = digest(destination)
if old_hash == expected:
records.append({"path": str(destination), "already_current": True})
continue
backup = backup_folder / (str(index) + "-" + old_hash + ".dylib")
backup_folder.mkdir(parents=True, exist_ok=True)
if backup.exists():
if digest(backup) != old_hash:
raise ValueError("The existing backup has unexpected contents")
else:
shutil.copy2(destination, backup)
fd, temporary = tempfile.mkstemp(prefix=".libsystem_kernel-staged-", dir=destination.parent)
staged.append((Path(temporary), destination))
with os.fdopen(fd, "wb") as output, binary.open("rb") as input:
shutil.copyfileobj(input, output)
output.flush()
os.fchmod(output.fileno(), stat.S_IMODE(metadata.st_mode))
os.fchown(output.fileno(), metadata.st_uid, metadata.st_gid)
os.fsync(output.fileno())
if digest(Path(temporary)) != expected:
raise ValueError("The staged library does not match the build")
records.append({"path": str(destination), "backup": str(backup)})
for temporary, destination in staged:
os.replace(temporary, destination)
directory = os.open(destination.parent, os.O_DIRECTORY)
try:
os.fsync(directory)
finally:
os.close(directory)
if any(digest(path) != expected for path in destinations):
raise ValueError("Installed library verification failed")
finally:
for temporary, _ in staged:
if temporary.exists():
temporary.unlink()
return {"installed": True, "sha256": expected, "libraries": records,
"restart_performed": False,
"activation": "Exit the game and clients, then restart Darling; an active overlay may still expose the old library."}
def prefix_destinations(config, binary, artifact):
"""Destination list for an installation, and a note about the artifact.
The prefix copies may be replaced from any tested source, but the prepared
artifact is never a destination of a different library: a run that does not
install the artifact itself leaves it untouched. That is what keeps the
optimized relink from being silently replaced by the plain CMake build.
"""
destinations = [
Path(config["prefix"]) / config["guest_home"].lstrip("/") / "RuntimeLibraries/libsystem_kernel.dylib",
# Keep the per-prefix bootstrap copy consistent; leave the system SDK alone.
Path(config["prefix"]) / "usr/lib/system/libsystem_kernel.dylib",
]
if not artifact.exists():
return destinations, "the prepared artifact " + str(artifact) + " does not exist yet"
if Path(binary).resolve() != artifact.resolve():
return destinations, ("refusing to overwrite " + str(artifact)
+ " with a different library; rebuild it with "
"build/runtime/tools/build-riot-kqueue-runtime.py")
destinations.append(artifact)
return destinations, None
def parse_arguments(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--binary", type=Path, default=DEFAULT_ARTIFACT)
parser.add_argument("--artifact", type=Path, default=DEFAULT_ARTIFACT)
# A previous sudo server install can make build/backups root-owned.
parser.add_argument("--backup-dir", type=Path, default=ROOT / "build/memory-runtime-backups")
return parser, parser.parse_args(argv)
def main():
parser, args = parse_arguments()
if not args.binary.is_file():
parser.exit(1, "The library to install does not exist: " + str(args.binary) + "; build the "
"optimized relink first: python3 build/runtime/tools/build-riot-kqueue-runtime.py\n")
config = json.loads((ROOT / "build/config.json").read_text())
destinations, note = prefix_destinations(config, args.binary, args.artifact)
if note:
print("note:", note)
try:
result = install(args.binary, destinations, args.backup_dir)
except PermissionError as error:
parser.exit(1, "Cannot write " + str(error.filename) + "; choose a writable --backup-dir or run the installer with sudo.\n")
result["artifact"] = str(args.artifact)
result["artifact_replaced"] = any(Path(record["path"]).resolve() == args.artifact.resolve()
for record in result["libraries"] if not record.get("already_current"))
print(json.dumps(result))
if __name__ == "__main__":
main()