2021/02/08(Mon)ヘッドレスLinux GUI環境でVNC描画が遅い

2021/02/08 1:38 Software::Linux
ディスプレイ付きの別環境で環境セットアップしたX環境を、別筐体に載せ変えて完全にヘッドレスの状態でVNCから使おうとしたら、何故かとても動きが遅い……というのを解決したメモ。

なぜ遅い?

物理ハードウェア(ディスプレイ)が無い状態では、fbdev*1が使われるようで*2、アクセラレーションの類が一切効かない。
というわけで、ダミードライバを用いて仮想的なディスプレイが繋がっていることにしてあげると、Xorgがキビキビ動く様になる。

*1 : Linux Framebuffer Device

*2 : /var/log/Xorg.0.logを見ると、driverにそれを選んだというログが残っている

ダミードライバの導入

dnfで一発。簡単。
# dnf install xorg-x11-drv-dummy
でも、これだけではダメで、xorg.confにこれを使うと明示的に書く必要がある。
# vim /etc/X11/xorg.conf
以下サンプル。
Section "Device"
    Identifier "Configured Video Device"
    Driver "dummy"
    VideoRam 256000
EndSection

Section "Monitor"
    Identifier "Configured Monitor"
    HorizSync 5.0-1000.0
    VertRefresh 5.0-200.0
    # 1600x1000 59.87 Hz (CVT 1.60MA) hsync: 62.15 kHz; pclk: 132.25 MHz
    Modeline "1600x1000_60.00"  132.25  1600 1696 1864 2128  1000 1003 1009 1038 -hsync +vsync
EndSection

Section "Screen"
    Identifier "Default Screen"
    Monitor "Configured Monitor"
    Device "Configured Video Device"
    DefaultDepth 24
    SubSection "Display"
        Depth 24
        Modes "1600x1000_60.00"
    EndSubSection
EndSection
ポイントは
  • Device > Driverにdummyを指定する(今回の肝)
  • Device > VideoRamに適当なビデオメモリサイズを指定する(でないと最小メモリでやりくりしようとして、高解像度が利用できない insufficient memory for mode とログに出る)
  • Monitor > HorizSync/VertRefreshはお好みでいいらしい。どうせ物理ハードがないので、関係無いし…
  • Monitor > Modelineはcvtコマンドで生成したお好みの解像度をそのまま記載すると良い
    $ cvt 1600 1000
    # 1600x1000 59.87 Hz (CVT 1.60MA) hsync: 62.15 kHz; pclk: 132.25 MHz
    Modeline "1600x1000_60.00"  132.25  1600 1696 1864 2128  1000 1003 1009 1038 -hsync +vsync
    
  • Screen > Display > Modesは、Monitorセクションに書いた名前で表記すること。Xorgはデフォルトでいくつもモニター定義を持っているが、width too large for virtual sizeとかbad mode clock/interlace/doublescanとか色々な理由で適合しないみたい。
  • Screen > DefaultDepthとScreen > Display > Depthは24でないとダメだった。32だと何故かVNCが繋がらない(あまり深追いしてない)
書けたら、以下のコマンドでXorgを再起動する。
(システム全体を再起動する必要はないよ!物理的にキーボードに触れるならCtrl+Alt+BackSpaceでも良いかも…)
# systemctl restart display-manager
うまくいかなかった場合は、/var/log/Xorg.0.logを開き、エラー行"(EE)"とその前後を確認してみると、検索のヒントになるはず。

x11vncの設定

ちなみにVNCサーバーの設定はこんな風に。
# cat /etc/systemd/system/x11vnc.service
[Unit]
Description=VNC Server for X11
Requires=display-manager.service
After=display-manager.service

[Service]
Type=forking
ExecStart=/usr/bin/x11vnc -norc -forever -shared -bg -rfbauth /root/.vnc/passwd -allow 192.168. -autoport 5900 -o /var/log/x11vnc.log -noxdamage -auth /var/run/lightdm/root/:0 -noxrecord -nowf

[Install]
WantedBy=multi-user.target
x11vncの引数の意味は、
-norc
.x11vncrcファイルを処理しない
-forever
VNCクライアントが接続を切った後に、VNCサーバをシャットダウンしない
-shared
同時に複数のVNC接続を許容する
-bg
デーモンとしてバックグラウンド起動
-rfbauth passwd
RFBプロトコルでVNCクライアントを認証する*3
-allow address1[,address2,[...]]
接続元アドレスを制限
-autoport port
listenポートを指定。被っていたら+1, +2, ...と次番号のポートを使用する(多分だけど-rfbportで固定指定)
-o logfile
ログファイルの指定
-noxdamage
Framebufferの検出にX Damageを使用しない。画面変化に応じた負荷軽減を行うextensionぽいけど、まあLAN内で接続する事が多く、帯域もガンガンつかって構わないので、無効に。
-auth file
X authority fileを指定。/usr/libexec/Xorgに指定された-authと同じ物を指定したらよさげ。
-noxrecord
RECORD extensionを無効化。無効にしないと、VNCクライアント側でスクロールしたときにクラッシュしたので。
-nowf
ワイヤーフレームをオフ。ウィンドウをドラッグしたときに中身をずっと表示していてほしいので。帯域が広ければ問題にならないはず
なんか色々お節介機能としてオフってる気が……でもこうしないと安定しないのは……

*3 : "x11vnc -storepasswd vncpassword file"でpasswdファイルを作る