Mac のスケーリング解像度別 GPU 使用状況を Mackerel で確認する


Mackerel チームで Web アプリケーションエンジニアをやっている inommm です。
この記事は Mackerel Advent Calendar 2022 12月13日の記事になります。



macOS には複数のピクセルを使って1ドットを表現するための機能が備わっています。 高解像度のモニタを使ってなめらかな表示を行うための機能ですが、どの程度スケーリングさせるか調整できるようになっています。

作業領域を増やすためになめらかさを犠牲にしてスケーリング解像度を上げてみたりしたいわけですが、Apple の Web サイト によるとスケーリング解像度を上げていくとパフォーマンス低下が起きるようです。

解像度を調整するとパフォーマンスに影響する場合があります。

(以前は設定画面にも同様の注意書きがでていましたが Ventura では表示されなくなっていました)

実際のところこれがどのくらいパフォーマンスに影響するのか気になったため、解像度別の GPU 使用状況を Mackerel に投稿して確認してみることにしました。

スクリプトを書いて GPU 使用率を Mackerel へ投稿する

macOSGPU 使用率は powermetrics コマンドで取得することができ、現在の解像度の取得には system_profiler コマンドが使えます。 今回は以下のようなスクリプトを用意し、メトリック名に解像度を含めつつ、GPU 使用率を値として送信するようにしています。

#!/usr/bin/env ruby

require "time"
require "mackerel/client"

API_KEY = "******"
@mackerel = Mackerel::Client.new(mackerel_api_key: API_KEY)

def get_gpu_usage
  command = "powermetrics --samplers gpu_power -n1"
  `#{command}`.split("\n")
    .find { |l| l.match(/GPU Busy/) }
    .split(":")
    .last
    .sub(/%/, "")
    .strip
    .to_f
end

def get_current_resolution
  resolution_pattern = /([0-9]+\s+x\s+[0-9]+)/

  base_resolution_command = "system_profiler SPDisplaysDataType |grep 'Resolution'"
  base_resolution = `#{base_resolution_command}`.split(":")
    .last.match(resolution_pattern)[1]
    .gsub(/\s+/, "")

  scaled_resolution_command = "system_profiler SPDisplaysDataType |grep 'UI Looks like'"
  scaled_resolution = `#{scaled_resolution_command}`.split(":")
    .last
    .match(resolution_pattern)[1]
    .gsub(/\s+/, "")

  # base_resolution と scaled_resolution が同じであればモニタネイティブの解像度として扱う
  if base_resolution == scaled_resolution 
    base_resolution
  else
    scaled_resolution + "-scaled"
  end
end

loop do
  service_name = "scaled-resolution-test"
  metrics = [
    {
      "name" => "mbp.gpu.usage.#{get_current_resolution}",
      "time" => Time.now.to_i, "value" => get_gpu_usage
    }
  ]
  pp metrics
  @mackerel.post_service_metrics(service_name, metrics)
  sleep 60
end

このスクリプトを実行し、解像度を変えながら Mackerel へサービスメトリックとして投稿したのが以下のグラフになります。

デフォルトのスケーリング解像度 (1920x1080) から一段回ずつ解像度を上げていくにつれて、GPU の使用率が少しずつ増えていっている様子が分かります。最後に試した 3840x2160 はモニタのネイティブ解像度となり、スケーリングされていないものになるので負荷が最も低くなっています。

スケーリングはどのように実行されているか

スケーリングがどのように macOS 上で実行されているか公式な情報は見つけられませんでしたが、Stack Exchange のこの回答によると、モニタのネイティブ解像度の整数倍にならないスケーリング解像度では一旦倍の解像度で出力してからスケーリングしているようです。

4K (3840x2160) のモニタで 1920x1080 のスケーリング解像度を選択するとそのまま整数スケーリングされますが、2560x1440 のスケーリング解像度を選択すると一旦 5120x2880 で出力してから 2560x1440 へスケーリングされるようです。 余分な解像度で出力する分パフォーマンスが落ちるということでしょうか。

さらにこのブログによると、非整数スケーリングを行った際にはスクロール時のチラつきなどパフォーマンス低下以外にも様々なデメリットが生じるようです。結局この方は整数スケーリングで 3008x1692 のスケーリング解像度を実現できる 6K の Pro Display XDR を購入したようです。。。

最後に

Mackerel ではホスト監視以外のメトリックもサービスメトリックとして投稿することができます。今回のように思いつきでスクリプトを書いてデータ収集する用途で使っても便利なので、ぜひ試してみてください。