Skip to content

BEAM schedulers consume 850% CPU on macOS when idle (missing +sbwt none) #66

@jmanhype

Description

@jmanhype

Problem

On macOS (Apple Silicon, 10 cores), OSA consumes 850% CPU even when completely idle — no active sessions, no pending tasks, no LLM calls.

Root Cause

The BEAM VM's default scheduler behavior is to busy-wait (spin-poll) for work. With 10 scheduler threads, each spins at ~85% CPU checking for runnable processes, even when there are none.

This is controlled by the +sbwt (scheduler busy wait threshold) flag. The default is medium, which means schedulers actively spin. On Linux servers this is usually fine (schedulers yield to the OS scheduler), but on macOS with Apple Silicon it results in sustained high CPU usage.

Evidence

$ ps -o %cpu -p $(pgrep -f OptimalSystemAgent)
%CPU
853.1

$ uptime
load averages: 18.22 18.40 18.79  (on a 10-core machine)

$ sample 52936 1
Thread erts_sched_1: 682 samples
  227 in JIT code (actual work: 0%)
  185 in erts_schedule → erts_check_io → kevent (busy-wait cycle)
  270 in pthread mutex contention (scheduler lock overhead)

The process had been running for 2.5 days accumulating 18,444 minutes of CPU time while doing essentially nothing.

Fix

Add +sbwt none +sbwtdcpu none +sbwtdio none to the BEAM VM flags before startup.

Option 1: Environment variable (simplest)

export ERL_FLAGS="+sbwt none +sbwtdcpu none +sbwtdio none"
mix run -e "OptimalSystemAgent.CLI.serve()"

Option 2: Wrapper script

#!/bin/bash
export ERL_FLAGS="+sbwt none +sbwtdcpu none +sbwtdio none"
cd "$(dirname "$0")"
exec mix run -e "OptimalSystemAgent.CLI.serve()"

Option 3: launchd plist (macOS)

Add to EnvironmentVariables dict:

<key>ERL_FLAGS</key>
<string>+sbwt none +sbwtdcpu none +sbwtdio none</string>

Result

After applying the fix:

  • CPU: 853% → 0.0%
  • Load average: 18.4 → 3.5 (and dropping)
  • OSA fully functional, all sessions and tools working normally

Recommendation

Consider adding +sbwt none as a default in the startup path, or at minimum documenting it in the README. Every macOS user will hit this.

Environment

  • macOS 15.3.1 (Sequoia)
  • Apple M-series (10 cores)
  • Erlang/OTP 28, Elixir 1.19.5
  • OSA running via mix run -e OptimalSystemAgent.CLI.serve()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions