ISUCON 11 予選に参加した

ISUCON 11 の予選にいつものチーム「ワイハリマ」で参加していた。利用していたリポジトリは https://github.com/yuta1024/isucon11 で、予選終了後に public になっている。最終スコアは 26656、走らせたベンチマークの中で最良のものは 29189。記事執筆時点では最終結果は発表されていないが、再起動後に機能を維持すること自体は確認している。(追記:ベンチマーク周りの事情で追試の際に再計測が行われ、最終スコアは 27163 だった。)

COVID-19 による緊急事態宣言の最中であり、いくらワクチン接種済みとはいってもさすがにチームメンバーも物理的には集合せず、各自自宅からオンラインで参加。

時間としては 10:00-18:00 の8時間の予定で、定刻通り10時開始、17:20頃にポータルに問題があってベンチマークが行えなくなり18:10頃に復旧、競技は18:45まで延長となった。

いつものように言語を PHP に切り替え、ベンチマークを流して kataribe で様子を見たり実装を見たりしながら改善方針を検討した。デフォルトの Go の初期実装で走らせると 1656 だったのに対し PHP に切り替えた直後は 980、初期実装の段階では Go に負けている。PHP は(ISUCON ではいつものことのようだが) Slim が採用されており、しかし ./app/routes.php にほぼ全てが書かれている形のようだ。そして、とにかく isucondition テーブルへの書き込みに該当するリクエストの件数が多いようだ(ただし初期実装では9割のリクエストが PHP 側で無視されている。書き込んだ変更が反映されて初めて点数ではあるものの書き込みが無視されること自体のペナルティはなし)。

isucondition のテーブルで3つの値の true, false をわざわざ CSV 形式のテキストで保存しているのを発見し、 TINYINT 3 つのカラムに切り替える改修を行った。ただ、これは明確に効いたという感じではないようだ。今にして思えば結局このカラムは3カラムまとめて取得してくるものでデータベース側でどうこうするものではないので、実運用上するならともかく、速度だけ気にするなら特に影響が大きいというものではなかったのだと思う。

assets の静的ファイルがなぜか PHP の file_get_contents で実装されているという問題があり、これはメンバーが nginx で返すように修正していた。

ここまで一台のサーバーで三人が作業していたが、3 VM 同じものが動いているので、ここで3人がそれぞれ1台の VM を使うようになった。

とにかく POST /api/condition/<uuid> へのアクセスが非常に多く、無視している9割も一度 PHP で処理しているのはシンプルに問題がある。また、少なくとも ISUCON での経験上は Slim のオーバーヘッドは無視できないほど重くなることもある印象だった。ISUCON の PHP 実装は Slim で書かれており、かつほぼすべてを ./app/routes.php に書いていて Slim のメリットを生かせていないことが多く、もともと PHP が初期実装として有利でない現状では初期実装としてもフレームワークなしのべた書きにした方がバランスがとれるのではとは思うものの、Slim のメリットを活かしたコードになっていないなら逆に改修箇所も小さいので、要所を絞って一つ、二つ脱却するだけなら現実的にコンテストの時間内で行える。そのため、残りの1割でも充分リクエスト数が多いこの API は Slim を脱却したいという話になった。90% の割合は PHP 側で何もしないで処理しているはずにも関わらず、1割を超えるリクエストが nginx のログで status 499、つまり実際にはレスポンスすら返却せずタイムアウトしているのも気にはなっていた。

メンバーが nginx 側のロードバランシング機能を用いて一定の割合を nginx 側で所定の形式で返却、残りのみを PHP に回す処理を書いていて(これも冒頭にリンクを張ったリポジトリに上がっている)、これはかなり効いたようだ。さらに初期実装で 90% を無視していた割合を見直して調査した結果、そもそもこの時点では 90% でも捌き切れておらず、さらに高い値にしてある程度捌けるようにした方がスコアが伸びることが判明した。GitHub のこの時のプルリクエストでは 98% を無視する(2% しか php-fpm に流さない)ことになっていたが、この値は定期的に見直しているのでどの時点での値かは正確には思い出せない。

僕は POST /api/condition/<uuid> を Slim から脱却し単一 PHP ファイルで動作するようにする修正を行っていた。これはさらに別 VM へのオフロードもこの時点で目論んでいた。なお、この API はざっと見た限りでは WebUI からは行われずベンチマークからしか修正の正しさを確認できないのがやや面倒ではあったが、ベンチマーク自体はシステムがスムーズに動作していたので大きな問題でもなかった。

また同時に PHP の xdebug モジュールの無効化やデータベースのスロークエリを確認した上でのインデックス追加を行っているメンバーもいた。

この時点で15時過ぎ、10058 のスコアを記録した。

ここから先は3台の VM の役割を検討し始めた。まず、 php-fpm も mysql も nginx も全て CPU をまあまあ使っていたので、 MySQL は別 VM への移行を決定。更に POST /api/condition/<uuid> も別 VM に渡すことになった。ここで3台の VM の役割がわかれるが、リポジトリに置いていたファイルはあくまで全台に撒いても問題ないように書いていた。少なくとも今回は全台共通で撒けるようにする工夫に大きな手間はかかっていなかったと思うし、余計なことを考えないで良い効果の方が大きかったと思う。

多分この頃、時刻で言えば17時頃に、再起動試験も行った。とはいってもデータの置き場所は結局変更していないので、データ保持の確認は行わず機能維持のみを確認した。ミドルウェア周りはいうほどいじっていないしオンメモリ化もしていないので、特に問題なし。心配する要素がないのでデーモンが上がってくることのみのチェック。ただし無効化したつもりの余計なデーモンが起動してくるということはあった。

この後は、いくつかの重い処理をどの VM にやらせるかを移動したり POST /api/condition/<uuid> の無視割合を変更したりしてはベンチマークを走らせるといったことを3人でしていた。またこのころ、 nginx の client_body_buffer_size の調整や、 InnoDB 周りを主とした MySQL 周りのチューニング、 nginx の各種パラメータの修正をしていたメンバーもいたようだ。

なお、認証が必要な API は単に別のサーバーに逃がすだけだと 401 Unauthorized を返して正常に動作しなかった。調べた結果、 Slim 標準のセッション管理機構がサーバーローカルで閉じていて複数サーバーにまたがるとセッション管理が機能しないことが原因のようだった。ルールにはこういうサーバ側で生成する文字列は文字種を変えなければ自由にして良いと書いてあったと記憶していたこと、 Cookie に関するルールは記憶の限りではなかったこと、そもそも言語標準のセッション管理機構を用いるのであれば初期実装が複数言語あるアプリケーションで共通の何かを守らなければ外部連携に関するトラブルが発生するとは考えづらいこともあり、 Cookie に直接ユーザー名を保存して認証はユーザーの申告を全面的に信用するという方針に実装を変更した。これにより任意の API について php-fpm の負荷はどのサーバーにでも逃がすことができるようになった。

この調整を行い、分散具合や負荷のかかり具合としては良い感じになったと感じた。

この後も無視割合を変更する調整を行った。最終的に、有効1:無視5、つまり無視割合 83% 相当にすることを決定、ログなどの性能分析には有益だが直接的には不利にはなっても有利にはなりえないオプションを無効化し、その状態でベンチマークを二回ほど走らせたら一応は他の設定よりは良さそうな値にはなり、残時間もあまりなかったのでここで作業終了。

後から改めてコードを見てみると、 kataribe 報告で合計時間が多いとされていた API のいくつかには、 isu それぞれについて isu_condition テーブルから最新の情報を取得するクエリが実行されており、これが HTTP リクエスト 1 回に対して多数回呼び出されるものがあった。isu それぞれについての最新情報は isu_condition の時に併せて更新すれば isu テーブルに持たせられることから改善の余地があったと考えられ、今回は実装の修正をおろそかにしていたことが悔やまれる。

コンテストとしては、まず問題としてはプログラム自体の改善と3台の VM の活用それぞれがバランス良く織り込まれていたし、改善やその調査は ISUCON 専用の何かというものが多いわけでもなく実用的な技術の延長上にあるものが多かったので、質が高かったと感じる。また、今回は終了直前にポータルが50分ほど落ちた以外には運営側起因のトラブルは(少なくともワイハリマに影響するものは)発生しなかったし、ベンチマークボタンを押したらキュー待ちもほとんどなくほぼ即時にベンチマークが実行された。ベンチマークの結果自体も同じプログラムで実施すれば複数回実施しても大幅な変動が出ないものであった。全体を通して、8時間の競技の枠内で最大限に高速化技術を発揮できるかに集中できるものになっていたと思う。

(追記)メンバーの write up:ISUCON11 Qual writeup – yuta1024’s diary

PiPO X9s (12V 版)に Ubuntu Desktop 20.04 をインストール

以前買ってきた PiPO X9s に Ubuntu Desktop 20.04 をインストールした。その際、デバイス周りで設定が色々必要だった。なお前回の記事にもある通り、 X9s と呼ばれるものでもマザーボードが新しくなっており、 X9s という名前でも全くデバイスの情報が出てくるのでウェブ上の情報では混乱することがあるようだ。今回は電源電圧が 12V のものである。

数十秒でスリープしてしまう現象

まず、 Ubuntu のインストーラーを起動した時点で、操作するしないに関わらず数十秒でスリープしてしまう現象が起きて、そのままでは操作がままならなかった。調べてみると、 /proc/acpi/button/lid/LID0/state というファイルに closed である旨が書かれていた。どうやら lid スイッチが見えており、これが closed として認識されているために、ラップトップのふたを閉じた時の動作が行われているようだった。

どうやら似たようなことが起こるデバイスは他にもあるようだ:razer-blade-stealth-linux/ubuntu-18-10.md at master · rolandguelle/razer-blade-stealth-linux に書かれていた。基本的には button.lid_init_state=open という起動オプションを渡すと良いようだ。インストーラや初回起動時は GRUB のメニューから手でこのオプションを追加し、インストール完了後に /etc/default/grub の GRUB_CMDLINE_LINUX_DEFAULT に button.lid_init_state=open を追加して、 update-grub で生成して解決した。

無線関係

WiFi については前回記事と同様、日本で合法に使用できないと思われる内蔵 WiFi を無効化して USB WiFi を使用することにした。Ubuntu 20.04 では GUI から WiFi を有効にする際、内蔵 WiFi と USB WiFi を別々に設定できたため、一応そのままでも USB WiFi のみを使用することができると思われるが、networking – How to disable WiFi interface with netplan? – Ask Ubuntu を参考に、以下の設定で無効にした。(wlan1 として見えていた時に wlan1 を無効したら、 wlan0 として見える時もあったので両方書いた)

$ cat /etc/network/interfaces
auto wlan0
iface wlan0 inet manual
        pre-up ip link wlan0 set down
        pre-down ip link wlan0 set down
        down ip link wlan0 set down

auto wlan1
iface wlan1 inet manual
        pre-up ip link wlan1 set down
        pre-down ip link wlan1 set down
        down ip link wlan1 set down

Bluetooth は使わないので普通に設定画面から Bluetooth を無効化した。

Sileadtouch

タッチパネルについては sileadtouch が使われている。Ubuntu 20.04 には silead というモジュールがデフォルトでインストールされていたが、機器ごとに固有となるファームウェアを /lib/firmware/silead/mssl1680.fw に配置する必要があるようだ。

ファームウェアについては onitake/gsl-firmware: Firmware repository for Silead touchscreen controllers の tools/scanwindrv で SileadTouch.sys を読み込ませて出力されたものを利用した。SileadTouch.sys は最初にインストールされていたものだが、一応 PiPO のウェブページからリンクされている Baidu のクラウドストレージに置かれたイメージファイルからも復元はできる。なお、解像度などの設定が書き込まれたファームウェアを作る fwtool は標準の silead モジュールとは別のドライバを使う時のもののようだ。NANOTE P8でLinuxを動かすメモ – 信頼できる発行元を参照した。

firmwre_00.fw を /lib/firmware/silead/mssl1680.fw に配置した後、 modprobe -r silead して modprobe silead すれば、反応はするようになった。ただし、先ほどの NANOTE P8 の記事と同様、この状態ではタッチ位置が大きくずれる(タッチパネル全体の認識が画面の左上の矩形領域にマッピングされているようだった)ので、キャリブレーションを行う必要があった。キャリブレーションには xinput-calibrator パッケージ(universe リポジトリにあり、 Live USB では apt-add-repository universe する必要があった)の xinput_calibrator を用いるが、そのままだと設定ファイルを書いてもキャリブレーションが反映されなかった。なお、 xinput_calibrator は DPI を 150% にした状態では正しく動かなかったが、 100% の状態で設定したパラメータを 150% の状態で使っても問題はなかった。

一時的な反映については、マルチディスプレイ環境での液晶タブの調整 – yu_izumi’s blogに記載されている方法で行列に変換し、 Coordinate Transformation Matrix の形式に変換するととりあえず意図したとおりのところがタップされるようにはなった(ただしこのページの数式の係数の 0.5 は今回は不要だった)。minX, maxX といったパラメーターが、実際の広大な入力の値域のうちどこからどこまでが実際の画面であるかのパラメーターとみなして、元のキャリブレーションパラメータで導出される画面上の座標を新しいキャリブレーションパラメータで導出されるはずの座標に変換する行列を作るイメージ。

恒久的な反映としては、 xorg – Touchscreen calibration fails on Ubuntu 20.04 / PixelBook – Ask Ubuntuに書かれているように、 xserver-xorg-input-libinput を削除して xserver-xorg-input-evdev をインストールし、再起動してから xinput_calibrator を実行すると xinput_calibrator の出力形式が変わるようだ。 evdev の方を入れた状態で出力したファイルを /usr/share/X11/xorg.conf.d/99-calibration.conf に保存して再起動すると、正しく認識されるようになった。

ただし、これでもスリープ後等のロック画面などでは正常にタッチパネルが使えていないように見える。

(追記)Firefox では XINPUT2 の指定有無に関わらずあまりきちんと認識してくれないように見える。chromium そのまま問題なく認識してくれそうだ。

スクリーンキーボード

おそらくハードウェア固有の話ではないが、タッチパネルのみのデバイスでキーボードを繋がず運用したいときに必要になるスクリーンキーボードについて、 Ubuntu の設定の Universal Access のところから Screen Keyboard を有効にできるが、ファンクションキーどころかカーソルキーも見当たらず、それらを有効にする方法も見当たらなかった。

ウェブで調べてみた限りだと、以前のバージョンの Ubuntu でデフォルトだった OnBoard をインストールしてそちらを使っている人もいるようだ。こちらはこちらでテキスト入力画面で自動で起動する設定が試した限りだと動作しないが、キーが足りないよりは良いので一旦は OnBoard を使ってみることにした。

(追記)Ubuntu 20.04 + GNOME で、物理キーボードなしでタッチスクリーンを用いた場合、 OnBoard 使用中でも GNOME 標準のスクリーンキーボードが出てくるようだ。

その他

バッテリー残量が見えているが、 PC 自体を動かすためのバッテリーは搭載していないと思われるので何の数字か謎。84% などといった数字が見えており放置しても変化しないが、再起動すると変化することもある。(配送時の航空関係の申告はリチウム金属電池であってリチウムイオンではなかったし、 AC アダプタへの電源供給を止めると一瞬で電源が落ちる。また、 Windows 10 からはバッテリは見えなかったと記憶している。問い合わせで仕様を確認した際に no battery かと聞いたら 40mah と言っていたが、この理由からボタン電池ではないかと思っている。)

その他、試した限りだと microSD カードリーダー、 USB ポート、音量ボタン、電源ボタン、内蔵スピーカー、イヤホン端子は正常に認識されて動作しているようだ。手前の Windows ロゴ(Win10 では使えていた)は、この方法でセットアップした後にタッチしても何も起こらず、 xev でも何の反応もないようだ。

スリープ・復帰もそれ自体は正常に動作しているように見える。ただし、タッチパネルのところで言及した通り、スリープした際にロックしているようになっているとログイン画面では正常にタッチパネルが使えない。スリープしてもロックしないように設定すれば問題ないようだ。ログイン画面についてはキーボードを使ってもうまくログインできないようだったが、そもそもロックが必要な使い方をしない想定なので、自動ログイン ON、スリープ時にもロックされないようにしてそれ以上は追わないことにした。

挙動については  RAM4GB で Windows ほど何をするのも重いということにはならなかったが、 Firefox で試した限りでは YouTube の 1080p 動画は厳しいようだ。

(追記:そもそも存在を完全に忘れいていたが、 Win10 で使えていた加速度センサーは Ubuntu でも認識されているらしく、本体の向きを変えると画面の向きも変わるようだ。ただし、横にしたときの画面回転は想定通り[誰の?]動いているようには見えない。いずれにしてもタブレットパーツの流用の都合で設置されていると思わしきセンサーであって、少なくとも僕にとっては必要なセンサーではないので、正しく動作させるための検証をするつもりはない。)

PiPO X9s を買ってきた

持ち運びを想定していない、机に置く用のデスクトップタブレット端末である PiPO X9s (4+64GB 版)を買ってきた。

まず PiPO の端末の売り場はあちこちに色々あるが、どれがちゃんとしたところかよくわからなかったのでそこからというところだった。Baidu で「pipo」と検索すると、 http://www.pipo.cn/ が公式マーク的なものがついていたので、一旦ここから辿っていくことにした。(結果的に届いた商品のパッケージにも www.pipo.cn の記述があった)

今回はこのサイトの英語版の Contact Us ページに書いてある alibaba.com のリンクである https://pipotech.en.alibaba.com/ から購入した。なお Contact Us のところには公式のように見えるが公式ではないサイトが一つ注意喚起されている。

alibaba.com の会員登録にあたっては、 alibaba.com の上部の “Join Free” からだと会社名の入力が必須(しかもおそらく日本の不動産契約の書類に書くような個人が所属する会社としての記述というより、会社のアカウントとしての立ち位置だと思われる)になっていた。先に商品を選んで Contact Supplier を押し、そのタイミングで出てくるログイン画面から Join Alibaba.com を選択すると “I’m a non-business entity” というチェックボックスが利用可能になり、個人でのアカウントが登録可能になった。ここでチャットでやりとりし、在庫がなかったので在庫が復活するのを待って購入することができた。本体 179USD, 送料 50USD で合計 229USD で、香港から FedEx で送られてきた。(追記:後日FedEx から関税を支払うよう郵便で通知された。「その他税金(Consumption Tax/VAT)」が1000円、「関税その他税金についての特別取扱手数料(Duty Handling Fee)」が1000円で合計2000円だった。)

PiPO X9s と呼ばれる製品は過去に何度か X9s という名前のまま設計を変えているようだ。提供されている OS イメージやウェブ上の資料を見る限りだと少なくとも、

  • Windows 10 + Android デュアルブートモデル (OS イメージがある)
  • Windows 10 シングルブートモデル、電源電圧5V版(OS イメージがある)
  • Windows 10 シングルブートモデル、電源電圧12V版(新マザーボード版で、おそらく今回買ったものはこれ。 OS イメージ

が存在しそうに見える。その中でさらにバリエーションがありそうにも見える。

特に今回買った 12V 新マザーボード版は、ざっくり調べたところおそらくだが

  • 電源電圧(今回買ったもの:12V、旧版:5V (PIPO の X9s 紹介ページでも 2021/5/23 現在 5V ということになっている)。ドライバダウンロードも電圧で区別している)
  • タッチパネルコントローラー(今回買ったもの: Sileadtouch、旧版:Freaktab のやり取りを見るにおそらく Goodix)
  • メインボード(イメージダウンロードページのところに「注意此系统支持新主板,机器电源为12V!」と注意があるので、おそらく 12V 版はメインボードが変わっている)
  • 画面解像度(今回買ったもの:1920×1280、旧版:おそらく 1920×1200 (PIPO の X9s 紹介ページでも 2021/5/23 現在 1920×1200 ということになっている。Android 版のイメージのファイル名にも 1920×1200 を示唆する文字列がある)
  • UEFI (今回買ったものは NTFS パーティションからのブート不可、旧版と思われるイメージの説明書や、FreakTab でのやり取りを見るに、おそらく旧版は NTFS ブート可と思われる)

辺りが異なっていそうに見える。X9s という名前がついていても、見た目やできることは似ていても中身は旧版と別物と思った方が良さそう。従ってトラブルの際はウェブ検索で調べて X9s についての対処が書いてあっても、当てはまるかどうかわからない。

今回買ったものは負荷をかけてもファンの音はしていないようだ。

購入後、ドライバを

dism /online /driver-export /destination:C:\driver-bak

でバックアップして Windows 10 をクリーンインストールし、デバイスマネージャーからバックアップしたドライバを適用しようとしたが、いくつか挙動に問題があった。試行錯誤の結果、以下の感じでクリーンインストールした状態から、見た限り正常に動作するようになった。Sileadtouch はウェブ検索してみると中国製の格安タブレットに多く使われているようで、やや鬼門であるようには思われたが、結局のところはバックアップしたドライバか、 PIPO が公開しているイメージファイルで正常動作させられるようだ。

  • (そのままで当てられるドライバを先に当てたが、このタイミングでやらなくても良いと思われる)
  • “bcdedit -s testsigning on” で、未署名ドライバのインストールを許可
  • ウェブで調べた方法で詳細は覚えていないが、回復メニューから再起動を行い、ドライバの署名を強制しないモードで起動
  • デバイスマネージャーで不明なデバイスになっているデバイスを片っ端からドライバ更新を指定し、バックアップしたドライバのフォルダを指定してインストール
    • Sileadtouch について試行錯誤の結果、dism でバックアップしたものではなく別途公開されている OS イメージに含まれていたものにしたが、中身は同じと思われる
  • この時点で、なぜかタッチパネルが、短く押しても長押し判定されるようになっていた。もとのインストールイメージでも sileadtouch.fw というファイルがあるわけではなく、理由がなかなかわからなかった。
  • “bcdedit -s testsigning off” してテストモードを抜けて再起動すると、タッチパネルが誤って長押し判定されることがなく、正常動作した。理由はわからないが一旦これで進めることにした。
  • スタンバイや電源オフにしても液晶のバックライトが点灯したままになっていた。デバイスマネージャーで Microsoft Basic Display Adapter と表示されていたデバイスについて、 dism でバックアップしたドライバからの更新を試みると、数分経った後に Intel(R) HD Graphics として認識され、スタンバイなどの際はきちんと消灯するようになった。

Intel Atom x5-Z8350, RAM 4GB というスペックなので、 Windows 10 が動くとは言っても速くはないし、今時だとできることは限られている。この辺りはうまくカバーする使い方をする必要があるだろう。

また、液晶と実際に触れる面の間にまあまあの厚さのガラスがあるのか、斜めからタッチすると視差が出るようだ。形状・用途的には斜めからタッチすることも多いと思うが、慣れるしかない。

ちなみに Ubuntu については USB ブートで試してみた限りで、放置すると1分程度でスリープしたり電源が落ちたりする現象があったのと、タッチパネルが正常に使えなかった。ウェブの情報を見るに Silead のタッチパネルを Linux で動かしている人はいるようだが、おそらく Ubuntu そのままというわけにはいかないのと、1分程度でスリープする現象についてはまだ追っていないので、入れようとすると苦労しそうだ。(追記:結局 Ubuntu はインストールできた。PiPO X9s (12V 版)に Ubuntu Desktop 20.04 をインストール参照。)

なお、技術基準適合証明やそれに類する記述は見当たらなかったし、そもそも日本市場を意識しているとも思えないので、おそらく内蔵の無線は日本では合法には使えないと考えて無効化した。内蔵の有線 LAN で困らない場合もあると思うが、今回は小さく安い USB WiFi を背面ポートに刺すことにした。特に邪魔にはならない(実運用上は、今回使わないアンテナや、 AC アダプタの端子の陰に埋もれる)と思われる。

WiFi アダプタを刺した様子

PIPO X9s 背面に ELECOM WDC-150SU2MBK を刺して上から見たところ

(追記)書き忘れていたので追記。PC として機能させられるだけのバッテリーは搭載しておらず、AC アダプタを抜くとすぐに電源が落ちる。輸送時には UN3091 のラベルが貼り付けられ、チャットではバッテリーについて確認した際にバッテリーなしではなく 40mAh と言っていたので、おそらくこれがボタン電池かそれに近いものを刺していると思われる(が、分解するためのねじ穴にアクセスするには接着されたゴム足を外す必要がありそうなので、分解しての確認はしていない)。少なくとも UN3091 はリチウムイオンバッテリーではないので、品質の低いリチウムイオン電池が問題を起こす心配はなさそう。

千葉県の福岡の桜並木に行ってきた

桜が満開になる季節になってきたので、千葉県にある福岡の桜並木(リンク:千葉県観光物産協会による紹介サイト)に一昨日ドライブに行ってきた。道沿いに断続的に桜が咲いていてなかなか良い感じだった。

「福岡の桜並木」では使った車のカーナビに登録されておらず、鹿野山神野寺への道として設定しても周辺の道としては見当たらなかったが、結局は近くのコンビニで車を止めている時に Google マップで「福岡の桜並木」検索したところ見つかった。鹿野山 福岡口(リンク先は Google マップ)の T 字路から県道163号を西に進めばよいようだ。上の方に分岐があって片方は時間帯指定で進入禁止、かつ進入禁止の道もそうでない道もすれ違いができない道に見えたので、そこで引き返してきた。

下りの動画(ダウンロード

入り口

福岡桜並木入り口

反対側から(帰り)

中ほど(下り)

福岡桜並木中ほど

(投稿してから思い出したので追記)しかしこの日は渋滞が激しかった。カーナビはとにかく首都高を避けようとしていたし、実際のところアクアラインでは以下のような表示が出ていたのでカーナビに従って、浮島から湾岸線に出ず、殿町から出てあとは下道で帰ってきた。
2021/3/26 渋滞(湾岸環八から辰巳まで渋滞15km70分)

このブログを(多分) The Privacy Sandbox の FLoC による演算から opt-out した

最近、 Google が The Privacy Sandbox なる試みを行っているようだ。現在の広告その他のエコシステムを保ったままプライバシーを改善することを狙っているようで、 The Privacy Sandbox 自体が仕組みの名前というよりは複数の仕組みを作ることを通してプライバシーを改善するプロジェクトとして存在しているようだ。とはいえ、やはりサードパーティー Cookie を廃止するための代替としての、ブラウザ側でユーザーの閲覧履歴の分析・学習を行って、嗜好を知りたいサイト側にはどのグループ(Cohort)に属しているかだけを通知する FLoC が一番取り沙汰されているように感じる。

調べてみた感じでは現在のところ、広告のための学習のためにプライベートな情報を使う機構を今からわざわざ追加するモチベーションがあるとは思えない Firefox や Safari をどうするつもりなのかといった情報は見つけられなかった。もし少しでも Chrome 以外のブラウザを排斥する意図があるのであれば、それは Google によるインターネットの支配であり、オープンなインターネットの終焉であり、同一の事業者の広告が貼ってある複数ページの閲覧履歴を束ねて追跡されることよりもずっと危険な問題であると思うが、情報がない以上何とも言えない。

また、一応は学習を担当するブラウザベンダと学習結果を実際に評価できる広告事業者が別々の役割として存在しているわけで、何をどうやって学習するのかもよくわかっていないが、そのあたりは追っていない。加工されているとはいえ FLoC システム全体の学習のために、閲覧履歴をもとにしたデータをブラウザベンダとやりとりするというのであれば、ブラウザベンダが持つ権限は今よりずっと大きなものになりそうだと思っている。

ただし、少なくとも現時点で、明示的にサイト側で対応しなければすべてのサイトを学習の対象にしようとしているようだった。www.chromium.org ドメインにある The Privacy Sandbox のページからリンクされている GitHub リポジトリで WICG/floc: FLoC というものがあり、そこに現時点では以下のように記されている:

A site should be able to declare that it does not want to be included in the user’s list of sites for cohort calculation. This can be accomplished via a new interest-cohort permissions policy. This policy will be default allow.

opt-in 形式にした方が良いというプルリクは上がっており、まだ close はされていないようだ: Opt in cohort training by dmarti · Pull Request #42 · WICG/floc

従来では一応、関連の広告事業者の広告を表示する(といっても各社、広告にはなぜか自社ロゴではなくわざわざ似たような (i) のロゴを設置していて、マウスオーバーしない限りどこの事業者の広告かはわからないことが多いが)か、表示しなくとも関連の広告事業者に追跡させるためのコードを明示的に書いたページのみが対象になっていた。従って opt-out しなければ学習の対象になるというのは、従来と比べると随分学習に使うデータを乱暴に増やそうとしているように感じる。

opt-out するための方法は一応準備されている(まだ正式仕様ではないので、変わるかもしれないが)。

For example, a site can opt out of all FLoC cohort calculation by sending the HTTP response header:

Permissions-Policy: interest-cohort=()

従って関係ないサイトの広告のために閲覧履歴を使用されたくない場合は以下のようなヘッダを追加することになる。一応ブラウザから直接出る外部に値というわけではないものの、これらをもとに学習されたデータは任意のサイトから読みだされることになるし、学習の過程でブラウザベンダとの通信も発生すると思われることから、おそらくセンシティブな情報を扱うのであれば入れた方が良いだろう。

Permissions-Policy: interest-cohort=()

本質的にクライアント側の挙動であり、サイト側というよりはブラウザをインストールした側の責任ではある。とはいえ、プライバシーに寄せましたと主張しながら関係ないサイトの情報も広告に使うというのは、個人的には賛成できるものではない。そのため、せめてもの抵抗として、(ちゃんと排除できているか確認はできていないものの)このブログは interest-cohort は許可しないようにヘッダを追加した。これを理由に Google 検索の順位が下げらなければ良いが。

fontconfig の優先順位を調整して中国語フォントより日本語フォントを優先する

Ubuntu MATE 20.04 を使っていて、日本語で表示されるべきものがいわゆる中華フォントになってしまった(後述するがこれ自体は Ubuntu MATE のせいではなく自分の操作によるものだった)ので、フォントの優先順位を修正して日本語フォントを優先するようにしたのでメモ。

まず、フォントの優先順位そのものの設定は /etc/fonts/ で行われているようだった。調べてみると Linuxでアップデートしたら中華フォントになった件について(修正方法) – Qiita に、 Noto シリーズの JP のものを serif, sans-serif, monospace それぞれのエイリアスに追加する良い感じの fontconfig の xml があった。この記事では /etc/fonts/local.conf に置いていた。

これをもう少し管理しやすい場所に置きたかったので調べてみたところ、このファイルは /etc/fonts/local.conf ではなく $HOME/.config/fontconfig/fonts.conf に置くことで、管理者権限なしに自由に修正できるようだった。世代によって推奨される場所が変わったりはするようだが、そんなに特殊な置き場所というほどでもないようだ。

さらに、これは /etc/fonts/conf.d/50-user.conf によって呼び出されていた。この後で優先順位を変えて絞り込んだところ、/etc/fonts/conf.d/56-kubuntu-noto.conf というファイルで Noto 関係のフォントにエイリアスが指定されており、これより前に読み込めば、通常の漢字表示が日本語フォントになるようだった(先ほどの /etc/fonts/conf.d/56-aaa.conf にすれば日本語フォントになり、 /etc/fonts/conf.d/56-zzz.conf にすれば中国語フォントになった)。おそらく Kubuntu を追加でインストールしたときに変わってしまったのだろう。

その後に読み込まれるファイルを漁ってみたところ、 /etc/fonts/conf.d/64-language-selector-prefer.conf というファイルがあり、 Noto の中で、どの言語から順番に表示するかの優先順位が設定できるようになっていた。手元の環境だと JP のものが一番優先になっていたので、おそらく Kubuntu をインストールする前はこのファイルによって日本語フォントが優先されていたのだろう。

ということで結局この環境では

sudo ln -s /etc/fonts/conf.d/64-language-selector-prefer.conf /etc/fonts/conf.d/52-japanese.conf

としてこのファイルの優先度を上げることでほぼ解決できた(すべてのアプリケーションではない模様)。似たような問題が起きた時や他の理由でフォントの優先順位を変えたいときも、この辺りのファイルから見ていけば良さそう。

sshrc の内容に関するメモ: Xforward で必要

ssh で X 転送しようとすると次のようなエラーが出て困っていた。ぐぐってもよくわからなかった。

PuTTY X11 proxy: Unsupported authorisation protocol

原因は色々あるようだがググって出てきたものがなかなか当てはまらなかった。別サーバと比べたりしていたところ、 .ssh/rc を置いている場合、 /etc/ssh/sshrc が呼び出されないため、この内容がないと困ることがわかった。man sshd すると SSHRC の項に説明とサンプルファイルがあり、これが .ssh/rc を置いていることに阻害されていただけだった。.ssh/rc に man の内容に従って xauth 関連の記述を追記すると繋がった。

Win10 で使っていた SSD (Crucial MX200)の完全消去でハマった

Crucial MX200 SSD を ThinkPad W550s で、 Windows 10 Pro で使用していたが、新しい PC を買った後しばらく経ち、 Ubuntu MATE に入れ替えようと思ったため、一旦 SSD のデータを消去しようとした。その際、ハマったのでメモしておく。

まず、 SSD の secure erase はハードディスクと異なり、 SSD に対してコマンドを発行することで行えるようだ。それ自体の手順は Solid state drive/Memory cell clearing – ArchWiki に記されている通り、一度 hdparm でパスワードを設定した後、 hdparm で –security-erase オプションを使用すればよいようだ。frozen 状態に注意するよう注意書きがあった。SSD はハードディスクと異なり使用中の領域かどうかを管理しているようなので、性能上も security erase して使うのが一番良いように思えた。

しかし、今回の SSD では、これをしようとすると、エラーが出た。エラーの内容は記録するのを忘れてしまったが、コマンドの実行で何かバッファでもあふれているかのような、怪しいエラーメッセージだった。その時ウェブ検索していた内容から見るに、bad/missing sense data といったことが書いてあったようだ。この時開いていた、hard drive – hdparm error: SG_IO: bad/missing sense data – Super User の質問のエラーメッセージ(以下に引用)と同じようだ(数字の羅列が一致するかはわからない)が、状況は違うように思えた。

sda:  Issuing SECURITY_SET_PASS command, password="PASSWORD",
user=user, mode=high SG_IO: bad/missing sense data, sb[]:  70 00 05 00
なお先の ArchWiki で書かれている frozen かどうかは、それらしい行がこの時は見当たらなかった。そもそも、Security の項がなかった。

また、先頭 593MB は読み書きできるものの、それ以上は Input/output Error で読み書きできない(dd if=/dev/sda of=/dev/null bs=1048576 count=1000 で簡単に確認できた)現象にもなり、削除せずに使い続けることもできなかった。

色々調べた結果、忘却の彼方: Crucial M500/M550/MX100とSecure Erase に、 Windows 8 以降ではいくつかの SSD において、ディスクのセキュリティ機能を変更できなくなるような修正を加えており、 PSID を復旧すると元に戻る旨が書かれていた。特に今回は BitLocker を使っていた端末でもあり、暗号化された領域にロックがかかっていたりしても不思議ではないように思えた。

結局のところ、 PSID をリセットする操作が必要であり、これを行うと無事に他の操作も行えるようだ。Crucial の SSD であったので、 Crucial Storage Executiveをインストールしたパソコンに、 USB-SATA で当該 SSD を接続し、「PSID を元に戻す」を押すと、データが消去される旨が表示され、その後無事 SSD を利用することができた。hdparm -I でも Security: の項目に frozen かどうか、表示されるようになった。security erase も ArchWiki の手順で成功した。

ISUCON 10 予選に参加した

いつものようにチームワイハリマで ISUCON 10 予選に参加していた。今回はいつもにもまして手も足も出ない状態だった。

今回は競技に関するルールが事前に公開され、当日の競技開始と同時に ISUCON10 予選マニュアルが公開された。

今回は競技開始後もなかなかサーバに入れなかったり、ポータルが終始不安定でベンチマークも運が良い時しか走らせなかったりした。まずはざっくり画面を操作して機能を把握したうえで、ベンチマークが走るようになったら重いクエリがどこにあるかなど、徐々に詰めていった。また、サーバは 3 台与えられた。EPYC 1vCPU, RAM 1GB なのは良いとして、ディスクが 10GB なのが目に付いていた。

まずは目に付いたいくつかの重い検索クエリを軽くしようと、インデックスを色々張ってみたり、 SQL の外で実行しようとしたり、そもそもウェブアプリケーションの外で実行しようとしてみたりしたが、特段速くはならなかった。SQL が詰まっていたので専用サーバにしたことも、効果を発揮しなかった。recommend では条件が 6 つ OR で繋がっているのを、データの入力を工夫して一つにまとめてみたが、これもうまくいかなかった。

検索が重いことが分かっていたので、レプリケーションを行って検索系クエリを逃してみたが、却って遅くなった。3台のマシンすべてを使うことで CPU 使用率が 100% のマシンはなかったが、全体に CPU 負荷があまりかからなかった。レプリケーションを有効にするためにバイナリログを有効にしたが、これが問題になったようだ。後で考えてみれば、ディスク 10GB に目がついていたが、このディスクが低速で(今となってはわからないが、 SSD ではなく本当にディスクだったのだろうか)書き込みもそれなりに詰まっていた可能性がある。

また今回は、いくつかの最適化を試みた時から、互換性を失わないと思われる変更でベンチマークが通らなくなる現象にも苦しんだ。json_encode 周り及び、 PDO から SQL の結果を受け取る時に独自のクラスで受け取るもとの実装について、どこがしかの挙動を変えてしまったようだが、デバッグログの出し方がわからなかったこともありデバッグには終始時間がかかっていた。

もともと PHP 実装を選択した後一度も Go の初期実装スコアを超えていないことに加え、最終的にはベンチマークでの互換性テストすら通らない状態となり、 0 点となった。高速化視点での実力不足とは別にも、色々と反省すべき点を整理したほうが良さそうだ。

Ubuntu MATE 20.04 を GPD Pocket 2 にインストール

(追記)Ubuntu MATE の公式ダウンロードページ に GPD Pocket 2 版の Ubuntu MATE イメージが公開されているようなので、今後はこの記事の方法ではなくそちらを使った方が良いかもしれない(既にこの記事の方法でインストールしてしまったので検証はしていない)

Ubuntu MATE 20.04 を GPD Pocket 2 にインストールした。

まず、 Ubuntu MATE のダウンロードページには GPD 用のイメージは 20.04 はなかったので、標準イメージの 20.04 をダウンロードした。これを Rufus で USB メモリに焼いてインストール。WiFi は最初から見えているので、とりあえずインストールは通常通りの手順で行える。画面は 100% スケーリングかつ X 起動後は向きもおかしいが、とりあえず首を90度傾けてどうにかする。

インストール後、実際に使えるようにいくつか追加していく。Ubuntu MATE 18.04 の UMPC ポートのページを見るに画面、タッチパネル関係が主のようだ。WiFi はこのページで言及されているが、 Ubuntu MATE 20.04 と GPD Pocket 2 の組み合わせではそのまま認識した。ファンコントロールはリンク先の GitHub のコードを見る限り OS 組み込みのように見える。GRUB などの、 X 起動前は、なにもしなくとも正しい向きで表示されるようだ。

なので、さきほどのページからリンクされている https://github.com/wimpysworld/umpc-ubuntu のリポジトリから必要な項目だけを持っていくことにした。

まずは X 起動後に画面が 90 度傾いていることを解決する。画面が傾いているだけなら GUI から画面設定をいじればよいが、それだと今度はタッチパネルが 90 度傾いた状態で作動し、よくわからない状態になる。加えて GUI から画面設定を修正した場合はログイン前の画面などが直らないため、今度はログイン前にタッチの場所がずれることになる。なので、両方設定ファイルを修正するのがよさそう。先ほどのリンクから 40-gpd-pocket2-monitor.conf を /usr/share/X11/xorg.conf.d/ に、 99-gpd-pocket2-touch.rules を /etc/udev/rules.d/ にコピーし、再起動すると画面の向きは正常になった。

DPI を上げる設定はいくつか方法があるようだ。ただし、 Ubuntu 20.04 から正式導入された fractional scaling の機能は、検索した限りだと MATE に来ている様子はなかった(少なくとも見つけられなかった)。100% だと小さすぎるが 200% だと大きすぎる場合、ほかの方法は、そもそも実際より小さな解像度に見せかけるか、 xrandr で実際より大きな解像度でレンダリングして HiDPI 扱いで 200% にする Mac の Retina ディスプレイみたいなやり方か、 テキストの DPI 設定だけ大きくする(GUI で設定可能)か、といったあたりのようだ。HiDPI – ArchWiki にだいたい載っていた。とりあえず、いくつかの UI 部品が小さく表示されるものの、それ以上に厄介な問題を生じにくそうなテキストだけ DPI を GUI の設定画面で大きく設定することにした。

Firefox でタッチパネルを使うとスクロールすらできない問題が起こった。これは MOZ_USE_XINPUT2=1 という環境変数を入れることで、 Firefox 側の設定を変更し、正しく動作させることができたので、 ~/.xsessions に設定した。

純粋な CUI の文字サイズが小さい点は実用上どこまで問題になるか不明だが、一応先ほどのリポジトリを参考に、 /etc/default/console-setup の FONTSIZE を 8×16 から 16×32 に変更した。

ほぼタッチパネル液晶周りしかいじっていないが、ハードウェア依存な部分は一旦これで使い始められそうだ。解像度回りを考えると素の Ubuntu の方が楽かもしれないが、致命的ではないので、ひとまずは好みを優先して Ubuntu MATE でしばらく使ってみることにする。

(追記)99-gpd-pocket2-touch.rules は MATE じゃない素の ubuntu-desktop で使う場合は不要というかあると回転が狂うようだ。この 9 つの数字は3次元の回転行列のようなので、単位行列、すなわち 1 0 0 0 1 0 0 0 1 を入れたときに素の Ubuntu では正しく、今度は Ubuntu MATE では正しく回転が認識できない状態になる。

色々試した結果、 99-gpd-pocket2-touch.rules は有功のまま、さらに次のコマンドを打つとどちらからでも正しくタッチパネルが使用できる状態になった。これを GUI から Startup Application に登録したところ、ログイン前の MATE の画面、ログイン後の MATE の画面、ログイン後の ubuntu-desktop の画面がすべて正しくタッチできるようになった。

xinput set-prop 'pointer:Goodix Capacitive TouchScreen' 'Coordinate Transformation Matrix' 1 0 0 0 1 0 0 0 1

(追記)音が鳴るようなタイミング(通知音が鳴るようなタイミングや、ブラウザで動画の再生が始まった時)で、たとえスピーカーをミュートにしていてもスピーカーから「カッ」という音がする現象があった。確認できていないが個の挙動としてはそもそも使わない間はスピーカーの電源を切っているのだろうか。Popping sound on speakers when starting 19.3 (Solved) – Linux Mint Forums の記事を見ると省電力設定を解除しているようだ。lsmod を見るとこの端末もこの記事の設定ファイルと同じ snd_hda_intel を呼び出しているようだったので、/etc/modprobe.d/alsa-snd-hda-intel.conf を次の内容で作成して再起動すると直った。

options snd-hda-intel power_save=0

(追記)WiFi はこの設定で動作しているものの、明らかに見えるはずの SSID を掴めないことが多いように感じる。/lib/firmware/brcm/brcmfmac4356-pcie.txt についても対応したほうが良いかもしれないので試しに入れているが、再現方法すらわかっていないので何とも言えない。