macOSの寝相について考えたこと -- `pmset`

電源まわりの設定,
前々から何となく気になっていて,なら何故すぐやらない,先日も触れましたが,マシンの新調きっかけで,この辺を整理しておこう,と思ったわけです.
勿論"あくまで自分レベル"で浅く😛

つか,スリープ,よくわかんない.

後で触れようかとは思っているのですが,いまいちスッと入ってこないんですよね.
思うに,"何処が分からないのか,が,分かっていない".

そんな状態で,見切り発進です.

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.3
BuildVersion:   18D42

目指したい設定

ポイント3つ.

ポイント1: バッテリー稼働時は,"持ち".

外出,特に移動中の使用を想定.

電源の供給が保証されない環境の下での作業になるので,バッテリー電源の持ち重視.

ポイント2: 電源アダプタ使用時は,"スリープしない".

一方こちらは,バッテリーの減りを気にすることなく作業できるの環境になるので,勝手に入るスリープは要らない,とする.

ポイント3: 何か裏でやっているらしい,"余計な書き込みはさせない".

SSDには寿命があるのだそうです.なので出来るだけ大切に使っておきましょうよ,な発想からのものと受け止めてます.

言われてみれば確かに,と言うことなのでこちらでもそれに倣おうかなと思いました.

お馴染み,"hibernation" と称されるもの.

スリープ,厳密にはスタンバイモードに入る時,セッションの状態をフラッシュストレージ (SSD) に保存しているのだそうです.
この仕組みにより,スリープ前の状態で復帰する,と言うことを実現しているらしい.

しかしですね.
この "セッションの状態をSSDに書き込む" と言う振る舞いから,SSDをいたわりましょう,と言うのがここで施す設定の目的になります.

行った設定

の前に

csrutil disableしておくこと.*1

csrutil disableの具体的な方法についてはコチラもありますので,よろしかったら.

A: バッテリー稼働時 + ACアダプタ接続時 共通

先述ポイントの3の話になります.

A-1: 書き込まない (hibernatemode)

sudo pmset -a \
  standby              0 \
  hibernatemode        0 \
  highstandbythreshold 0 \
  standbydelaylow      86400 \
  standbydelayhigh     86400

バッテリー稼働時およびAC電源接続使用時に関わらずhibernatemodeはオフ0にすることで,"セッションの状態をSSDに書き込む" という作業を抑制しています.

念のため,
standbyも,man page の記載に従い,0にしておくことにしました.:

To disable hibernation images completely, ensure
hibernatemode standby and autopoweroff are all set to 0.

via. man pmset

また,これまでstandbydelayとされていた設定値は,standbydelaylowstandbydelayhighに変わった模様.
highstandbythresholdで「バッテリー残量,何%を基準に」,それ以下はstandbydelaylow,以上ではstandbydelayhighの値を使う,といった感じみたいです.

これら3つの設定は,デフォルト値のままでも良いかと思ったのですが*2,lowもhighも同じ24hを設定したと言うことで,highstandbythresholdは余り意味無いだろうと考え,0としました.
この設定の方法が正しいかどうかは自信ありません.完全独断によるもので,様子見.

A-2: 書き込まない (hibernatemode)

次です.

hibernateの書き込み先となっているhibernatefileファイルです.
これをクリアし,書き込みできないようにしてしまいます.

sudo rm /var/vm/sleepimage
sudo touch /var/vm/sleepimage
sudo chflags uchg /var/vm/sleepimage

参照先は,いつものこちら.:

» dotfiles/.macos at master · mathiasbynens/dotfiles · GitHub

A-3: その他

最後,その他.

sudo pmset -a \
  gpuswitch            2 \
  acwake               0 \
  halfdim              1 \
  disksleep            0 \
  proximitywake        0

"デフォルト値のままで良いいけど一応"なノリで.
改めてやらなくても良いのでしょうが,pmset -gで出てきたアイテムですので,と言う程度で定義.

proximitywakeという設定値は意味分からないのですが,使わないだろうと思って0
「Apple Watchじゃないの?」なんて声もあって,膝を叩いたのですが,実際の振る舞いを試した人曰くどうも違うらしい.
man pageの記述みても,それっぽい気がしないでもないのですが,公認のサポートページ見ると[セキュリティとプライバシー]の話になっているので,そこら辺りの設定値とのしがらみがあるのかもしれません?

B: バッテリー稼働時

電源の供給がないシーンを想定したもの.:

sudo pmset -b \
  sleep                10 \
  displaysleep         10 \
  powernap             0

C: ACアダプタ接続時

スリープさせない設定に.

sudo pmset -c \
  sleep                0 \
  displaysleep         0 \
  powernap             1 \
  womp                 1

sleepdisplaysleep0にするか,最後まで悩みましたが...

最後に補足しますと,ハードディスクのスリープってのもありますが,これはSSDには関係ないので触れておりません.
設定値はdisksleepとなっているようです.

今回分かった"分かっていなかったこと"?

冒頭で,どうも今いちスッと入ってこない,と書きましたが,
おそらくこんなことだったのだろうと感じてます.

公の場を使って晒すようなものでもないでしょうが,後の忘却のために😇書いておきたいと思います.
シツレイシマス...

2つ.

ひとつめは,「そのために,設定するのはここ」というところを整理できないまま作業をしていたこと.
ふたつめは,用語の使われ方に関するもの.

"コレをするために,ドコを突けばよいのか"

致命的なほどに根本的な話で実に恥ずかしいのですが,
今思えばhibernatemodeへの捉え方のまずさが,この混乱の元凶となったのかな,と感じています.

ストーリーはこんな感じです.:

  1. スリープについて,設定の見直しを思い付く.
  2. 「それ知ってる,pmsetだ,hibernatemodeだ」な感じで,前つんのめり気味で着手.
  3. hibernatemodeによって,3つのスリープモードがあるよね.(ふんふん...)
  4. その後,様々な情報を参照する中.
  5. どうもhibernatemodeは,スリープと言うより,バッテリー消費やhibernate imageの書き込みによる諸問題の中で論じらることの方が多い.
  6. 改めて,自分のスリープって何?,ってなる.調べる.
  7. ん? hibernatemodeはもとより,そのhibernatemodeが実現する3つのスリープとは...?
  8. もしかして違う? 何が?
    :
    : (繰り返し)


と言うことで,整理しておきたいと思います.

"トピック" を設け,それぞれに,
そのために操作対象となる "設定値" を箇条書きで,
考えるきっかけとなった"問題",その"処方",結果それによって"どうなるのか"との切り口でまとめてみたいと思います.

以下.

バッテリーの電力消耗

  • powernap
    → 何が問題?: スリープ時の電力放電(消費).
    → やること?: スリープ中にも関わらず特定のタスクを行うPower Napと言う機能がある.これをオフにする.
    → どうなる?: Power Napによって "意図しない" 電力消費を抑制できる.

"起動ディスクSDDへの書き込み頻度"

  • hibernatemode
  • (standby)
  • (highstandbythreshold)
  • (standbydelaylow)
  • (standbydelayhigh)
    → 何が問題?: SSDの寿命.
    → やること?: スタンバイモードに入る度に,SSDへ,セッションの状態を保存するためのアクセスを行う.この "hibernation" の振る舞いをオフにする.
    → どうなる?: 上述アクセスに起因するSSDの劣化軽減を望むことができる.

"起動ディスクSSDの容量占有"

  • hibernatemode
  • (standby)
  • (highstandbythreshold)
  • (standbydelaylow)
  • (standbydelayhigh)
    → 何が問題?: SSDの容量.
    → やること?: スタンバイモードに入る度に,SSDへ,セッションの状態を保存する.この "hibernation" の振る舞いをオフにする.
    → どうなる?: 上述保存処理によるSSDの容量の占有を回避することができる.

"スリープからの復帰速度"

  • hibernatemode
  • (standby)
  • (highstandbythreshold)
  • (standbydelaylow)
  • (standbydelayhigh)
    → 何が問題?: スリープ状態からの復帰スピード.
    → やること?: スタンバイモードに入る時保存した,復帰前の情報を読み戻している.問題はこの時間.この書き-読みを行う "hibernation" の処理をオフにする.
    → どうなる?: SSDから復帰前の情報を読み戻す手続きがなくなった分,復帰スピードが上がる.しかしマシンの電気容量が無くなった場合,スリープ前の状態を復元できない.

"スリープさせたくない"

  • sleep
  • displaysleep
  • disksleep
    → 何が問題?: スリープによって中断されたくない.
    → やること?: スリープに関する設定値をオフにする.
    → どうなる?: スリープしない.ただしこれによるディスク,ディスプレイの劣化は自己責任.

こんなところ.でしょうか.

なお,()による表記した設定値は,無くても良いかな,と考えているアイテム.

そもそもスリープ(モード)をheibernatemodeで理解しようとするところが,問題なのかも...?

と.

これが2点目にあげました,用語の問題.

その筆頭が,hibernatemode
これにに関する説明.

こんな感じではないでしょうか.*3

hibernatemodeは,03,そして25があり,
0は,スリープモード,
3は,セーフスリープモード,
25が,ディープスリープモード,

どうでしょう.
実に広く,かつ実に多く良く見られるコンテンツではないかと思います.

ところが,お頭弱い自分にとって,この説明の仕方こそが,拙い理解をややこしくしてしまっているように感じてならなかったりするのです.どうでしょう?🙃

決して,上述の説明内容をディするつもりはありません.
それはmacのスリープ,スリープモードというものに対して,アプローチが異なっていた,ということだと.

根本的に,自身の読解力の問題だと思っています.

上述のようなhibernatemodeの説明で目にしていたスリープというのは,云わば"内部的な"とか,技術的な人たちのものであって,
一方,自分が知っていたスリープという用語は,UIやヘルプからのものですので,それとは異なるのだ,
ということを,自身もっと早くに気付くべきだったと思っています.

これに気付いたのは,pmsetのman pageで,"スリープモード","セーフモード",そして"ディープスリープモード"と言った文言が全く出てこないことを知り,その違和感に自分なりの説明がついた時でした.

勿論,hibernatemodeについても,「0がスリープ,3がセーフスリープ,25がディープスリープ」という記述もありません.

ここでやっと,言葉にできたのです.

hibernatemodeは,スリープモードとやら自身を制御するものではない.

誤解承知で極端な表現をすると,
hibernatemodeは,スリープ直前の作業状態(以下,メモリの内容)をSSDに書き込む?,書き込ませない? を選択するもの,と.

スリープの振る舞い自体,つまりスリープモードなるものを制御するチャンネルではない,と言えるのではないか,と言うのがここでの立場.

そんな観点から改めて説明をすると以下.色々と端折ってます.:

hibernatemode=0は,メモリの内容をSSDに退避するような振る舞いは,しないモード,*4
hibernatemode=3は,メモリの内容のコピーをSSDに退避する.スリープ時はメモリの内容で待機.復帰は,そのメモリの内容から.
hibernatemode=25は,メモリの内容のコピーをSSDに退避する.スリープ時はメモリの内容は破棄して待機.復帰は,SSDの内容から.

じゃぁ,そのスリープのモードってやつは?

スリープモードについて調べていた時,一番最初に目にし,一番多く参照していたのがこちら.:

» Mac で省エネルギー設定を使う - Apple サポート

ここではスリープモードについて,Appleオフィシャルな情報ですので,信頼性あり,と勝手に祀って,上のページの内容にしたがって整理をしると,こんな感じでしょうか.:

┌─ スリープモード
│
└─ ディープ・スリープ・モード
        │
        ├─ スタンバイモード
        │
        └─ セーフスリープ

時系列で示すと,こんな書き方ができるでしょうか.:

(ディスプレイのスリープ)  >  スリープモード  >  スタンバイモード  >  (hibernademode=3)の場合   >  セーフスリープ  >  スリープ前の状態で復帰
(ディスプレイのスリープ)  >  スリープモード  >  スタンバイモード  >  (hibernademode=25)の場合  >  セーフスリープ  >  スリープ前の状態で復帰
(ディスプレイのスリープ)  >  スリープモード  >  スタンバイモード  >  (hibernademode=0)の場合   >  (なし)          >  真っ新で復帰

いかがでしょうか.

hibernatemodeについて説明する時に度々使われる,0はスリープ,3はセーフスリープ,25はディープスリープ,と言った対応とは異なるようです.

そして,
Appleサポートページ上でのセーフスリープは,hibernatemode=3のセーフスリープとは,異なっているように読み取れませんか? それはむしろ25で言うディープスリープとも言えます.
ちなみに,このセーフスリープ.
これが他のスリープモードと異なるのは,スリープからの復帰において《進捗状況バーが表示され》ると言うところ.これをイメージ出来ると,それらとの違いというものが理解し易くなるのではないかと思います.が,いかがなものでしょう笑

Appleさんからの引用.:

https://support.apple.com/library/content/dam/edam/applecare/images/en_US/macos/macos-sierra-mbp-progress-bar-after-deep-sleep.png

と言うことで,
hibernatemode=3とhibernationを行う設定は,スタンバイモードおよびセーフモード,つまりディープスリープで効くものとなっているようです.

そんな話だったのですが,...相変わらずまとめる力ないようで,無駄に長い内容になってしまいました.

まとめるセンスを持ちたいです.
だっめですね.

はい,おしまい.

*1:'pmset'は'enable'のままでも使える様なのですが,'hibernatefile'をリセットする作業で,アクセス権で怒られます.

*2:ちなみにデフォルト値は以下の通りでした.:
  - 'standbydelaylow'='10800'
  - 'standbydelayhigh'='86400'
  - 'highstandbythreshold'='50'

*3:若干対応するモードがずれていたりするものもありますが.

*4:これまでの従来からあった,スリープ(historically, plain old sleep)の仕組み.