5 ポイント 投稿者 GN⁺ 2025-12-29 | 1件のコメント | WhatsAppで共有
  • MacThrottle は、Macが過熱により性能を制限しているときに、その状態をメニューバーで視覚的に知らせる SwiftUIベースのアプリ - オープンソース
  • macOSの ProcessInfo.thermalState API と powermetrics コマンドを比較し、システムの実際の熱状態を正確に検知する方法を探る
  • 最終的に thermald が Darwin の notifyd システムに投稿する通知 を活用し、ルート権限なしで熱状態を読み取る方式を実装
  • アプリには 温度・ファン速度グラフ状態ごとの色分けアイコンmacOS通知機能 が含まれ、ログイン時の自動起動にも対応
  • Apple Silicon Macの 熱管理状態をリアルタイムで把握 できるツールとして、開発者やパワーユーザーに有用な診断手段を提供

Macの熱スロットリング問題を認識

  • M2 MacBook Airで外部4K 120Hzディスプレイを使用すると、性能低下と応答遅延 が発生
    • ファンがないため騒音では検知できないが、CPU使用率が100%の状態で電力使用量が低下
  • iStat Menus と MX Power Gadget により、CPU周波数と電力の低下 を確認して熱スロットリングを診断
  • M4 Max MacBook Proでも同様の現象が発生し、14インチモデルの 熱設計上の限界 による問題と言及
  • Apple Siliconの電力効率は依然として高いが、熱状態を直接検知する方法 を探したい

macOSで熱状態をプログラムから確認する

  • macOSは複数の方法で熱状態を公開しているが、一貫性に欠ける
  • Appleが推奨する方法は、FoundationProcessInfo.thermalState を使うこと
    • 出力例: nominal, fair, serious, critical
  • ルート権限が必要な powermetrics -s thermal コマンドでも同様の情報を得られるが、
    両者では 状態の区分単位が異なる
    • 例: fairpowermetricsmoderateheavy の両方を含む
  • 実際にスロットリングが始まる時点は powermetrics では heavy と表示されるが、ProcessInfo では区別できない

thermald と Darwin通知システムの活用

  • powermetrics のデータは thermald デーモン から取得され、
    thermald は現在の熱圧力状態を notifyd システムイベント として公開している
  • notifyutil -g com.apple.system.thermalpressurelevel コマンドで状態を確認可能
  • OSThermalNotification.h ヘッダーで定義されている熱圧力レベル:
    • nominal, moderate, heavy, trapping, sleeping
  • Swiftコードから notify_register_checknotify_get_state を呼び出し、
    ルート権限なしでリアルタイムの熱状態を読み取る機能 を実装

MacThrottleアプリ開発

  • SwiftUI と MenuBarExtra を使って、メニューバー専用アプリを制作
    • 温度計アイコンの色で状態を表示(緑→赤)
    • Info.plistLSUIElementtrue に設定して Dockアイコンを無効化

初期アプローチ: powermetrics ルートヘルパー

  • 当初はルート権限が必要な powermetrics を使うため、
    LaunchDaemon と bashスクリプト でヘルパープロセスを構成
    • /usr/local/bin/mac-throttle-thermal-monitor が10秒ごとに状態を /tmp ファイルへ記録
    • アプリはそのファイルを定期的に読み取って表示

改善: thermald IPC通知の利用

  • notifyd イベントを直接購読する方式へ移行
    • ルート権限が不要になり、コードも簡素化

温度とファン速度の表示

  • CPU/GPU温度とファン速度をグラフ表示
  • 初期には IOKitの非公開API を使った際、温度が実際より低く表示された(約80°C)
  • オープンソースの Stats プロジェクトを参考に、SMCインターフェース へ移行
    • SoC世代ごとに異なるキー(Tp0D, Tf0E など)を使う必要がある
  • SMCが動作しない場合は IOKit にフォールバック

メニューバーグラフの実装

  • グラフは3種類の情報を同時に表示
    • 背景色: 熱状態(緑〜赤)
    • 実線: CPU温度
    • 点線: ファン速度比率
  • 2秒間隔でデータを収集し、10分単位の履歴 を維持
  • onContinuousHover でツールチップを提供し、
    .drawingGroup を追加して GPUレンダリングにより120Hzディスプレイでも滑らかに表示

macOS通知と自動起動

  • 熱状態の変化時に 通知送信機能 を追加
    • 特定の状態への遷移や復帰時に通知可能
  • SMAppService API により、ログイン時の自動起動設定をサポート
    • register() / unregister() / status メソッドで制御

配布と利用

  • Apple Developerアカウントがないため、正式な公証(notarization) は不可
    • GitHub Releases からインストールする場合、Privacy and Security で手動承認が必要
    • 一部のMacでは Xcodeで直接ビルド しないと実行できない
  • インストール方法とビルド方法は GitHub README に記載

結論

  • MacThrottleは、Apple Silicon Macの熱スロットリング状態をリアルタイム監視 できる軽量ツール
  • ルート権限なしで動作し、視覚的フィードバック・通知・グラフ機能 によって
    開発者や高負荷作業ユーザーに システムの熱状態認識 を提供

1件のコメント

 
GN⁺ 2025-12-29
Hacker Newsの意見
  • 2019年モデルのMacBook Pro i9を使っていたが、熱スロットリング検知関数はこんなふうに簡単に書けそう

    function isThermalThrottling() {
      return true;
    }
    

    冗談だけど、高価なi9 CPUを買ったのにi7より性能が低いのはかなりがっかりだった

    • 私も同じモデルを使っているが、右側のポートで充電しないと問題を解決できなかった
      理由は分からないが、そうするとスロットリングが消えた
      それでもmacOSLogicベースのワークフローに慣れているので使い続けている
      Linuxに移ることもできるだろうが、今でもかなり使えるマシンだ
    • 私も2019 i9モデルを使っていたが、VRMモジュールにサーマルパッドを貼ったら完全に別の新しいコンピュータのようになった
      外部モニター2台とAdobe Creative Suiteを使うたびにスロットリングがひどかったが、このパッドで解決した
      欠点は底面が熱くなって膝の上に置きづらくなることだが、まったく後悔していない
      今はM3 MacBook Air(24GB RAM) に買い替えて非常に満足している
      まだ2019モデルを使っている人なら、ぜひVRMサーマルパッド改造を検討してみてほしい
    • 実際、i9自体がノートPC向きではないCPUだったと思う
      Dellでもi9をi7に替えた途端、ずっと良くなった
      「大きい数字 = より良いCPU」というマーケティングに騙されたようなものだ
    • 私も同じ問題を経験した。特に外部モニター2台を接続したときにひどかった
      その後M1 Maxに替えたら完全に別世界だった
      今はM3 Maxにアップグレードしていて、Apple Siliconは長く使えそうだ
    • そのノートPCは私が使った中で最悪のコンピュータだった
      起動直後からファンが回り、Thunderbolt機器をつなぐとカーネルパニックもしばしば起きた
      今使っているM1 Max MBPは完璧に安定している
  • プロジェクトはかなり良さそうに見える
    ただ、macOSでは開発がどんどん難しくなっていて、スロットリングを検知しても実際に何ができるのかは疑問だ
    ファン速度の調整もできないし、アンダーボルティングも不可能では?

    • 私の場合はiStat Menusでファンカーブを直接調整していた
      デフォルトのカーブが遅すぎて、先にスロットリングが発生していたからだ
      Apple SiliconではHigh Power Modeを使うとファンがより速く回る
      今はカスタムカーブは使っていないが、14" M4 Maxではかなりうるさい
      MacBook Airにはファンがないので、ただ冷ますしかない
    • 私はMacs Fan Controlを使ってCPU温度に応じてファンRPMを調整している
      デフォルト設定だと90度以上まで上がるので、もっと保守的に設定した
      GitHubリンク
    • こういうアプリがまさに必要だったが、ついにできた
      ときどきプロセスが暴走してスロットリングが起きるのに、それに気付くまでにバッテリーが半分くらい減っている
    • 結局できるのはアプリを終了するか少し休ませることだけだ
      バックグラウンドで動いているアプリが多いと、こういう問題がよく起きる
  • Homebrewに入れれば無料でコード署名と公証を受けられる
    そうやって配布されると本当にいいと思う

    • いい情報だ。もしWindows向けの無料署名方法もあるのか気になる
    • おお、知らなかった。開発者設定次第で変わるものだと思っていたが、調べてみないと
  • 私の仮説ではCPUの問題ではなく、USBコントローラが熱を飽和させているのだと思う
    CPU/GPUではなく筐体が過熱して放熱が妨げられ、最終的にスロットリングが起きる構造のようだ
    別のアダプタやモニターで実験してみる必要がある

    • 私も2019 i9を使っているが、充電ポートを変えたらスロットリングが消えた
      あなたの言う通りだと思う
    • 完全には理解していないが、私のM2 Airにも似た症状がある
      4K 144Hzモニターに接続してZoomや動画ストリームをいくつも開くと発熱がひどくなる
      USBコントローラというより、単純に負荷が大きいせいのように思う
    • この現象はthermal soakingと呼ばれる
  • サイトはトラフィック急増で落ちたようだ
    リポジトリは angristan/MacThrottle

    • 修正完了。Cloudflare Workersがfail closedモードに設定されていて、トラフィックをブロックしていた
  • iStat MenusでCPUが100%なのに消費電力が低いとスロットリングだと考えられるが、
    低出力のUSB-C充電器に接続されている場合にも同じ現象が起きる
    充電器の電力を検知する機能を追加するとよさそうだ

    • 私もM1 MacBook AirでD&Dセッションをしているときに同じ問題を経験した
      充電中で熱くなってスロットリングがひどかったが、セッション前にあらかじめ充電しておいたら解決した
    • 昔、電源アダプタの出力不足のせいでゲーム中にバッテリーが減って電源が落ちたことがあった
      その後の世代でより大きい電源アダプタが出た理由が理解できた
    • それなら、なぜコア温度だけではスロットリングを判断できないのか気になる
      温度こそが直接の制御変数ではないのか?
    • iStat Menusでは充電器の電力を表示しているが、なぜこういう現象が起きるのかはいまだによく分からない
  • CPU使用率とシステム電力をメニューバーに表示しておけば異常の兆候にすぐ気付ける
    exelban/stats

    • 私もそうしてスロットリングを最初に疑った
      CPU使用率は高いのに電力量が下がっているのを見て気付いた
  • 次のMacBook Air M5にはVapor Chamber冷却が入ってほしい
    今はAppleが放熱よりも騒音最小化を優先しているように見える
    そのためファンの最低速度を強制的に上げている

    • Vapor Chamberは瞬間的な熱拡散には有効だが、結局熱はアルミニウム筐体に伝わる
      筐体が環境と熱平衡に達すると、放熱量は限界に突き当たる
      ファンがあれば銅板と風で十分に解決できる
      結局はエネルギー保存の問題だ
  • thermal pressure通知のバグがあるようだ
    アプリでその問題に遭遇したことがあるか気になる
    関連Issue

    • 私もProcessInfo.processInfo.thermalStateを使ったときに状態が更新されないのを見た
      でも、今使っているthermald通知方式ではそういう問題はない
  • なぜ@_silgen_nameDarwin APIを直接宣言したのか気になる
    import Darwinではアクセスできないのか?

    • 実際、import DarwinだけではそのAPIは公開されていないようだ