Numa

2 posts

meta3 min readCurated summary

Modernizing the Meta Ads Service With an Open-Source Kernel Scheduler

At Meta’s scale, small latency regressions can materially affect ad relevance, ranking, and revenue. When Linux kernel 6.9’s EEVDF scheduler reduced ad-serving performance, Meta used sched_ext to deploy a workload-specific BPF scheduler without modifying the kernel. The solution reduced p99 ads-retrieval latency by 28%, saved 3.28 MW of power, increased ads ranked by 1.1%, and enabled further improvements through rapid user-space updates. ## Why Ads Latency Matters - Meta’s ads platform processes more than 5 million requests per second, or over 400 billion requests daily. - Lower p99 latency allows more relevant ads to be retrieved and ranked within each request. - General-purpose schedulers such as CFS and EEVDF balance CPU usage without understanding which threads are most important to ad delivery. - Ads-specific scheduling can prioritize work on the critical request path while deferring less-sensitive tasks. ## The Kernel Upgrade Problem - During a move from Linux 6.4 to 6.9, Meta found that EEVDF introduced a latency regression. - The regression reduced the number of ads ranked in responses. - Some servers had to remain on Linux 6.4, creating operational fragmentation and technical debt. - sched_ext provided a way to address the regression without waiting for another kernel release. ## How sched_ext Customizes Scheduling - sched_ext is an upstream, BPF-based framework that entered Linux 6.12. - It lets developers implement scheduling policies in BPF programs responding to events such as: - Thread wake-ups - Run-queue insertion - Dispatching the next thread - CPU idle-state transitions - Meta’s policy divides CPUs into two dynamically sized pools: - Latency-critical request-path threads - Less latency-sensitive background work - Keeping related work on the same CPUs improves L3 cache locality and reduces DRAM access. - The scheduler is loaded by a user-space binary, so new policies can be deployed by restarting the scheduler process rather than rebuilding the kernel. ## Performance and Operational Results The initial deployment on the largest ads-serving server type achieved: - 28% lower p99 latency on the ads retrieval path - 1.1% more weighted ads ranked - 3.28 MW of fleet-wide power savings Two subsequent policy updates produced additional gains: - A further 60% reduction in service p99 latency - 18% fewer timeout errors on the critical path - Delivery in days instead of the months typically required for kernel changes ## From Fix to Optimization Platform - sched_ext gives Meta an independent scheduling-development path alongside upstream Linux evolution. - BPF updates support rapid experimentation with: - Cache-aware thread placement - ROI-based executor routing - NUMA-aware scheduling - Because sched_ext is upstream, other organizations can implement workload-specific policies without maintaining a Linux kernel fork. - Meta plans to use application-level hints, such as request importance, to adjust scheduling slices and queue priority dynamically. sched_ext demonstrates that application-aware scheduling can produce measurable business, latency, and energy benefits. For workloads with priorities that general-purpose schedulers cannot see, an extensible BPF-based scheduler offers a practical way to optimize continuously without coupling improvements to kernel release cycles.

Read original(opens in new tab)
netflix3 min readCurated summary

Mount Mayhem at Netflix: Scaling Containers on Modern CPUs

Netflix’s effort to modernize its container runtime exposed a hardware-level bottleneck rather than an application problem. Under heavy startup concurrency, containers with many image layers triggered massive mount and unmount activity, causing kernel lock contention, systemd stalls, and container startup failures. The issue was especially severe on older dual-socket NUMA instances, while newer single-socket systems scaled much more reliably. ## Container Startup at Netflix - New AWS capacity is rapidly filled with pods as applications scale. - Some nodes became unresponsive, with: - Health checks timing out for more than 30 seconds - Kubelet requests to containerd timing out - systemd processing huge numbers of mount events - The mount table taking tens of seconds to read - The problem primarily affected `r5.metal` instances running images with more than 50 layers. ## Mount Lock Contention - With user namespaces, containerd performs several mount operations for every image layer: - `open_tree()` references the layer. - `mount_setattr()` applies the container’s ID mapping. - `move_mount()` creates an ID-mapped bind mount. - These bind mounts become OverlayFS lower directories and are later unmounted. - The Linux VFS uses global mount-related locks, so concurrent container creation causes CPUs to contend on the same kernel locks. - For 100 containers with 50 layers each, containerd performs the process twice: - `100 × 2 × (1 + 50 + 50) = 20,200` mount operations - This makes startup cost depend heavily on both container concurrency and image layer count. ## Why the New Runtime Exposed the Problem - The old Docker-based runtime shifted file ownership while unpacking images. - All containers shared one host user range, avoiding repeated per-container mount work. - The new containerd-based runtime assigns each container a unique host user range for stronger isolation. - Instead of rewriting file ownership during extraction, it uses Linux ID-mapped mounts to apply ownership mappings efficiently. - This improves security and avoids expensive image copying, but creates many additional mount operations during startup. ## Differences Between AWS Instance Types Netflix compared: - `r5.metal`: 5th-generation Intel, dual-socket, multiple NUMA domains - `m7i.metal-24xl`: 7th-generation Intel, single-socket, single NUMA domain - `m7a.24xlarge`: 7th-generation AMD, single-socket, single NUMA domain Results showed: - At low concurrency—around 20 containers or fewer—all systems performed similarly. - `r5.metal` began failing at roughly 100 concurrent container launches. - Newer Intel instances maintained lower startup times and better success rates. - AMD-based `m7a` instances scaled most consistently and had the fewest failures. ## Kernel and CPU-Level Diagnosis - Profiling showed that containerd spent most of its time in Linux VFS path lookup code. - Specifically, threads were spinning in `path_init()` while waiting on a sequence lock. - Intel Topdown Microarchitecture Analysis found: - 95.5% of pipeline slots stalled on contested accesses - 57% attributed to false sharing - Cache-line bouncing and global lock contention, rather than raw CPU capacity, dominated performance. ## NUMA as a Contributing Factor - NUMA systems divide memory among processor sockets. - Local memory access is faster, while remote access crosses an interconnect and introduces additional latency. - The dual-socket layout of `r5.metal` amplified contention around shared mount-related data. - The better behavior of newer single-socket instances indicated that CPU topology and memory locality were key contributors to the container startup bottleneck. ## Practical Conclusion High-concurrency container launches can overwhelm kernel mount infrastructure, especially when using per-container ID mapping and images with many layers. Netflix’s results suggest minimizing image layers, controlling startup concurrency, and favoring newer single-socket hardware can substantially improve reliability and scaling.

Read original(opens in new tab)