最小限の環境を作る「フォントえらび」

私は基本、4台のコンピュータを運用している。これはまんま「3部屋+携行」なのだが、それぞれの最終システムインストール日を見ると

  • ThinStation P720 (2019-01)
  • FM2A88X (2017-12)
  • Z400 Workstation (2019-07)
  • ThinkPad X1 Carbon 5thGen (2018-06)

である。ちなみに、これはjournalctlすれば分かる。

システムセットアップ時に悩ましいのがフォントだ。 ここではManjaroを前提にして語るが、日本語フォント関連のパッケージは“font japanese”で検索すると62ほどあり、うち公式パッケージは源ノ角ゴシック、源ノ明朝、IPAフォント、花園明朝、さざなみフォントである。

フォント関連のAURパッケージはあまりメンテナンスされないことが多く、多くのフォントを維持するのはかなり厳しい。インストール時間もかかるので入れるのもしんどい。 ひとつにまとめて、それを/usr/local/share/fontsなどに入れて運用する方法もあるのだが、商用フォントの除外という手間もあるし、OS側(/usr/share/fonts)との兼ね合いもディストリビューションが違ったりすると特に発生しがちなので割と難しい。

なにより、「フォントの数」と「画面の総ピクセル数」は ものすっごく 反応速度に影響するのだ。遅い遅いと思っていたマシンをまっさらにして1366*768なディスプレイをつないだら爆速になったりしている。 だから、メインマシン(もしくはフォントを使うようなアートワーク作業をするマシン)だけにフォントを積んで、他はessentialに運用したい。

ここでは私の経験に基づいてよいと判断したessentialを紹介するが、好みによることはご了承いただきたい。

先に結論

% trizen -S adobe-source-han-sans-jp-fonts adobe-source-han-serif-jp-fonts ttf-cica ttf-ume
  • 商用フォント顔負けのクオリティで出せる源ノ角ゴシック、源ノ明朝
  • zsh-theme-powerlevel9kpowerlineを入れた場合に必要になるpowerlineシンボルなどまでカバーし、日本語コーディングフォントを必要する場合に有用なCica
  • MS日本語フォントにメトリック互換の梅フォント

という構成である。

好みのちょい足し

もう少し意味を補強すると、IPAフォントがあるとLibreofficeで文書をやりとりするようなケースでは有効である。 IPAフォントは公式パッケージなのでインストールしてもいいかもしれない。

さらにいえば、コーディングフォントは日本語フォントである必要はなかったりする。 私が様々なコーディングフォントで様々なコードや文章を書いた経験で言えば、長時間使っていて快適性が高かったコーディングフォントは

  • Hermit
  • Input Mono
  • Fira Mono
  • Meslo
  • Camingo Code
  • Roboto Mono

だった。

あと、私は個人的にMiguも好きなので、

% trizen -S otf-ipafont ttf-migu otf-hermit

好みのちょい盛り

ひょっとしたらスタイリッシュな欧文フォントがないことが不満かもしれない。 定番としてはSenとかだったと思うのだけれど、今SenはGoogle Fontsから外れてしまった。 Overlockも定番。これは個人的には静凛さんのチャット欄がOverlockなので馴染みがある。

ManjaroのロゴフォントであるComfortaaは最近のManjaroはデフォルトで入っていたりする。

あと、Joseffin Sansも好き。

かっこいいSerifフォントが欲しい、とかいうと特に定番はないので、GoogleでSerifカテゴリを選択して探していただくのがよかろう。 Serifフォントに関しては私は商用のHumanist Slab 712を使っていたりするし。 どうしてもお勧めというのであれば、MartelとかCormorant Garamondとか、Abhaya Libreとかだろうか。

そして個人的には源ノ角ゴシックも良いが、やっぱりモトヤフォントが好きだ。 それにこのラインナップでは丸ゴシックがない。

そこで小杉ゴシック小杉丸ゴシックだ。 小杉ゴシックは元「モトヤ Lシーダ W3等幅」、小杉丸ゴシックは「モトヤ Lマルベリ W3等幅」のリネームである。 これらはApache Lisence 2.0でAndroidに載っていたフォントだ。

好みの盛り盛り

ドキュメントを書く上で使いやすいフォントに欠けるので、源暎フォントを追加している。 ただし、これはドキュメント生成、つまりPandocを使う端末のみ。

あと、本文フォントは「源暎ラテミン」よりも「元陽逆アンチック」のほうが人気があるので、それも入れておく

セットアップ

言葉はいらないよな?

<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
    <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
        <its:translateRule translate="no" selector="/fontconfig/*[not(self::description)]"/>
    </its:rules>

    <description>Re-define sans-serif, serif and monospace.</description>
    <match target="pattern">
        <test qual="any" name="family">
            <string>sans-serif</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Joseffin Sans</string>
            <string>MotoyaLCedar</string>
            <string>Source Han Sans JP</string>
        </edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family">
            <string>serif</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Overlock</string>
            <string>GenEi Koburi Mincho</string>
            <string>Source Han Serif JP</string>
        </edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family">
            <string>monospace</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Hermit</string>
            <string>Cica</string>
            <string>Migu 1M</string>
        </edit>
        -->
    </match>
</fontconfig>
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
    <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
        <its:translateRule translate="no" selector="/fontconfig/*[not(self::description)]"/>
    </its:rules>

    <description>Substitude popular Japanese fonts</description>

    <match target="pattern">
        <test qual="any" name="family">
            <string>MS Pゴシック</string>
        </test>
        <test qual="any" name="family">
            <string>MS PGothic</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Ume P Gothic S5</string>
        </edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family">
            <string>MS P明朝</string>
        </test>
        <test qual="any" name="family">
            <string>MS PMincho</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Ume P Mincho</string>
        </edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family">
            <string>MS明朝</string>
        </test>
        <test qual="any" name="family">
            <string>MS Mincho</string>
        </test>
        <edit binding="strong" name="family" mode="prepend">
            <string>Ume Mincho</string>
        </edit>
    </match>
</fontconfig>

Inflatonにおけるサーバープロビジョニングのおはなし

Inflatonにおけるサーバープロビジョニングに関する質問があったので、記事にしようと思う。

基本的にはこの部分は、私の(=Inflatonの)基本的方針を踏襲したものになっている。 つまり、

  • 一般的である、あるいは流行であるということにはとらわれず
  • Unixの流儀に従い
  • 堅牢で確実なツールと手法で
  • 全ての理解が容易であるように

している。

前提

Inflatonにおいては、一般的ではない前提が成り立っている。

まず、「私が前提になっているということ」である。

つまり、私に属人化することは基本的に問題視されない。 それよりも私の能力が発揮できることが優先されるのでやり方は好きに選べる。

もうひとつは、会社自体が少数精鋭になっているということだ。

これを前提に一般的な手法を避けたりもしていて、「IT業界の人間」が直ちに即戦力になるような状況にない。 戦力になるまで、1年くらいは育てて使う方針になっている。

その間賃金が低いとしても、300万円くらいは利益を出さない人のために使うということである。 しかも、まっさらな状態から1年でちゃんとやれるようになるとしたら、つきっきりで教えなくてはならない。 私だとえらいことになってしまうし、全てを教えられるレベルのエンジニアだと年俸600万円は下らないだろう。

これは「1人増えるのが一大イベント」であるからこそできることで、新卒採用があるような会社ではここまでの方法はとれない。

ここまでの前提を以て、他とは違うInflaton styleを可能にしている。

正しい方法

ConoHaの場合、「スタートアップスクリプト」という機能があり、サーバー構成時にスクリプトを実行させることができる。 cloud-config形式とシェルスクリプト形式をサポートしているという。

ConoHaに限らなければ、Chefなどのツールを使うのが一般的である。

もちろん、これらの方法はInflatonでは採用していない。

我々の方法

基本的に

  • ドキュメントを書く
  • シェルスクリプトを書く

の2点である。

ドキュメントは手順書と言っていいのかはわからないが、基本的に最低限コマンドが打てればこれだけ読んで構築できるレベルの内容になっている。 開発も実務も忙しいのに事業かけもちでドキュメントもちゃんと書いていることについては是非とも褒めまくっていただきたい。

シェルスクリプトのほうは、より正確に表現するならZshバッチになっている。 正直なところ、ドキュメントを読むよりもこちらを読むほうがわかりやすいだろう。

何のために、といったことに関しては、そのサービスを構成するものに関する、内部向け外部向けのドキュメントが存在するため、それを見れば確認できる。

それぞれちゃんとした理由がある。

まず、ドキュメントが揃っている最大の理由は、しばらく触ってないソフトウェアやサービスに関して、私が覚えていられないことと、説明する時間が割けないことだ。

弊社取締役はMimir Yokohamaの生徒さんでもあり、私が書くレベルのドキュメントがあればだいたいは理解できる。 このため、ちゃんとドキュメントがあるだけでも私の負担は確実に減る。そして、ドキュメントがなければ私は開発に戻ってくるのが大変になる。

そして、システム構成に関してはあまり固定化されていない。そもそもコンポーネントの変更をしやすいように設計してあり、サーバー面での変更というのは相当カジュアルに行われている。

もちろん、理由は私が管理しているからであるが、もうひとつの理由としてArch Linuxだからというのもある。 Arch Linuxは普通にバージョンも上がれば、役割を担うソフトウェアが変更されることもある。だから、構築から運用を固定化したところで、固定化したものが自動的に通用しなくなって困るだけなのだ。

ドキュメントに関しては単純に都度アップデートしている形だが、実はシェルスクリプトとドキュメントの2段構成にしている大きな理由として、「サーバー構築手順が次のサーバーで成立する可能性はかなり低い」というのがある。 一番躓くのがパッケージ名の変更である。Archは非常にカジュアルにパッケージ名を変更するので、インストールするパッケージ名の指定がコケる原因になる場合が多い。 加えていえば、サーバーソフトウェアの設定ファイルの項目も、意外と頻繁に変わる。

そこで

  1. ドキュメントで手順を確認
  2. そのパートのバッチスクリプトを実行、あるいはドキュメント記載のコマンドをコピペしながら実行
  3. 躓いた場合は原因を確認し、ドキュメントとスクリプトをアップデート

という形でstep by stepで進めていくと構築できるようになっている。 Inflatonとしてはサーバーを増やすのは年に数えるほどでしかないため、完全自動化するのはメリットよりデメリットのほうが大きい。

サーバーインスタンス増加による増強よりは、新しいことをやるために構成の異なるサーバーを立てる頻度のほうが高い。 だから作業においてコアになることが確定している部分…例えばzsh, grml-zsh-config, zsh-theme-powerlevel9k, screenのインストールと、/etc/zshrc.localの設定などはそれでひとつのスクリプトにまとめられている。 なので、このスクリプトは使い回しが効く。

Inflatonでサーバーを立てるということは、最近始まったばかりなので稀な話だが、「システムの構築」そのものは数え切れないくらいやっている。 今でも何らかの理由でシステムを作ることは年に10回くらいはあるし、15年とか前だと週イチなんてペースだったので、知識と経験があるし、効率化も進んでいる。 結局のところ「最適解を追い求めている以上、ゴージャスな方法で固定するよりは変更しやすい方法のほうがいい」というのが教訓なのだ。

ここには私の信念、及び流儀も絡む。 私は「完璧たりうる」と思っているし、かつ「完璧と動的である」と思っている。だからこそ、「完璧を追い求めることにこそ意味がある」と信じている。 そのためには「動いた状態」で固定することには意味がないし、「動的な最善」であるArch Linuxなのである。

一例としては、現在Plutoのサーバーではsshd_config(5)のCiphers

Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com

である。この設定の主たるところはchacha20-poly1305@openssh.comが外されていることで、外している理由はSSHの処理が比較的重いサービス特性上、サーバー側でAES-NIを使いたいからである。

余談だが、AMDプロセッサはBulldozer以降でAES-NIをサポートしており、IntelはIvy Bridgeまではi3においてAES-NIがサポートされていなかった。 こうしたことを含め、性能の低いデバイスにおいてはAES-NIがなく、計算量の多いAESは重いということになるのだが、コネクションが1本であるクライアントにとっては大した話ではなく、多数のコネクションをさばくサーバー側で軽くすることが優先である。

しかし、この設定ではaes128-ctrが最初に来ており、今後10年で変更されることを意味している。

つまり常に動的に構成され、動的に変更されるのである。 構成時はむしろ構成変更タイミングでもあると言っていい。

手順スクリプトは

pacman -S grml-zsh-config tmux zsh-completions zsh-syntax-highlighting zsh-theme-powerlevel9k zsh-history-substring-search vim vim-plugins rsync
cat > /etc/zshrc.local <<EOF
setopt vi

autoload -U history-search
#zle -N history-beginning-search-backward-end history-search
#zle -N history-beginning-search-forward-end history-search
bindkey "^P" history-beginning-search-backward
bindkey "^N" history-beginning-search-forward
bindkey "\e[5~" history-beginning-search-backward
bindkey "\e[6~" history-beginning-search-forward
bindkey -M viins "\e[5~" history-beginning-search-backward
bindkey -M viins "\e[6~" history-beginning-search-forward
bindkey -M vicmd "\e[5~" history-beginning-search-backward
bindkey -M vicmd "\e[6~" history-beginning-search-forward
...
EOF

みたいな感じで、普通にコマンドラインの手順のバッチと、catを使ったファイル生成から成り立っているのだが、ステップ中で躓いた場合、Vimでd:2してそのステップからやり直すようにすれば良い。 dggでない理由は、「失敗時にそのステップを終了する」ため、先頭で

TRAPZERR() { exit 48 }

としているからだ。

付して述べるなら、「理解していなくても使える」というのはInflatonとしては嬉しいことではなくて、「理解する前提で育てる」方向だから、 「知悉しやすい、教材としても優れたものにしておく」という考え方になってもいる。

プロビジョニングツールを使うことでディストリビューション間の差異を吸収しやすくなるという面はあるが、 ディストリビューション変更をするような場合は、パッケージに含まれるファイルの詳細を把握しなければ潜在的に危険であると考えているので、そのような吸収をしてもらう必要はない。

同様にプロビジョニングツールを使うことで構成することそのものを容易にする面もあるが、そもそも構成が普通でないので、これも全く役に立たない。 例えば私は個人としては2017年までサーバーにDeleGateを使っていたが、DeleGateを構成することなど誰も考えていないし、そこまで極端ではなくとも常に普通にはない構成になっている。 こうしたことから、定番の構成を容易にする機能というのは助けにならず、こうした機能を理由にツールを選択することもない。

サーバーに依存したツールを使うことも、「サーバーの変更」という選択を難しくさせるので、望ましいとは思えない。

Sharhiveって何か

Sharchiveの話をしたら、「それなに」という方がいたので、「あぁ、そうか。思いっきり昔話だもんなぁ」というわけでちょっとSharchiveの話をしよう。

概要

Sharchive (Shell Archive)はアーカイブファイルフォーマットである。filename suffixは.sharで、コマンド名もshar

アーカイブが7bit ASCIIで書かれたshスクリプトになることが特長。展開時はシェルスクリプトとして実行することで展開できる。

「危険ではないのか」という意見に関して答えると、非常に危険である。 純粋なシェルスクリプトであるため、Windowsの自己解凍形式なんかよりはるかに危険である。

背景

Sharは1995年頃まで使われていた。 tarがアーカイブファイルとしてはまだ一般的でない頃に使われていたのだが、アーカイブファイルフォーマットとして主流だったことはない。間違いなくやや特殊なアーカイブだった。

Unixプラットフォーム上ではshがあることは期待できたので、そうした互換性問題を回避するという面はあった。 だが、Sharが使われていた頃であってもtarがないということはそれほどなかった。

Sharが使われた最大の理由はネットニューズである。

ネットニューズを知らない人は多いだろうが、だいたいやりとりの感覚としてはメーリングリストに近い。 そして、当時はMIMEが制定される前で添付ファイルというものはなかった。つまり、データはメール内に書くしかなかった。 なおかつ、まだ8bit目がチェックディジットに使われている時であり、7bit ASCIIでしかメールが書けなかった。

もちろん、この頃でもtarでアーカイブを作り、uuencodeする、という選択肢はあった(Base64という選択肢はまだなかった)。 だが、これだとネットニューズで見ただけでは、それがどのようなソフトウェアなのかということを推定することができない。 Sharchiveであれば、特にスクリプトファイルやソースコードの場合、ネットニューズ上で確認するだけで内容を把握することができる。 メールと違い、uuencodeされたソースを展開するには取り込んでから保存してソースを取り出すという手間があるし、今と違ってX window system前提というわけでもなかったのでコピペが簡単にできたわけでもない。

こうしたことから使われていたのだが、バイナリサイズが大きくなってくると目視は困難だし、効率も悪く、なにより目視確認できないSharchiveは危険極まりない。 これによって、MIME制定以降Sharchiveは使われなくなっていき、やがて全く使われなくなった。

現在

Manjaroの場合sharutilsというパッケージがextraに存在する。

FreeBSD/DragonflyBSDのtarはlibarchiveを使っており、Sharに対応している。--formatオプションやaオプションで作成可能。

もちろん、展開はshでできる。そのため、展開そのものは今も苦労なくできる。

もはや使っている人はいないレベルだと思うのだが、Mimir YokohamaやInflatonでは使う場合がある。 その理由は、コマンドラインツールの利便性や説明の統一を狙って、Git for Windowsをインストールし、Git Bashを使う、という手順で説明することがあるからだ。

サーバー側はLinuxだし、zipでは返しづらい部分もある。こうした理由から手順が統一できるsharを使う…ということをしていたのだが、 現在は「Git for Windowsにtarが入っている」ことに気づいたのでこれも廃止した。

「シェル」と「端末(ターミナル)」の違いと詳細

【超ざっくり解説シリーズ】シェル(Shell)とは?シェルについて初心者にもわかりやすく解説するよというnoteを読み、ちょっと内容がひどかったので、Twitterで言及したものの、ちゃんと説明したほうがよかろうと考えて急遽、この記事を書くことにした。

「シェル」「端末」「端末エミュレータ」「端末デバイス」については、Mimir YokohamaのLinux基礎初級「シェルとコマンドライン」の中でやっている。 この内容をやる時期としてはかなり難しい部類に入り、かつ重要であることから、最近は端末デバイスを直接叩くといったことを含めて2時間以上じっくり取り組むことが多い。

内容自体はそれほど難しくはないと思うのだが、理解に至るには

  • 入出力
  • デバイスと接続
  • カーネルとシステムコール
  • プロセス
  • ファイルディスクリプタ
  • デバイススペシャルファイル

に対する理解が前提となるため、ちゃんと認識できていないと難しいかもしれない。

なお、このあたりはOSによって非常に大きな差異があるところなので、ここではLinuxを前提に説明する。 ここに書かれている内容では理解に至るには足りないと感じられる方は、ぜひMimir Yokohamaの授業を受けてみてほしい。 じっくりと丁寧な説明とハンズオンによって理解できるまでしっかりと授業を行っている。

カーネル

カーネルはCPUの特権モードで動作するプログラムである。

実際に定義としてはそれしかなく、カーネルが実際にどのような仕事を担っているかというのも特に決まってはいない。

とはいえ、カーネルにやってほしい重要なこととして「リソース管理」というものがある。 最近のOSはタイムシェアリングシステムなので物理的な装置数以上のプロセスを起動することができるから、プロセスが好き勝手にリソースを使ってしまうと色々奪い合ってしまうのだ。 一番わかりやすいのは、「ハードディスクのアームをどっち方向にどれだけ動かすか」というモーター制御を奪い合ってしまうという状況ではないだろうか。

というわけでリソース管理をするためにカーネルとしてはプロセス管理をしなければならぬ、ということになる。

だが、カーネルというのは基本的にそういうことをする。 つまり、コンピュータを使う上で必要な環境を整える、コンピュータという舞台を作る、というのがカーネルの仕事だ。 ここが改善されるとそれを使う全てが改善されるため開発にも力が入るというものだ。

端末とコマンドライン

カーネルはプロセスを起動する仕組みを提供し、起動したプロセスを管理してくれるのだが、ここで問題になるのは「どうやってプロセスを起動するか」だ。

Linuxの場合、カーネルロード時にinitというプログラムを実行し、initが色々なプログラムを実行するようになっているのだが、 これでは任意のタイミングで必要なプログラムを実行するという方法がない。 また、プロセスやカーネルにユーザーが対話的にやりとりする方法がない。

いや、実際にそう時代もあったのだ。 コンピュータがパンチカードマシンだった時代、プログラムを実行するというのはパンチカードを差し込んで読み込ませることだった。

だが、タイムシェアリングシステム時代になると、ユーザーとコンピュータは「やりとり」をする必要が生まれた。 それも、できるだけ使いやすく。

ここで使われるようになったのが「テレタイプ」である。

テレタイプというのは通信機能(送受信機能)をもったタイプライタである。 言ってみればモールス信号とFAXの中間みたいな感じで、電話回線を通じて(手動交換機を通じて)ほかのテレタイプの紙に印字できる。

テレタイプ自体は1920年代には存在していたもので、1960年代にコンピュータに接続して使われるようになった。 当時の「最もポピュラーのコンピュータとユーザーが意思疎通するための機械」だったのだ。

ユーザーは、タイプライタ同様にテレタイプでタイピングをする、あるいは予め打ち込んで紙テープに出力したものを読み込ませることでコンピュータに対して意思を伝える。 コンピュータからの出力はテレタイプを通じて紙に印字される。

この仲介をするのがシェルなわけだけれども、この時点ではシェルと呼ぶようなものは必ずしも必須だったわけではなく、単純にテレタイプ・インタープリターのようなものであったし、 それ自体が「OS」と呼ばれることが多かった。

Linuxでも端末のことをテレタイプ(tty)と呼ぶが、実はUnixですらテレタイプは過去のものだった。 1970年代にはビデオディスプレイ端末が登場しており(Unixは1973年に登場)、Unixの端末というと紙テープではなく画面を使うもののイメージが強い。

紙テープから画面になることの違いは、「入出力環境が複数行になる」ということである。 例えばUnixのエディタコマンドとしてex(1)とvi(1)がある。 ex(古くはe, そしてee, ed)はラインエディタであり、一行で入出力ができる。つまり、紙テープに適している。 だが、ビデオディスプレイなら複数行を表示し、それを見ながら編集できる。それがvi(VIsual)なのである。

そして、もうひとつ大きな点として「表示上での削除が可能になる」ということがある。

だから、キーボードから打ったものをそのまま解釈してプロセスを起動する、という方法より「よりよい方法」が登場する。 それが「コマンドライン」である。

コマンドラインは、ユーザーはその意図を「行」に記述することができる。 行単位なので、改行したときがその意思の確定である。

このコマンドラインを快適なインターフェイスとして利用できるようにしたのが「シェル」である。

シェル

コマンドラインの基本的な考え方は前述の通りだが、Unix原初のシェルであるshは

  • 行を編集する機能
  • コマンドラインで複数のプロセスを起動する操作
  • ファイルディスクリプタをファイルに対して再オープンする操作
  • 出力ファイルディスクリプタを別のプロセスの入力ファイルディスクリプタへのパイプにする操作

など様々な機能を搭載した「超高機能インターフェイス」であった。 ユーザーは1行の「コマンドライン」の中で実に様々な操作を行うことができる。

今にすればshなんて貧弱極まりないのだが、当時の感覚からすれば「キーボードから打ったものがそのままコンピュータの動作になる」などというのと比べ信じられないほどいろんなことができ、様々に応用できるスグレモノだったのだ。

これがスグレモノである点として、「プログラムを記述する必要性が下がる」というのがある。 インターフェイスが単にキーボードから打った内容に基づきプロセスを起動するだけであるならば、全ての操作は事前にプログラムを用意しておかなければ行えない。 shは実に様々な操作をsh自身によって提供し、なにより応用が効くようになっていたので、圧倒的にプログラムを書くのではなくコマンドラインを打つことで目的を達成できるようになったのだ。

基本的には、bashであれ、zshであれ、それらの「機能が豊富で便利」という点を強化したにすぎず、基本的には変わらない。 シェル自身もプログラムであり、別に特別なものではない。ただ、「インターフェイスが何もなければ対話的にコンピュータを使うことはできないが、シェルはただ対話的に使えるだけでなく、対話的に 便利に 使えるインターフェイスだ」というだけの話である。

カーネルに対して特別にくっついているわけではないし、Linuxシェルはユーザースペースで動作し、別にシステムコールを直に叩くわけではなく汎用性のあるライブラリ(例えばglibc)をロードし、実行する「対話的プログラム」でしかない。

ただ重要な点がある。シェルが登場したとき、コンピュータとやりとりするための機械はテレタイプ、あるいはビデオディスプレイ端末であった、ということだ。

Unixはそれがどちらであっても、あるいはどこのメーカーのテレタイプであっても抽象的に扱えるように「デバイスファイル」という仕組みによって扱うようになっている。 そのため、「端末デバイス」という抽象化したレベルで取り扱うことができ、この端末デバイスは、テレタイプのような一行のものなのか、あるいはビデオディスプレイ端末のような複数行のものなのか、という情報と合わせて取り扱うことができる。

現在は端末デバイスではなく、ビデオデバイスを通じて出力し、キーボードを通じて入力するのが普通だ。 これは一般的には「X Server→ビデオデバイス(カーネルインターフェイス)→ビデオドライバ(カーネル)→ビデオカード(ハードウェア)」の構成であるが、シェルは依然として端末デバイスを必要とする。 普通、シェルは直接にX Server、あるいはビデオデバイスを扱う機能はもたされておらず、あくまでも端末デバイスを使って入出力を行うようになっている。

端末、仮想端末

だが、現在本当に端末に繋がっているコンピュータなんてまずないので、物理的に端末を意味する端末デバイスファイルが用意できない。

そこで、実際には端末はなくても、端末デバイスとして扱える仮想端末デバイスと、コマンドラインの入出力に適した仮想端末ソフトウェアが使用される。

「テキストモード」においては、「仮想コンソール」と呼ばれることが多いプログラムを使用する。 このプログラムは、ビデオデバイスによってテキストビデオモードを設定すると共に、(テキストビデオモードの)ビデオデバイスを通じた画面出力と、キーボード入力の処理機能、 そして仮想端末デバイスの提供(Linuxでは/dev/tty*)を行う。 その上でシェルを起動すれば、シェルは/dev/tty?を端末として扱うことができるわけだ。

ターミナルエミュレータは単なるX client(あるいはWaylandクライアント)である。 つまり、グラフィカルアプリなのだが、これはこれで仮想端末を提供する。Linuxでは/dev/pts/*である。 やはり、この上でシェルを起動すれば、シェルは/dev/pts/?を端末として扱うことができる。

だから、例えば

% ls -l /proc/$$/fd/0
lrwx------ 1 haruka haruka 64  6月  1 00:19 /proc/2835/fd/0 -> /dev/pts/0

ということである。

なお、端末エミュレータはキーボードを処理しない。X serverから受け取ったキー入力を仮想端末デバイスを通じて入力するようになっている。 だから、「シェルの標準入力はデフォルトでキーボードに繋がっている」というのは嘘で、対話的シェルは入出力ともに端末デバイスに繋がっている。 仮想コンソールの場合、シェル→端末デバイス→仮想コンソール→キーボードと間接的につながっているのだが、ターミナルエミュレータの場合は全く繋がっていない。

ちなみに、「端末」といえば、DECのVT-100である。 1978年にリリースされたビデオディスプレイ端末で、まぁとにかく売れに売れて、端末といえばVT-100というレベルだった。

だから、VT-100の仕様が一般的で、VT-100と互換仕様の端末も出たし、仮想端末もだいたいVT-100と互換になっていたりする(そして、その設定がある)。

そして、もうひとつ。

xtermは、それを端末として扱うための色々なものを、自前でもっていたりする。

【Manjaro/Arch Linux注意】Yaourtは廃止になりました

すごくニュースだと思うんだけれど、全然話題になっていないけれど。

AURヘルパーである YaourtはAURからなくなりました

もう随分長いこと「非推奨」とされてきたのだけれど、ついになくなった、というかたち。

AURヘルパーの中ではYaourtが最も親しまれてきたし、最も有名だった。 「Yaourtを使う」というのが当たり前になってもいた。

けれど、近年はセキュリティ上の問題があり、メンテナンスされていないことからobsolateになっていた。 で、今ついにAURからなくなった、ということ。

これに伴って、CommunityパッケージになっていたManjaroでもYaourtは廃止に。

今後はyayなり、Trizenなりを使っていくことになる。

そのうち「Yaourtを野良ビルドして使う」みたいな記事が出てきそうだけれども、 危険なのでやめましょう

Archwikiでは2019-05-20現在、日本語版はそのままであるものの、英語版はYaourtに関する記述自体が削除されている。

カスタムキャストでキャストデータを移行する

アプリとしての出来が悪いままのカスタムキャスト

ドワンゴのVTuber戦略は相当不調らしい。 まぁ、「当然だな」という越えがおおかったりもするのだが、登場当初は非常によく遊ばれ、期待も大きかったカスタムキャストがいまひとつ普及していないのも、その現れなのかもしれない。

カスタムキャストは元はアダルトゲームのカスタムメイドがベースになっている。 あれは、エディット機能自体は優秀なものの、DMM版含め出来がよくないという評判がもっぱらなので、必然なのかもしれない。 ありとあらゆる面でいまひとつであり、そのひとつとして「引き継ぎ機能がない」というのが挙げられていた。

やがて引き継ぎ機能が実装されたのだが、著しい「コレジャナイ感」が漂っている。

ほとんどの人は引き継ぎたいのはキャストデータだと思うのだが、キャストデータは対象外、というか引き継げるデータはほとんどない。 キャストデータを作るのは結構時間もかかるし、再現するのは困難なので、キャストデータが引き継げないとそもそも使い物にならないと思うのだが。

データをコピーすればOK

説明にある通り、キャストデータは端末に保存されている。 保存場所はAndroid/data/jp.customcast.cc2/以下である。つまり、このフォルダ以下をコピーすれば良い。 幸いにも現在データチェックは甘く、キャストデータをピンポイントに上書きしなくても、必要なデータを再ダウンロードする形で通してくれる。

ただ、私が試した限りだとgvfs MTPの制限なのか、このフォルダ以下にコピーすること自体ができなかった。 ただし、ファイルの作成や上書きはできるため、

のようなシェルスクリプト(これはサブフォルダ用)で処理できた。 これ以上深いディレクトリの中身は放置して良いし、cache以下は気にしなくて良い。

Windowsユーザーはどうすればいいか、という話は私が取り扱うべき話ではないから、 このフォルダをコピーすればいいよ、という情報を元にがんばっていただく方向で。

論理的思考力 初歩

授業や講座でも人気の論理的思考力のおはなし。最近だいぶアップデートされたので、これをChienomiでも紹介することとする。

論理とは

周辺事情から間接的に事象を確定する(観測する)ことである。

論理は“真”または“偽”で表す。成り立つものが“真”、成り立たないものが“偽”である。 「部分的に成り立つ」ということはない。成り立たないこともあるのであれば成り立つことが証明できていないからだ。 偽であることは「必ずそうでない」ことを証明するのではなく、「必ずしもそうはならない」ことを証明するものである。

よって、物事は圧倒的に偽になる可能性が高く、真であることとは本質的に同一または包括関係であることが多い。 真であるとする証明が正しくないことを証明するためには、わずか一例でも成り立たない例を示せばよい。

論理は因果関係である。「Aであるならば、Bである」というものだ。 AとB(因果)を逆にしたものを「逆」という。 つまり、「BであるならばAである」ということだ。

逆は必ずしも成り立つとは限らない。特に、AがBを包括するとき、AであるときBは十分条件を満たすため真になるが、BはAの一部でしかないためBであってもAでない場合というのが存在することになる。 もし、AとBが同一であれば逆も真となる。

AとBが共に否定関係にあるものを「裏」という。 つまり、「Aでないならば、Bではない」というものだ。

これが成り立つためには、AがBにとっての必要条件である必要がある。 AがなくてもBを満たす方法があれば裏は成り立たない。 そして、「裏が成り立つ」と「AはBにとっての必要条件である」は等しい。

なお、論理的に言う「否定」とは「論理反転」を意味する。だから、「〜ない」を否定すると「〜である」になる。

「逆」と「裏」の両方にあたるものを「対偶」という。 「Bでないとき、Aではない」である。

対偶はあまり使わない。意味としては裏を逆にしたものであり、BがAの必要条件であることを意味する。 裏も対偶も真であるのに逆は偽である、というケースはだいぶ稀だ。 互いが必要条件であるならば、両者は密接な関係にあると考えて良いからだ。 ただし、必須の包括状態にある場合には、逆だけが偽になることもある。

これは高校数学でやるのだが、高校では数学をやらないケースもあるため、知らない人もいるだろう。 私も数学ではやっていない。

余談だが、「逆に言う」「裏を返す」は、まんま論理学的用語であるため、ちゃんと逆ないし裏になっていないと、私としては教養のない人だなぁ、という感想を抱く。

論理の初歩にナンプレを

ナンプレ(ナンバープレース)というパズルがある。

かなりメジャーなもので、やったことのある人も多いだろう。 一時期、Nintendo DSがリリースされたブームになったりもした。

ルールはシンプルだ。9×9の81マスがあり、各マスには1から9の数字が入る。 ただし、制約があり、縦列、横列、及び3×3で区切られた中には重複する数字を入れてはいけない。

ルールは以上だ。

このルールの時点で論理的に解法を求められる。 ちなみにもナンプレの攻略テクニックとしてこれ以外の方法があったりするのだが、ここはあくまで普通に論理的に解くこととする。

空行の候補は1から9の数字である。 これは、ルールによって定義されており、直接的に表現されている。

そして、ルールから「縦列、横列、または区画において出現している数字は除外できる」ということが導ける。 これら出現している数字をあてはめた場合、ルールに反することになるからだ。

ごく簡単なナンプレ問題では、このように除外することで候補がひとつしか残らないマスが出現する。 マスには数字を入れなければならないため、候補がひとつになった時点でそのマスの値は確定する。 このように順次確定することでマスを埋めることができる。

そのマスだけを見たとき、直接定義されているのは「1から9の数字が入る」ということだけだ。 だが、周辺事情によってそのマスの値は確定することができる。 それが確定するのは、そのマスの値が残された候補でないとき、そのパズルのマスを埋めることができない、という命題が真になるからだ。 よって、そのマスは最後に残された候補の値にならざるを得ない。

これは、「周辺事情によって他の可能性が消去される例」である。

もう少し難しいナンプレ問題だと、複数の候補が残る。 この場合、そのマスに値を入れるとその影響によって候補が残らないマスというのが発生する。

だが、そのマスの正しい値というのはわからない。候補1になるマスは存在しない状態だ。 しかし、いずれかの候補値を仮定すると、結果的に他のマスの値が確定することになる。

このとき、マスが「答を入れることができない」状態になることがある。残される候補が0になるのだ。 これはつまり、仮定した値が間違いであることがわかる。よって、仮定したマスの候補から除外できる。

これは、「Aの値がXであるとき、ゲームBはクリアできなくなる」が真になるため、「Aの値はXではない」が成立するのである。

このように問題を一旦仮定することで、成立しなければ除外するということができる。 これもまた、「周辺事情によって偽であること良いが明らかになる例」である。 先に述べたように「AであるときBではない」の裏「AでないときBである」が成立するわけではないことに注意してほしい。 例え仮定した結果成立したとしても、それによって真であることが証明されるわけではないのだ。

実際、ナンプレでも複数の値によって仮定しても確定する値が矛盾をきたさないこともある。 実のところ、ナンプレの場合は基本的には最終的には埋められる値は1つしかない。もっとも、数多い空きマスの全マスに対して仮定を適用するのは、人間にはちょっと無理だが。 だが、現実にはそうでない場合も少なくない。想定すべき全体像がわかっているとは限らないからである。 そのため、例え直ちに矛盾をきたさないことが、その仮定が正しいことを証明するわけではない―ただし、正しいのではないか、という推測は成り立つ。

パズルと論理

ナンプレに限らず、パズルではこのような論理性を持った論理パズルが多い。 クロスワードのような潜在的に特殊な論理性を要求するものを割と珍しい。もっとも、ビデオゲーム用のパズルは全く別だが。

このような最も基本的な論理の適用方法は消去法である。 まず現在の状態から採りうる候補を列挙し、状態の変化に合わせて消去していく。 回りくどい方法だが、「こうだからきっとこうだ」などと推測するよりはずっと正確だ。

ボードゲームも、総当りすることができるのであれば、このような論理ゲームとして成立する。 実際、マルバツゲーム程度であれば論理ゲームとして成り立つ。 ただし、実際はそれが不可能であるため、別の方法をとることになる。

「らしさ」と論理

ナンプレにおいては明確に制限された規則によって論理を求めることができた。 だが、実際にはそのような状況を設定することができないことのほうが多い。そこで、逆に規則のほうを設定して、「論理が成立する条件」を求めるという手法もある。

規則は前提条件である。命題自体には含まれていなくても、その命題が設定される時点で常に適用されるものになる。 例えば、ナンプレであれば、「ナンプレのルールにおいて」という規則がある。そして、ナンプレのルールという形で様々な条件が設定されている。

規則がまるで導入されていない状態で成り立つ論理というのは「真理」だが、これはかなり限定的であり役に立たない。 (さらにいえば、真理ですらも最低限、「この宇宙における法則において」という規則が導入されている)。 そこで、有益な論理を導出するために必要な規則を探すのである。

やってみればわかるのだが、規則が限定的になればなるほど論理を成立させるのはたやすくなる。 だが、実際には「規則は適切に限定されていなければならない」のである。これは、必要以上に限定的な規則では有益ではない、ということだ。 ちなみに、導入した規則の存在を忘れてより一般性がある論理であるかのように言うのは愚か者である。

基本的には成り立たない論理というのは、それが当てはまる場合と当てはまらない場合の両方が存在するわけだが、規則のほうを限定していけばいずれ成り立つ。だが、その場合、「命題が何かを証明しているわけではなく、規則によって結果が必然的である」ということもあり、このような場合は有益ではない。

有益な論理というのは、「規則、命題ともに適切に限定されており、同じことを指してより限定的である以外に成り立たせる方法がない」というものである。 そして、論理の追求とは発見している論理や規則を、これに限りなく近づけることである。

論理では確定的事象を扱うため、確率の話は基本的にはしない。 だが、観測においては「確からしさ」というものを取り扱う。これは、確率の話である。

勘違いされがちだが、確率というのは「割合」とは違う。観測された事象のうちN%が該当するから事象の成立する確率はN%である…というほど単純な話ではないのだ。 (もちろん、この物言いがやや統計学に喧嘩を売るものであることはわかっているが、確率が統計だけのものだと思ってもらっては困る)

それが真である確率を強調していうのに、語義は同じだが「蓋然性」という言葉を使うことが多い。 「真である確率」とは基本的には「真にならざるを得ない条件」の蓄積である。

例えば、「地球には雨が降る」という事象の蓋然性について考えるとき、まず地球圏に(十分な量の)水分が存在することに着目する。 そして、地球圏の温度が均一たり得ないことを踏まえて考えると、その水分は偏りを持って移動すると考えられる。

この時点で「地球には雨が降る」を偽たらしめるのは、水分が大気中に混ざったまま浮遊していられる量である場合や、地球上に雨となりうる温度条件が存在しない場合などだ。 気象の話を本格的にし始めると多くの読者を置き去りにしてしまうのでイメージの話にとどめておくが、これら「偽の可能性」はいずれも否定しうる。

結果として、「地球上には雨が降る条件が揃っている」「地球上で雨が降らない条件は満たすことができない」ことから「地球には雨が降る」を真とみなすことができる。

しかし、物事によっては「これ以上偽たらしめる条件がない」ことを確定できない場合がある。 あるいは、偽たらしめる命題が偽であることを証明できない場合もある。 これらの不確定部分を「確かであること」から差し引いたのが、事象の確からしさ、ということになる。

なお、この節は非常に短絡的に述べているのはわかっているし、それはブログとして書けるものの制約によるものなので、論理学・天文学・量子力学・統計学・気象学できる系諸兄にはお見逃しいただきたい。

予測可能性

事象は連続する、という自然な感覚がある。 これは、自然においてそうなっているからなのだが、感覚的にはそれを拡張して捉えようとする。

これは理系文系の違いであると言われることもあるが、基本的には法則性・規則性が強いほうが予見できる、というのは事実だ。 というよりも、法則性・規則性がないものは予見できない。

このようなものを我々が強く意識するのは命名規則においてだ。 例えばメソッド名にaddElement, delElement, editElementがあったとする。 この状態でaddGroupが登場すれば、きっとdelGroupeditGroupがあるに違いないと考える。 もちろんそうであるべきで、いきなりgroupDelchangeGroupValueなんてメソッドを導入すべきではない。

似たような話だと、Unix系ユーザーアカウント操作コマンドがある。 useradd, userdel, usermodは一連のコマンドなのだが、これとは別にadduser, deluserというコマンドもある。 これらは全く別の体系にあるコマンドであり、useraddusermodとはコマンド形式からして違う。

ところが、これだけ提示されるとmoduserがある、と予見してしまう。 実際にはなく、vipwを使うのが基本であった。ところが、いくつかのLinuxディストリビューションは、adduser及びdeluserを採用した上で、usermodだけを導入する、ということをしてしまった。これだと、「変更コマンドだけ語順が逆、しかも書き方も全く違う」という事態であり、大変な混乱をもたらす。実際、これによって混乱しになっていた。ている人は多かったし、LPICでも結構な間違いポイントになっていた。

コマンド関係で言うと、serviceコマンドは引数が「サービス アクション」の順なのだが、systemctlコマンドは「アクション ユニット」の順で、このあたりも予見可能性を低下させている。

このような予見は非常に強く働く。あるワードが登場した時点で、例え法則性を提示されなくても、法則性があるのではないかと考えてそれを探す、という行動は極めてよく見られるし、検索語句としてもよく現れる。 このことから、「人は非常に強く物事に法則性を見出そうとするし、予見可能性が低いものを非常に嫌う」ことがわかる。

もうひとつよくある話だと、+=演算子の話がある。

A = A + Bを表すのにA += Bと書けるのだが、四則演算は減算(-), 乗算(*), 除算(/)もあるから、-=, *=, /=があると考えるのが自然であり、多くの人はそのように予見する。 そして、そうなっている言語も多い。

だが、実はそうなっていない言語というのも結構ある。 例えばzshは+=しかない。

この理由は、そもそもzshは四則演算がArithmetic evalutionの中でしか行われず、裸で演算子を書くことができないからだ。 そして、+=は配列に対するpostpendとしてのみ書くことができ、-=は文意が不明瞭になるため実装されていない。 実際、Arithmetic evalutionを使って(( A += 10 ))のような書くことはできる。

+=を四則演算以外に適用できるようにするケースも多い。少なくとも文字列の追加には使えることが多いし、配列の追加にも使えることが多い。 Rubyでは+メソッドが定義されてさえいれば、A += BA = A + Bとして評価させることができる。(ただし、例によってAは一度しか評価されないので同一ではない)

そのため、+=は汎用的に使える、と予見しがちである。しかし、Perlでは+=は数値演算以外に使うことができない。 そもそもPerlでは+演算子事態が数値演算に限定されており、文字列連結は.演算子を使う。 Perlは最近の大抵の言語よりも古い言語なので、Perlに責任はないのだが、今は一般に+=を一般化して使うことができるようになっているため、Perlよりも新しい言語から学び始めた人はPerlの挙動に予見可能性が低いと腹を立てることになる。

さらにいえば、+=は非常にメジャーな演算子であるため、JavaScriptに+=演算子がないことを腹立たしく思う場合もある―私はとても思うのだが、検索してもあまりそのような意見は見ないので、ひょっとしたらマイナーな意見なのかもしれない。

この予見可能性は基本的に「その人の中で成立しているように感じている論理」に基づいている。 法則性というのは観測の限りであり、別にそうなるものだという証明がなされているわけではない。だが、見出した法則性というのはその人の中では成立している論理と等しく、これに反するものは非常に強く裏切られたように感じられる。

設計におけるユーザビリティとしては予見可能性を高く保つことは何よりも優先される。 これは、APIであろうが、UIであろうが、挙動であろうが全てに言える。 予見可能性の低いUXというのは、例えばゲームで爽快感の低い操作を強いられて、ようやく動きが出てきて操作に追従するようになってきたと感じた途端に長いロードが入る、というのを繰り返すような不快さを提供することになるのだ。

そして、予見可能性を高めるということは、その枠組みの中で成立する論理を提供する、ということでもある。 例えばvipwは古くからあるコマンドだが、これは/etc/passwdファイルに変更を加える。これはユーザー情報のファイルであり、であれば/etc/groupを編集するvigrがあるはずだ…と予見する。特に、後に/etc/sudoersを編集するvisudoが追加されたことから、vi$targetという法則性を見出すことができるようになったという点も大きい。 vigrはかなり長いこと存在しなかったが、やがて追加された。これは、「ユーザーアカウントに関する編集を行うコマンドはvi$targetである」という論理性を創造した、ということになる。

自分でコントロールできる範囲であればより積極的にそうすべきである。 例えば、parmas[user]パラメータがparams[user][name]のように連想配列として提供されるのであれば、params[group]のようなパラメータが例え項目がひとつしかないとしても、params[group]によって値を返すのではなく、params[group][name]のようにすべきであるる なぜならば、そのようにすることでparams[$type][$term]が予測できるようになるからだ。 良い名前は名前だけでそれが何に属するどのようなものかを推理する余地を与える。

論理的思考

「世に論理的思考と呼ばれているものは論理とは関係ない」とよく言われるのだが、ここではちゃんと論理に基づく思考を指して論理的思考としたいと思う。

論理的思考とは「AのときBたりうるか」に基づいて判断することである、と言ってよかろうと思う。 この思考が究極まで至ることができるならば、全てを知ることができるのだが、残念ながら観測を含めそうはならない。 そして、基本的には(思考停止しない限り)時間があれば論理的思考量は増やすことができるので、時間に対してこの検討がどれだけできるか、というのが論理的思考力、ということになる。

論理的思考において、既知の箇所はスキップすることができる(もし、既知であるという判断が間違っていたとしてもスキップしてしまうのだが)ため、論理的思考力によって論理的思考量が一律に決まるわけではない。 例えば将棋やチェスにおいては、必ずしも論理的思考力に優れる者が勝利するわけではなく、定石などを知っていればある程度確定した状態からスタートできるので、大きなアドバンテージを築くことができる。

また、将棋やチェスなどにおいては基本的に時間制限があり、考えうることを全て考えて指すことができるわけでもない。 このため、単純な論理的思考力によって決着がつくわけでもなく、思考経路によって大幅に左右される。 いい経路を選択すれば論理的思考量に対して得られる結果がよりよくなる。だから、現実にはよい経路を選択できる勘のようなものも非常に重要になってくる。

論理的思考において重要なのは「期待しない」ことである。 人はなにかに期待すると、そうではない結果を否定したい、というバイアスが働く。だから、論理を歪めたがる。 「情報は情報であり、事実は事実であり、論理は論理である」ということを見失わないことが大切だ。論理に血が通う必要などない。そんなものは、言動において通わせれば良いのであって、論理を歪めるために使うものではない。

また、論理の正しさを肯定しないというのは、自分の都合の良いように事実を肯定歪めようとすることである、ということも覚えておいたほうがいいだろう。

Chienomiは結論を提供しない

Chienomiに限らず、私が書く文章において結論は提供しない、というのは私の信条である。

なぜならば、人が思考する上で有益なのは情報であって結論ではない。 情報さえあれば、人はその論理的思考力と価値観によって結論を出すこともできる。

結論が声高な文章は不快なノイズである。 もちろん、経験に導かれる結論はあってもよいのだが、そこに一般性があるとするのはノイズ以上のなにかにはなりえないだろう。 これは、当人がいかなる結論を得たか、ということとは異なる。それは単なる情報であり、意味のあるものだからだ。

そして、私の書く文章は、何らかの特定の結論に達することを期待しているわけでもない。 なぜならば、私自身が特定の結論を持っているわけではなく、あくまでその時々の判断と判断材料にあるに過ぎないから、「この文章はこういうことを結論としているのだ」と感じ取ってしまっているのであれば、それは全くあなたの気のせいである。それは、もしかしたら現代教育の被害なのかもしれないが。

文面からしか文意を導けないのは、論理的思考力の欠如だろう。 私は何かを書くときには論理的完全性にはかなり気を使っているつもりなので、あなたの論理的思考力を活用すれば、より多くの情報が得られるはずだ。 もっとも、それが有益かどうかについては保証できるものではないが。

Linuxデスクトップ環境の比較

Linuxデスクトップ(Unix系デスクトップ環境)の使い心地というのは使いこんでみないとコメントもできないものなのだが、なかなかその特性を理解するまでそれぞれを使い込むのも難しい。 特にまだLinux歴の浅い方はどれを選んで良いのかわからないこともあるだろう。

そこで現行のデスクトップ環境からメジャーなものについて、私が感じる良い点、悪い点をまとめてみた。 あくまで私の視点なので、異なる意見もあるだろうが、そこはあくまで1ユーザーの意見とご了承願いたい。

また、MATE, Deepin’, Pntheon, Budgie, Lumina, LXDE, LXQtなどの他のデスクトップ環境、あるいはEnlihgtenment, fvwm, i3, awesomeなどの他のウィンドウマネージャがあることは承知しているが、私が普段使っていないのでコメントするレベルにはないことも、併せてご了承願いたい。

GNOME

良い点

  • Waylandに最も良好なフィーリングを見せる
  • スクリーンショットツールがとても使いやすい (ただし設定はgsettingsコマンド)
  • ウィンドウボーダーのデザインが豊富で、良いものが多い
  • ランチャーがコマンド実行になっており、検索前提のアクティビティ機能と相性がいい
  • Gnome Keyringは様々なキーをいい感じに管理してくれて使いやすい

悪い点

  • 設定の大部分が隠されており、テーマ設定などの基本的な設定もできない。また、壁紙もコマンドを打たない限り$XDG_PICTURES_DIR直下の画像ファイルに固定されている
  • ウィンドウタイリングが左右にしかできない
  • ウィンドウフィッティングが弱く、表には設定もない
  • Nautilusで右クリックにおけるアクションメニューが簡単に設定できるようになっていない
  • Alt+マウスドラッグによるウィンドウ操作ができない
  • メニューが非常にわかりづらく、メニューが少なすぎて必要な機能を満たさない
  • 「1画面しかなくて、1画面に1アプリしか表示しない」が基本なので、ウィンドウはクローズボタンしかない
  • アクティビティ機能はプログラムをカテゴリ分けしてくれないので、探すのが非常に辛い
  • ウィンドウスイッチャがなく、常にアクティビティから切り替えるかタスクスイッチャから切り替えることを求められる。カレントウィンドウのメニューは表示されるが、マルチディスプレイの場合はプライマリディスプレイ以外無視される 
  • 設定がホームディレクトリ以下になく、バックアップしづらい

捕捉

私はGNOMEが好きではないので、すごく否定的な意見であると考えてもらっていい。 「Linuxなら出来て当たり前だったことをわざわざできなくしている」ことに私は好感を持てない。

Gnomeアプリケーションにはいくらか魅力的なものもあるけれど、デスクトップコンピュータ、とくにマルチヘッドディスプレイや、大画面で使うのに適したものだとはとても思えない。

Gnomeはパソコンよりもタッチデバイスを優先しているのだと感じるし、パソコンもせいぜいが今風なラップトップのみを想定しているといったところだろう。 そして、様々な機能を要求に応じて使いこなす努力するユーザーではなく、機能を使う気がなく、機能を与えてほしくないルーザーのみに親切、という印象である。

ただ、それは解消不能な一部の問題(例えばウィンドウタイリングやAltマウスイベント)を除けばgconfなどによって解消することができ、 およそ「Windowsでレジストリをいじる」のと同じレベルで操作することにより、ユーザーによっては満足できるものに仕上げることもできるだろう。

Cinnamon

良い点

  • 非常に使いやすいウィンドウタイリング。 Super+カーソルで「現在の状態を基準にカーソル方向へタイルする」という挙動。また、タイルした状態でリサイズもできる
  • ウィンドウタイリングしたあとウィンドウを移動すると元のサイズに戻すようになっている。これは、タイル状態でリサイズした場合も同様で、タイルにウィンドウサイズのステートが影響されない
  • 軽い。 ハードウェアアクセラレーションが効くためXFceと比べても格段に軽い
  • ウィンドウフィッティングが設定可能で、かなり使いやすい。タイルしたウィンドウに対してもフィットするため大量のウィンドウを並べるのも楽
  • Alt+左ドラッグ(move), Alt+中クリック(windows menu), Alt+右ドラッグ(resize)全てに対応している
  • 設定項目はやや少ないが、必要なポイントは抑えていて「ほどよい曖昧さ」になっている。設定が大変ではなく、かつ必要な設定はできる傾向がかなり強い
  • Gnomeのメリットだったスクリーンショットと鍵管理はGnomeと同じものを使用しており、同じメリットが得られる
  • Nemoアクションがiniファイルになっていて、結構書きやすい (ただ、現在ちょっとバグってもいる)
  • ウィンドウラベルのマウススクロールに対して細かな設定が効く。アルファ設定も可能
  • Nemoが単独で動作し、軽いファイルマネージャでありながら、gvfsによるマウントにも対応していて使いやすい
  • Alt+F1でワークスペース選択になるのが便利。数字キーで選択できる
  • マルチヘッドディスプレイでフルスクリーンにしているとき、パネルは「パネルがある画面上でフォーカスされているのが他のウィンドウであるときのみ表示する」という理想的な振舞い。フォーカスウィンドウはフルスクリーンウィンドウより前にくる
  • 選べるデスクトップアニメーション
  • 純粋なコマンドラインのランチャと、検索可能なメニューの組み合わせ
  • 左右へのパネル配置に比較的強い
  • 合理的な「フォントはDPIではなく倍率で設定させる」
  • DPのプラグアンドプレイ問題で「復帰できない変更をされる問題」が比較的少ない
  • ボリュームアプレットがマイクのミュートコントロール、デバイス選択、プレイヤーコントロールまでできる便利設計
  • フォント設定機能がフォント数が増えても軽く、使いやすい
  • ファイルダイアログが未選択状態でキータイプを始めると直接パス入力できる仕様
  • Conkyの表示が一番安定している
  • ウィンドウスイッチャからQで直接ウィンドウクローズが可能

悪い点

  • 通知を1件ずつ表示するため、大量の通知がある場合いつまでクリックしても終わらなくなる
  • 通知の有効期限をスクリーン上ではなく通知エリア上の時間として扱う。これは、恐らく正しくない
  • 壁紙がウィンドウごとではなく共通である。設定が楽、ディスプレイ認識でおかしなことにならないというメリットはあるが、残念には感じられる
  • ウィンドウデコレータがMetacityベースでデザインがあまりよくない
  • アプレット機能があるものの、動作しないものが多く、ほとんど役に立たない
  • 起動がやや遅い

捕捉

基本的に「すごくいいバランスで、うまい具合に作られている」のがCinnamon。 機能豊富というわけではないのだが、GNOMEやKDE Plasmaのように主張をぶつけてくる感じではなく、「どうあるのが自然か」「どうなっていれば使いやすいか」ということに向き合って作られている感じがする。 (ただ、Cinnamonはissue reportに対して割と対応は冷たいのだが)

ほとんどの場合要求を満たすことができ、完全ではないが不満というほどではないという状態を作るのがうまい。 至らないところもあるが、使い勝手なら最高だと思う。私は何に移ってもCinnamonに戻ってきてしまう。

ややいまいちだったウィンドウスイッチャは、Windows7以降と同様のアイコンスタイルのものが導入されて使いやすくなった。 グループに対してはホバー時だけでなくクリック時にウィンドウリストを表示する機能もあるが、これはまだbuggyである。 垂直表示を有効にしていると、ウィンドウグループを縦に表示し、さらにそのウィンドウから派生したウィンドウは水平に表示するという器用さを見せる。 懸案だった「.desktopファイルに書かれている情報を使ってくれない」という問題も解消してくれている。

ClutterとNemoの出来の良さが圧倒的で、総じて非常に使いやすい。派手な機能はないが極めて実用的だ。 Cinnamonの欠点を探してみたのだが、これといってあまり見つからなかった。以前はいくつかあったのだが。それが戻ってきてしまう理由かもしれない。

KDE Plasma

良い点

  • 非常に充実したアプリケーション群でクオリティも高い
  • 非常に充実した設定項目。特に電源管理が優れている
  • KIM Panelが格段に使いやすく、Fcitxのウィンドウも統合されていて入力が快適
  • Alt+マウスドラッグによる操作をカスタマイズできる
  • デザインが良い
  • KDEパネルは機能が多彩で、ウィジットも強力
  • 0.1倍単位のUIスケーリング。Gtkアプリケーションにも対応する
  • 検索のみではあるもののランチャもメニューも強力な検索で使いやすい
  • KDE Walletはウェブブラウザのパスワードを一括して管理してくれるので安心感がある
  • 設定ファイルが素直にホームディレクトリ以下にあるためバックアップしやすい
  • Qtの利点を活かした非常にスムーズなスクロール
  • ディスプレイ接続時のアクションが良好で、プレゼンなどでプロジェクターを使うときにも使いやすい
  • ディスプレイを「重ねて配置」できる
  • ウィンドウフィッティングが非常に素晴らしく、ピタッとウィンドウを並べることができる
  • フォントレンダリングに手が入っているのか、ちょっと綺麗
  • 通知の扱い方が適切で使いやすい

悪い点

  • やや不安定
  • サイズの異なるディスプレイを並べると、ディスプレイ位置がおかしくなったり、パネルを失ったり、壁紙を失ったりする
  • ディスプレイの再接続時に本来のディスプレイ設定に復帰しない
  • よくアイコン位置がおかしくなる
  • プラズマにログインしてからログアウトし、再度プラズマにログインするとスケーリングがおかしくなる
  • Balooを有効にしているとキャッシュファイルなども画像に含められてしまい困る上に、inotifyの上限に到達してもさらにファイルを追加するためシステムが終わる
  • AkonadiやKDE PIMは便利ではあるけど、「いらないことをする」感じも強い
  • KDE WalletがGnome Keyringのように暗黙にSSHエージェントのように振る舞わない
  • 設定が独特で、XDG標準を遵守しないし、XDGディレクトリもあまり尊重しない
  • Dolphinはアクションを追加するのも面倒で、XDGディレクトリを無視し、ブックマーク機能はない
  • ウィンドウタイリング後にウィンドウを移動すると、ステートはタイルされていないことになるが、元のサイズには戻らない
  • 壁紙の設定が面倒。フォルダの追加は知識が必要で、全部まとめられるので

捕捉

理想は高く、理想に届かないKDE Plasma。 KDE Applicationsに満足するか否かが分かれ目になる。

ウィンドウフィッティングはCinnamon以上に良好で、ウィンドウを並べるのは得意。 ただし8方向タイリングはショートカットキーの設定が必要になる。 一応、マウスでエッジに持っていくとタイリングしてくれるのだが、位置が割と狭くてやりづらい。

大きな欠点だった「等幅フォントにデュアルスペースフォントが設定できない」は、spacing >= 90にするのではなく、spacingを無視するオプションを加えて対応している。

うまく噛み合っていれば使いやすいのだが、噛み合わないことが多いKDE Plasma。 状況がハマれば使いやすいため、私はラップトップではKDE Plasmaを使用している。

なお、KWalletでブラウザの鍵を管理すると、ブラウザはこれまで管理していた鍵を捨ててしまう。 逆にブラウザに管理させるとKWalletで使えなくなる。だから他のデスクトップと行ったりきたりするのには最大の障壁になる。

systray問題として深刻だったsniについても、現在はおよそ問題のない状態になっているようだ。

特にスケーリングの自由度は大きなメリットと言っていいだろう。 電源管理の柔軟さと併せて最新のラップトップには適しているように感じる。

KDE4時代の癖のあった特徴的な機能は下げられている。そのため、積極的にKDE Plasma workspaceを使う理由を損ねたという印象もある。

相変わらずbuggyな部分も残念だ。Balooは非常に振る舞いに問題があり、オフにしておくのが無難だろう。

XFce4

良い点

  • Alt+左ドラッグとAlt+右ドラッグに対応
  • パネルウィジットのアプリケーションメニューが独自メニューを設定できるため、引き出しとして使用できる
  • 「ランチャー」ウィジットは副項目を設定でき、やっぱり引き出しとして使用できる
  • XFce4 Terminalの使い勝手が良い
  • やたら積極的で便利な「透明度」設定。透明ウィンドウ好きにはたまらない
  • ThunarがSFTPに対応している
  • ディスプレイの「ブランクスクリーン化」と「電源off」が分けられていて、DPプラグアンドプレイに悩まされている場合は便利
  • 自動起動にそれとわかるように他のデスクトップ環境のものが選択できるようになっており、Gnome Keyring SSH Agentを使うということもできる
  • 8方向タイル可能。ただしタイルのショートカットキーは全く設定されていない
  • デスクトップ右クリックでデスクトップコンテキスト(アプリケーションメニューつき)、中クリックでウィンドウリストと結構便利
  • アプリケーションファインダーがコマンド実行で候補検索を含み、展開すると(Alt+F3でこの状態でスタート)メニュー検索もできるようになった
  • Whiskerは簡単にリサイズできる
  • Mugshotが実は結構便利
  • デスクトップにウィンドウリストを表示することもできる
  • ウィンドウスイッチャがグリッド状に表示されるため選びやすい
  • パネルの設定が器用で、高さを含めるかどうか、ホバー時で透明度を変えるか、隠すかなど設定可能。「Dock風」と「タスクバー風」を使い分けられる仕様
  • 壁紙の設定がモニターごとである上、「設定ダイアログをモニター上に動かせばそのモニターが設定できる」親切設計

悪い点

  • アイコンラベルのサイズは固定で、アイコンの間隔も固定。ちょっと長い名前のフォルダは簡単に隠されてしまうし、隠されないように設定すると
  • Bluemanが初回起動時だけXDGディレクトリを拾うため、XDGディレクトリを変更すると毎回エラーを出す
  • ウィンドウフィッティングは一応存在し、リサイズ時にも効くのだが、非常に弱い。設定もできない
  • 通知がいくつでも出してしまう上に、閉じても表示した位置に表示しっぱなしで大量に出されるととても困る
  • ウィンドウタイリング後にウィンドウを移動すると、ステートはタイルされていないことになるが、元のサイズには戻らない
  • パネルがデスクトップの大きさとして除外されない(xfwm4は除外できる)ので、デスクトップアイコンやConkyがかぶる
  • ファイル選択ダイアログがGnomeと同じものになったため、ファイルをパスで一気に入力することができなくなった
  • アプリケーションファインダーがフォーカスロックしないため、複数起動してしまうこともでき、さらにフォーカスを失うことがあるため「あれっ」となって複数起動してゴミが残ることが多々ある
  • フルスクリーンにしているとき、フォーカスしているアプリ以外はパネルがウィンドウより前にきてしまう (マルチヘッドディスプレイでのみ発生する)
  • 標準のボリュームアプレットがない (外部プログラムとしてはPulseAudioアプレットがある)

補足

XFce4になったときからずっと「ちょっとずれてる」「いい感じなのに、対応したにもかかわらず痒いところに手が届かない」を続けているXFce。

だが、Gtk3化の過程で大胆にチェンジした。 アイコンラベルとか、アプリケーションファインダーのフォーカスとか、微妙に「XFceだなぁ」と思うところは残っているものの、機能的には遜色ないどころか、他の環境を凌駕するところまで到達している。

Manjaroでは18.2からついにXFce4 Gtk3がメインになった。 使い物にならなかった時期が長かっただけに、ようやくという感じだ。 だが、

  • thunar-archive-plugin
  • thunar-volman

についてはGtk2を引き続き標準としている。 thunar-volman-gtk3はextraとcommunityそれぞれにバージョン違いがあるちょっと困った状態だ。

ウィンドウデコレータがMetacity相当になり、Cinnamonと同じものを使えるようになった。 今までちょっと偏りがあって使いにくいものが多かったので、非常によくなったし、デフォルトのものが結構スタイリッシュにもなった。

基本的な方向性はCinnamonやMATEに近い進化だと思う。 使い勝手が劇的に向上し、他のデスクトップと比べ見劣りするという印象を払拭した。 Gtk3になったため「軽い」という特徴は損なわれたが、最近はアプリケーションのほうが重く、Gtk2を採用するアプリケーションも少ないため、正直デスクトップの重さというのはそもそも感じにくい。 むしろ処理が速くなって快適になったくらいだ。

LinuxでNvidiaもIntelもおかしなことになっているのでRadeonにかえてみた

もういやだ

パワフルなThinkStation P720ワークステーションだが、最近様子がおかしい。 Nvidiaではおなじみの

  • 画面が点滅する
  • X11 APIでスクリーンキャストするとウィンドウが消えてしまう (だからスクリーンショットでもウィンドウが消える)

という問題は直る気配がない…どころか、従来はVblankとFlippingを禁止すれば抑制できたのだが、最近はダメだ。 さらにいえば、Nvidia固有だったこの問題は、最近ではIntelでも発生する、というかINtelのほうがひどくなっている。

そして、追加で

  • Libreofficeが使っているSAL PLUGINとglibの連携が腐ってしまって、ほとんど操作不能なレベルでフリーズする
  • Vivaldiでありとあらゆる操作においてフリーズする

という問題が追加された。 Libreofficeの問題は最初Nvidiaだけだったが、現在はIntelでも発生するし、SAL_USE_VCLPLUGIN=genで防げたのだが、現在はこれも無理である。

そして、4kディスプレイにしてからビデオメモリが足りないのか、ウィンドウを開いていくとウィンドウ領域がグリッド状に表示され、かすかにウィンドウが見える場合もあるがほとんどの場合見えず、操作もできないという状態になる、ということに悩まされた。 作業効率が恐ろしく悪いことになってしまうため、毎日とてもストレスだし、貴重な時間を、1日で1-2時間程度失っている状態だった。

もうこれは耐えられない。

一方、Godavariはこのような問題を発生しない。 「じゃあGodavariでやれよ」と思うかもしれないが、Godavariは全面的にとっても非力である。よく馬鹿にされるくらいには。

それで、現在の出費は痛いし、TSMCは7mmプロセッサを控えている状態だというのはわかっているが、 結局のところRadeon 3000シリーズは噂の域を出ないということも踏まえて、思い切ってRadeon RX580を購入することにした。

なぜRX580か

最大の理由はLinuxにおけるパフォーマンスである。

WindowsにおいてはVega RXもそれなりの性能を示すようだが、Linuxにおいては多くの場合Vega RXとの性能差は誤差の範疇に留まる。 Vega RXでもGTX1060は越えない、というような所ぅたいだ。

にもかかわらずVega RXはずっと高値を維持しており、相当にコストパフォーマンスが悪い。 しかも、Vega RXはNvidiaと比べても相当燃費が悪いようで、「電気をめちゃくちゃ食う」のである。

そもそも私のP720はQuadro P6000のSLIを想定しているためキャパシティとしては耐えられないこともないのだが、家の電気回線はそうではないし、 無駄な電気は使いたくない。

また、Vega RXのパフォーマンスはVega RX 64であっても「Nvidia GTX1070に届かない程度」というのがWindowsにおいても現実であるようで、 ゲームのことを考えて高性能なカードを選ぶ、という気にもなれなかった。

タイミングは悪いなぁ、やたら高いなぁと思いつつも、Linuxにおいてはベストな選択肢となりそうなRX580を選択したということだ。

製品はAMD専門メーカーSapphireのゲーミング向けNITRO+シリーズSA-RX580-8GDN+001V2 VD6801を選択した。 オーバークロック製品で、発熱量は多いが性能は高いようだ。

P720にSapphire NITRO+ RX580は「ギリギリ入る」

製品が届いてびっくりした。 「大きい」

いやもう、比べるのが無意味なぐらい大きい。 「ミドルクラスだし、GTX960と同じくらいだろう」とか思ってサイズのことは一切気にしなかったのだが、「これはやばいかもしれない」と感じるほど大きかった。 ゲーミング向けトップモデルはこれより大きいのか!?

入らないかもしれない、と懸念したが、結局はギリギリながら収まった。 上下とも入るが、下段に関しては電源配線に触れてしまう。 また、サイドパネルに接触するため、サイドパネルがしめづらくなる。

「普通に入る」とは言い難い、「かろうじて入った」である。 だが、入る。

なお、SA-RX580-8GDN+001V2は補助電源が8ピン+6ピンというGTX1080Ti並の要求で、P720の標準の補助電源は2本であるためこれを全部使ってしまい、SLI構成はできない。 汎用の拡張コネクタがあるのだが、こちらは専用品で、なおかつLenovoとして単体の販売はしていないので、Crossfire構成にしたい場合は予めP6000のような「補助電源を2つ使う」ビデオカードを2枚構成にしておく必要がある。

クーリングパイプがまるでインテークマニホールドのようで、さらにSAPPHIREのロゴが青く輝き、大変かっこいい。 まぁ、P720の場合サイドパネルが透明なわけでもないので、全く見えないが。

消費電力は

4114+Quadro P400構成と比較すると、アイドル時で107Wと、約60W増えた。 運用時も140から220Wで、60W増加と見ていいだろう。 ただし、変動しやすくなったため、平均すると80W増加とみたほうがいいかもしれない。

ただし、変動しやすくなったのは、「今までP400で処理しきれなかった分を即座に処理する瞬発力があるため」と見ることができ、効率的には変わっていないかもしれない。

「省電力」という印象はなくなってしまったが、性能を考えればまぁ想定通りといったところ。

問題は解消したか

ほぼyesである。

  • 画面の点滅はなくなった。代わりにログイン時に画面がおかしくなることがあるが、支障は実際にはない
  • スクリーンショット、及びスクリーンキャスティングでウィンドウが消える不具合はなくなった
  • Libreofficeがフリーズする問題は解消された
  • Vivaldiが異様にフリーズするという問題は 軽減された
  • ウィンドウが表示できなくなる問題は解消された

また、私が非常に不満としていた、私お気に入りのフラゲ1が重すぎるという問題が事実上解消された。

この問題自体はつい先日からChromiumがマルチスレッドでFlashを処理してくれるようになり、最大で12.5%(5スレッド)で処理してくれるためにかなり軽減されてはいたのだが、 ビデオ描画のもたつきがなくなったためか、全く支障なくなった。 不思議なものだ。 まぁ、Flashはビデオアクセラレーションの対象ではあるのだが。

ちなみに、このゲームがあまりにも重いのは「4114が非力で、うち特有の問題」と考えていたのだが、先日Thinkpad X1でやってみたところ、とてもプレイできないくらい重かった。 というわけで、むしろ「このハイパフォーマンスマシンですらもこの程度」という状態だったと考えられる。 恐らくはWindowsであれば支障ないのだろう。

Vivaldiの重さはどこから

RX580になってVivaldiが操作のたびに、あるいはフォーカスするたびに止まる (タブ=レンダリングプロセスが止まるのではなく、Vivaldi全体が止まる)という問題は解消された。

ちなみに、Intelはこの問題はより深刻で、Vivaldiを立ち上げたあとメニュー操作をするとウィンドウマネージャごと固まってしまう。

だが、依然としてふたつの問題がある。

ひとつは、右クリックでメニューを開くとかなり長い時間固まるということだ。 これはstraceしてみると

read(17, "!", 2)                        = 1
write(18, "!", 1)                       = 1
openat(AT_FDCWD, "/usr/local/share/fonts/Commercial/FONT-COMP-SET21/Fontstyles2/FontGraphic_Mac/UniversalWalk.otf", O_RDONLY) = 251
fstat(251, {st_mode=S_IFREG|0644, st_size=8832, ...}) = 0
mmap(NULL, 8832, PROT_READ, MAP_PRIVATE, 251, 0) = 0x7fc6fd5f7000
close(251)                              = 0
munmap(0x7fc6fd5f7000, 8832)            = 0
openat(AT_FDCWD, "/usr/local/share/fonts/Commercial/FONT-COMP-SET21/Fontstyles2/FontGraphic_Mac/UniversalWalk.otf", O_RDONLY) = 251
fstat(251, {st_mode=S_IFREG|0644, st_size=8832, ...}) = 0
mmap(NULL, 8832, PROT_READ, MAP_PRIVATE, 251, 0) = 0x7fc6fd5f7000
close(251)                              = 0
munmap(0x7fc6fd5f7000, 8832)            = 0
openat(AT_FDCWD, "/usr/local/share/fonts/Commercial/FONT-COMP-SET21/Fontstyles2/FontGraphic_Mac/UniversalWalk.otf", O_RDONLY) = 251
fstat(251, {st_mode=S_IFREG|0644, st_size=8832, ...}) = 0
mmap(NULL, 8832, PROT_READ, MAP_PRIVATE, 251, 0) = 0x7fc6fd5f7000
close(251)                              = 0
munmap(0x7fc6fd5f7000, 8832)            = 0
openat(AT_FDCWD, "/usr/local/share/fonts/Commercial/FONT-COMP-SET21/Fontstyles2/FontGraphic_Mac/UniversalWalk.otf", O_RDONLY) = 251
fstat(251, {st_mode=S_IFREG|0644, st_size=8832, ...}) = 0
mmap(NULL, 8832, PROT_READ, MAP_PRIVATE, 251, 0) = 0x7fc6fd5f7000
close(251)                              = 0
munmap(0x7fc6fd5f7000, 8832)            = 0
openat(AT_FDCWD, "/usr/local/share/fonts/Commercial/FONT-COMP-SET21/Fontstyles2/FontGraphic_Mac/UniversalWalk.otf", O_RDONLY) = 251
fstat(251, {st_mode=S_IFREG|0644, st_size=8832, ...}) = 0
mmap(NULL, 8832, PROT_READ, MAP_PRIVATE, 251, 0) = 0x7fc6fd5f7000
close(251)                              = 0
munmap(0x7fc6fd5f7000, 8832)            = 0
openat(AT_FDCWD, "/usr/local/share/fonts/Commercial/FONT-COMP-SET21/Fontstyles2/FontGraphic_Mac/UniversalWalk.otf", O_RDONLY) = 251
fstat(251, {st_mode=S_IFREG|0644, st_size=8832, ...}) = 0
mmap(NULL, 8832, PROT_READ, MAP_PRIVATE, 251, 0) = 0x7fc6fd5f7000
close(251)                              = 0
munmap(0x7fc6fd5f7000, 8832)            = 0
openat(AT_FDCWD, "/usr/local/share/fonts/Commercial/FONT-COMP-SET21/Fontstyles2/FontGraphic_Mac/UniversalWalk.otf", O_RDONLY) = 251
fstat(251, {st_mode=S_IFREG|0644, st_size=8832, ...}) = 0
mmap(NULL, 8832, PROT_READ, MAP_PRIVATE, 251, 0) = 0x7fc6fd5f7000
close(251)                              = 0
munmap(0x7fc6fd5f7000, 8832)            = 0
openat(AT_FDCWD, "/usr/local/share/fonts/Commercial/FONT-COMP-SET21/Fontstyles2/FontGraphic_Mac/UniversalWalk.otf", O_RDONLY) = 251
fstat(251, {st_mode=S_IFREG|0644, st_size=8832, ...}) = 0
mmap(NULL, 8832, PROT_READ, MAP_PRIVATE, 251, 0) = 0x7fc6fd5f7000
close(251)                              = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/DeletedManjaro/UmePlus/umeplus-p-gothic.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/DejaVuSans.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Monospace/font-bh-ttf-1.0.3/luxisr.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/gsfonts/NimbusSans-Regular.otf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/MuktiNarrow.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/malayalam.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/Sampige.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/padmaa-Medium-0.5.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/VL-Gothic-Regular.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/OTF/ipag.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/TSCu_Paranar.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/NanumGothic.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Korean/UnDotumBold.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Commercial/Unknown/CODE2000.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Morisawa/\343\203\222\343\203\251\343\202\256\343\203\216\344\270\270\343\202\264 Pr6N W4.otf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Morisawa/\343\203\222\343\203\251\343\202\256\343\203\216\344\270\270\343\202\264 Upr W4.otf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/Mathematica6.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/Mathematica7.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/AndikaRegular.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Japanese/Tsuyuzora-bunko/XZBB.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Japanese/WadaLab/wlcmaru2004aribu4430/wlcmaru2004aribu.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/OTF/FiraSans-Regular.otf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Japanese/nukamiso/nukamiso_yamiyootf_beta07.otf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/OTF/Vollkorn-Regular.otf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/share/fonts/TTF/Ricty-Regular.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Commercial/Motoya/NFbc1kp.ttc", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Japanese/Motoya/MTLc3m.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Japanese/tfont/TGothic-GT01.ttc", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab69000, 57344, MADV_DONTNEED) = 0
madvise(0x3a38dab8b000, 49152, MADV_DONTNEED) = 0
madvise(0x3a38d9095000, 8994816, MADV_DONTNEED) = 0
access("/usr/local/share/fonts/Japanese/UchidaAkira/OradanoGSRR.ttf", R_OK) = 0
madvise(0x3a38dab8b000, 385024, MADV_DONTNEED) = 0

という感じで、フォントを片っ端から読んでいて、ものすごく時間がかかっている感じだ。 ちなみに、これはChromiumだと起動時に発生するため、フォント数が増えるとChromiumは起動が遅くなるのだが、Vivaldiではコンテキストメニューの表示がすさまじく遅くなる。 また、この問題はフォームをクリックしたときに発生するため、非常にストレスになっている。

もうひとつはページをロードしたときにロードの途中で異様に時間がかかる。 これはstraceを見ても止まるわけではないのだが、特徴的な要素は見つからず、コンソールで見るとただ単に飛んでいる。 これはChromiumでも発生するため、恐らくBlinkの問題だ。

Vivladi固有の問題のほうは時間があるときに報告するつもりだ。

現状では「Firefoxを使う」というのが解決策になりそうだ。 Chromiumは最近とにかく重くなっている。CPUの使い方がえぐいし、異様に処理に時間がかかるようになった。 フリーズしている、と感じるような処理時間で、原因がよくわからないケースが多い。 これがバージョン71から発生していることは認識しているのだが、そもそも「ウェブレンダリングを難しくしすぎている」というのが問題で、 「なんでもかんでもウェブでやろうとするのやめてくれないかなぁ」と心底思う。

だいたいこの流れや、レンダリングエンジンの複雑さがGoogleの胸先三寸になってしまっていることにはとても気持ち悪さを感じている。

Radeon RX580はどうだったか

なお、RTX2000シリーズは通常利用での暴走や出火などが問題視されていることからあまり完成度は高くないと見られており、 AMDは14nmプロセスでNvidiaより圧倒的に性能が低く、それでありながらライバルと位置づけるNvidia製品よりもずっと高い、という状況である。 しかもTSMCは7nmプロセスの新しいカードを用意しており、Radeon VIIという新製品は「RTX2080相当の性能で、価格的にも同等。Vega RX 64比では性能は1.8倍」とのたまっている。 TSMC、及びAMDは7nmで攻勢をかけるつもりのようで、とにかく時期が悪いのは確かだ。

だから、今買うならGTX1080かRTX2070あたりが妥当な判断で、RX580が4万円程度はするという点を考えると普通の(Windowsの、ゲーマーの)ユーザーには「迷わず買う人以外は買わないほうがいい」レベルの製品だろうとは思う。

Linuxにおける性能は、おおよそWindowsにおけるGeForceとの関係と同等。 つまり、NvidiaがWindowsと比べて半分程度の性能しか出せていない以上、AMDのドライバもWindows版と比べて半分程度、と考えれば良いのではないだろうか。 以前はもっともっと差が開いていたのでだいぶ健闘しているといって良さそうだ。現在はNvidiaのプロプライエタリドライバとAMDのオープンソースドライバ(AMDGPU)は同等の出来ということになる。 性能面では、だが

ゲーミング部分で言うと、ドライバの出来と、ゲームにおける最適化の結果として圧倒的にGeForce寄りであり、Radeonはその力を発揮できないという状態が続いている。 だから、ゲーム用途では何も考えずにGeForceでいいというレベルだし、多分それはRadeon VIIが出ても変わらない。

一方、Linuxのワークステーションユースで不満が出るという気はしなかった。 vdpauinfoでは

display: :0   screen: 0
API version: 1
Information string: G3DVL VDPAU Driver Shared Library version 1.0

Video surface:

name   width height types
-------------------------------------------
420    16384 16384  NV12 YV12 
422    16384 16384  UYVY YUYV 
444    16384 16384  Y8U8V8A8 V8U8Y8A8 

Decoder capabilities:

name                        level macbs width height
----------------------------------------------------
MPEG1                          --- not supported ---
MPEG2_SIMPLE                    3 65536  4096  4096
MPEG2_MAIN                      3 65536  4096  4096
H264_BASELINE                  52 65536  4096  4096
H264_MAIN                      52 65536  4096  4096
H264_HIGH                      52 65536  4096  4096
VC1_SIMPLE                      1 65536  4096  4096
VC1_MAIN                        2 65536  4096  4096
VC1_ADVANCED                    4 65536  4096  4096
MPEG4_PART2_SP                  3 65536  4096  4096
MPEG4_PART2_ASP                 5 65536  4096  4096
DIVX4_QMOBILE                  --- not supported ---
DIVX4_MOBILE                   --- not supported ---
DIVX4_HOME_THEATER             --- not supported ---
DIVX4_HD_1080P                 --- not supported ---
DIVX5_QMOBILE                  --- not supported ---
DIVX5_MOBILE                   --- not supported ---
DIVX5_HOME_THEATER             --- not supported ---
DIVX5_HD_1080P                 --- not supported ---
H264_CONSTRAINED_BASELINE       0 65536  4096  4096
H264_EXTENDED                  --- not supported ---
H264_PROGRESSIVE_HIGH          --- not supported ---
H264_CONSTRAINED_HIGH          --- not supported ---
H264_HIGH_444_PREDICTIVE       --- not supported ---
HEVC_MAIN                      186 65536  4096  4096
HEVC_MAIN_10                   186 65536  4096  4096
HEVC_MAIN_STILL                --- not supported ---
HEVC_MAIN_12                   --- not supported ---
HEVC_MAIN_444                  --- not supported ---

Output surface:

name              width height nat types
----------------------------------------------------
B8G8R8A8         16384 16384    y  NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 A8I8 I8A8 
R8G8B8A8         16384 16384    y  NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 A8I8 I8A8 
R10G10B10A2      16384 16384    y  NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 A8I8 I8A8 
B10G10R10A2      16384 16384    y  NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 A8I8 I8A8 

Bitmap surface:

name              width height
------------------------------
B8G8R8A8         16384 16384
R8G8B8A8         16384 16384
R10G10B10A2      16384 16384
B10G10R10A2      16384 16384
A8               16384 16384

Video mixer:

feature name                    sup
------------------------------------
DEINTERLACE_TEMPORAL             y
DEINTERLACE_TEMPORAL_SPATIAL     -
INVERSE_TELECINE                 -
NOISE_REDUCTION                  y
SHARPNESS                        y
LUMA_KEY                         y
HIGH QUALITY SCALING - L1        y
HIGH QUALITY SCALING - L2        -
HIGH QUALITY SCALING - L3        -
HIGH QUALITY SCALING - L4        -
HIGH QUALITY SCALING - L5        -
HIGH QUALITY SCALING - L6        -
HIGH QUALITY SCALING - L7        -
HIGH QUALITY SCALING - L8        -
HIGH QUALITY SCALING - L9        -

parameter name                  sup      min      max
-----------------------------------------------------
VIDEO_SURFACE_WIDTH              y        48     4096
VIDEO_SURFACE_HEIGHT             y        48     4096
CHROMA_TYPE                      y  
LAYERS                           y         0        4

attribute name                  sup      min      max
-----------------------------------------------------
BACKGROUND_COLOR                 y  
CSC_MATRIX                       y  
NOISE_REDUCTION_LEVEL            y      0.00     1.00
SHARPNESS_LEVEL                  y     -1.00     1.00
LUMA_KEY_MIN_LUMA                y  
LUMA_KEY_MAX_LUMA                y  

また、vainfoは

vainfo: VA-API version: 1.3 (libva 2.3.0)
vainfo: Driver version: Mesa Gallium driver 18.3.1 for Radeon RX 580 Series (POLARIS10, DRM 3.27.0, 4.20.1-1-MANJARO, LLVM 7.0.0)
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileHEVCMain10             : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc

と当初対応しておらず、重大な弱点であった「H.265の非対応」は解消されているようだ。 (ただし、VP8/9には対応していない)

実際に試してみたところ、hevc_vaapiでのエンコードは116fpsと、P400でのNVENCには劣るもののかなりの優秀さを見せた。これだけ速ければ十分に実用的だろう。 画質がNVENCだと実用には厳しいところがあったのだが、VCEの場合いくらか画質がいいためより実用しやすい。 それでも、利用できる場合は「普通は画質を少しでも良く保存したい」ために「速さ優先」とはなりづらく限定的だが。

さらにNvidiaと違い、Waylandのコンポジターがちゃんと動作するというのも大きなメリットだろう。

消費電力的にも、あまり電気を使わないプロセッサを使っているからという事情が前提になってしまってはいるものの、使いづらくなるほどではない。 気持ちとしては「もっと消費電力が少なかったらなぁ」というのと、「2万円台前半だったらなぁ」という気持ちはとてもしてしまうのだが、そうした点を除けば「入れておけばとりあえず安心できるカード」であると言えるだろう。 「とりあえず入れる」には巨大すぎて入れるケースを随分選ぶが。

DVI-Dがひとつ、HDMIとDPがふたつずつで計5出力というところも、使いやすく不満になりにくい。 このビデオカードは大きさ的にも電力的にもそう来やすく選べるものではないが、Linuxでのグラフィックにまつわる不満を感じているのなら、RX580と言わずとも(例えば560でも)Radeonにする価値はありそうだ。

将来的には

「ゲームをする事情」と「デスクトップユースとして普通のアプリを動かす事情」は似ているのだが、「計算力を求める事情」と「Linuxにおいて快適な仕様」とは大きな違いが出てきている。

だから、贅沢を言えば2種類の仕様を用意できると最善で、贅沢を言えば、 「Ryzen + GeForce (主にWindows及びゲーム向け)」と「Ryzen Threadripper + Radeon (Linux及び計算向け)」の2台で編成できたらなぁ、と思う。 Zen2でこれを構成するのはなかなかドリーミーだ。

とはいえ、現実的に1台に絞るとしたら、「Ryzen + Radeon」という構成で「現実的な計算力とLinuxで扱いやすいグラフィック」というのを取るだろう。

現状、P720はどうなのかというと、やはり4114に求めたものと諦めていたものというのが大きい。

「メニーコア」という性能は、それを発揮する場面というのは本当に少ない。 実際、私の普段の運用では4114ですら持て余し気味である。 ところが、普段遣いではあらゆるアプリで処理性能が足りずストレスフルである。 「普通の使い方でモバイルi3程度の快適性しか求められない」というのはわかっていたが、それでもこのマシンのクラスを考えるととても残念な感じがする。

対して、実際にメニーコアを求めるケースでは4114では全然足りないのだが、それでも処理性能はi7とは段違いであった。 「4114はフルコアを活用できたとしてもi7に劣る」と考えていたが、実際は第8世代Core i7よりもずっと高速に動作した。 シングルコア性能も諦めていたほどに低くはなく、「さすがにそれなりに性能はある」と感じることができる。 そもそも、20コア40スレッドであるから、「20スレッドスケールテスト」が手元でできるというのもかなりのメリットだった。 だから、ちゃんと求めたものは実現できているし、価格を考えれば完全に目的を達成できるほどではないというのはわかっていた。

だが、結局のところ現状P720の最大の魅力は「省電力」である。 48Wから90W程度でありながら非常に優れた処理性能を発揮する、というのはかなり魅力的だ。

だが、やっぱりコンピュータは「性能が足りるか否か」であり、エクスペリエンスが良いかと聞かれるとYESとは答えがたい。 部分的にボトルネックになるブラウジングが全体の作業の足を引っ張るという状況も痛い。

「エクスペリエンスは諦めて処理量を増やしたい」というのとは矛盾しているのだが、やはりエクスペリエンスを優先したい気持ちが湧いてくる。 今回RX580にしたことで飛躍的にエクスペリエンスが向上したことも大きな理由になっている。 というより、RX580にしたことでP720がとりあえず不満ないくらいの動作をしてくれるようになった。 だから、バランス的には今の状態は悪くないのかもしれない。

Erina/Surtrに関する研究が一区切りついて、あまりデータプロセッシングすることがなくなったというのも大きい。 圧倒的に重い処理であったことから、これのためにメニーコアを求めたし、それによって成果も挙げたのだが、これがなくなると相当頻繁に回されるタスクを考えても実際8コアもあればあまり支障はなく、16コアのRyzenが用意されるのであれば不満はなさそうに思える。

ただ、ゲームをすることに関していえばGeForce優位は揺るぎそうにもないし、かといってLinuxでは現状NvidiaもIntelもなかなかの惨状ということを考えればRadeon以外選択肢はないという状態であり、 これが2台構成を求める理由ともなっているが、1台を選ぶのであればLinuxエクスペリエンスを優先することになるだろう。

ただ、Zen2の世代ではまだP720は現役で、しかも「非常に高機能で並列処理能力は高いが、通常の使い方ではそれほど性能は高くなく、消費電力はやや少なめで、筐体はとても大きい」マシンをメイン以外で使うというのは非常に難しい。 今Godavariがそうであるように、「主にWindows環境(音楽制作)、必要なときは計算資源または分離された帯域としてのLinux」みたいな使い方になるだろうか。 実際、音楽制作では機材がIntelプロセッサを想定したドライバでAMDドライバだといまいちうまく動かないケースもあり、現在のP720のような構成は非常に好ましい。 多くのVSTプラグインを使う場合も4114はかなり良い働きをしてくれる。 それでも、なんとも微妙な話で、Zen2世代でメイン機の差し替えを行うかは悩ましいところではある。

やはり「それぞれの用途で最適化した理想の2台」なんて夢見がちな話をするに留めるとして、多分本当に多くの人にとって有益なのは現時点で性能的にやや微妙な立ち位置にあるRyzen Gが不満のない性能まで引き上げられること、 あるいはRX 580相当のRadeonがもっと安く、省電力でコンパクトなものとして出てくることだろう。それは、次の世代で実現するかもしれないし、Zen3の世代まで待たねばならないかもしれない。

一方、X11はいよいよ限界を迎えている感もあるが、一方でWaylandがよくなっているわけでもない。 IntelもNvidiaも不具合が出る状態が続けばかなり苦しいことになるだろう。


  1. 具体的にはFlower Knight Girlである。 なお、 18禁バージョンもあるため 検索される際にはくれぐれも留意願いたい。

「ZshからRubyにしたら速くなる」 その理由とテクニック

現在取り組んでいるプロジェクトで、パフォーマンスチューニングの一環として当初Zshで書かれていたスクリプトをRubyで書き直すことによって、60倍程度の高速化を実現した。 もちろん、単純に書き換えただけではなく、可能な限りfork/execをしないようにしたり、コストがかかる処理を最小にするなどの工夫を伴って手に入れた結果だが、「ZshでしていたことをRubyに書き換えた」だけでも相当な効果があった。

このパフォーマンスチューニングは単にプログラムを書くだけの人には生まれにくい発想である。 Unix、そしてLinuxのシステムや、プログラミング言語処理系に関する知識がないと考えられない要素が多いのだ。

そこで、この話を解説する。

「ZshよりRubyが速い」そのわけ

根本的な話として、Zshはそもそも遅い処理系だ。 「Zshが遅い」という話はZshのメーリングリストでもちらほら話をされる。 別にBashと比べて遅いということではないのだが(Bashもまた非常に遅い処理系だからだ)、状況によっては速度が問題になる程度に遅い。

Rubyも相当に遅い処理系であると言われていたし、実際かなり遅かったのは事実だ。 それでもZshに比べれば随分早かったのだが。

だが、それ以降、Rubyは高速化に取り組み続けている。対して、Zshはあまり高速化には取り組んでいない。だから、差が開いている。

しかし、理由がそれだけというわけではない。

Zshは純粋なインタープリタである。対して、Rubyはスクリプト言語ではあるがバイトコードインタプリタ型である。 この違いは、syntax errorが起きるタイミングが、Rubyがスクリプトを実行しようとしたタイミングであるのに対し、Zshはその行に到達したときであることからもわかる。

インタープリタ型であれコンパイラ型であれ、ソースコードを機械語に変換しなければならない、という点は変わらない。 その違いは方法とタイミングである。

インタープリタ型言語の場合、「1行ずつ(1コマンドずつ)変換する」のである。 その変換方法はもちろん処理系によって異なるのだが、Zshの場合、complex commandでも複数の文をまとめて変換することはしないし、ループによって繰り返される場合でも一度変換したものを使いまわしたりはしない。

対してRubyは、最初にコード全体を構文木に変換する。 RUby 1.8までは構文木インタープリタによってこれを実行していたが、Ruby 1.9以降はこれをさらにバイトコードに変換し、バイトコードインタープリタ(VM)によって実行するようになった。 バイトコードはRuby専用の機械語のようなもので、VMによって非常に小さなコストで実行できる。 Ruby 2.6からはJITコンパイラも追加され、部分的にCコードを生成し、これをネイティブコンパイラ(例えばgcc)によってバイナリコードに変換する(こともできる)。

これで1行だけのようなコードだとあまり差は出ないし、Zshでは1行だけどRubyでは何十行という可能性もあるので、このようなケースではRuby有利というわけではなくなる。 だが、ループで何度も同じコードを実行するような場合には非常に大きな差になってくる。 今回の場合、テスト段階で500回のループであったことから、大きな差になったということである。 だからループ回数が増えると倍率的にも速度差はさらに開く。

fork/execとコンパイルにかかる時間

Unix関連に少し知識がある人であれば、「forkはコストが重く遅い」というのを聞いたことがあると思う。

だが、この認識にはちょっと注意が必要だ。 というのも、C言語の速度から見た時に「forkする時間があればどれだけ実行できるか」という点を考えるとsystemで外部コマンドを呼び出すとそこだけ局所的に時間がかかる、という状況が発生する。

だが、実際にはfork(2)しても1000分の数秒にすぎない。 どちらかといえばそれよりもexec(2)のほうが重いのだが、それでもせいぜい100分の1秒程度だ。 だから、C言語で書いている場合ですらそれなりに長くなる場合はむしろ実行コストを省略できてコマンドを呼び出すほうが速かったりする。

昔のUnixではfork(2)はもっともっと遅かった。 現在のLinuxにおいてfork(2)が速くなったのはコピーオンライト形式であることの恩恵が大きい。 古典的なUnixではfork(2)は呼び出した時点でプロセスのメモリをコピーしていた。直後にexec(2)する場合はコピーしたメモリの内容は全く使わないのでかなりの無駄だ。

ところが、現在のLinuxにおいてはfork(2)によってメモリはコピーされない。共有されるのである。 そしてforkされたプロセスが共有されているメモリに対して書き込みを行った時に別に領域を確保してそれを変更する仕組みだ。

結果的にfork自体は一瞬に近くなっている。

そして、もうひとつ重要なのが「コンパイル時間」だ。 Rubyは起動時に対象スクリプトの変換を行う。 だが、この変換コストは速くなるに従って増加している。以前は構文木に変換するだけだったのが、1.9からはさらにバイトコードに変換する時間が必要になったし、2.6でJITを使うとさらにCコードを生成してそれをコンパイルする時間まで必要になっている。 つまり、Rubyはだんだん「実行は速くなっているが、実行に着手するまでは時間がかかるようになっている」のである。

これは、例えばechoであれば

% time /bin/echo > /dev/null
/bin/echo > /dev/null  0.00s user 0.00s system 79% cpu 0.001 total

ということになるのだが、Rubyだと空っぽに近くても

% time ruby -e 'nil'         
ruby -e 'nil'  0.04s user 0.02s system 59% cpu 0.089 total

結構時間がかかる。 つまり、一瞬で実行が終わるRubyスクリプトを何度も何度も繰り返して呼び出すと、トータルではかなり時間がかかるわけだ。 もともとのスクリプトは本体はRubyで、呼び出しがZshだったので、20並列で各500回、Rubyによるコンパイルがかかっていた。だから、かなりの時間がかかっていたのだ。

だが、「Linuxのforkはメモリが共有され、ほとんど一瞬で終わる」という点を利用すると改善の余地がある。 それは、実行可能なRubyスクリプトをライブラリ化する、という方法だ。

ZshからRubyを呼び出す場合、どうしてもRubyを呼び出すたびにRubyによるコンパイルをかけざるをえない。 当初は10000回コンパイルされていたのだが、500回のループをZshではなくRubyで行うようにすれば20回で済むようになる。だが、それでも20回のコンパイルが必要だ。

しかし、呼び出すスクリプト自体をRubyに変えてしまえば、実行しようとするスクリプトをライブラリとしてロードするという方法がとれるようになる。 ライブラリとしてロードすると、そのコンパイルは呼び出し元スクリプトをロードしたときに行われる。 もちろん、呼び出しの目的は呼び出すだけであり、直接そのライブラリの機能を使うわけではない。だが、この状態からforkすると、「コンパイル済みコードがメモリ上にあるRubyプロセス」が出来上がる。

この時点でスクリプトを実行する方法は「メソッドを呼び出す」(あるいは、その機能を果たすオブジェクトを作ってメソッドを呼び出す)だけである。 繰り返し呼び出すループを書くのも、単にRubyのループを書いて、そこで繰り返しメソッドを呼び出すなりオブジェクトを作るなりすれば良い。 呼び出し元スクリプト側では並列分だけforkしたあと、Process.waitallでもしていればいいわけだ。

これはZshに対して、「Rubyスクリプトのコンパイルが1度だけでいい」「execする必要がない」というメリットをもたらしている。 どちらも結構コストの高い処理であるから、繰り返し実行する場合は非常に大きなコストになり速度を低下させる。「処理自体は軽いのだが果てしなくループする」タイプのスクリプトに対してこの方法は本当に効く。 なぜならば、そのようなスクリプトに対してはコストの高い呼び出しをしているとコストのほとんどは呼び出しで占められ、実行コストは小さいためにスクリプト自体を高速化しようとがんばったところでほとんど無意味だし、逆に呼び出しコストを軽くすると劇的に速くなるからだ。