ルータの自由度を上げるために Protectli Vault FW1 を買ってきた

現在家のルータは RouterBoard RB3011-UiAS-RM を使っているが、Protectli Vault FW1 の存在を知り、より自由度が高い遊べる環境を用意しようと思って購入した。

買い物

今回は Amazon.com で買ってきた。Amazon.com でのページは Firewall Micro Appliance With 4x Gigabit Intel LAN Ports, Barebone だが、今は全く同じものは売り切れているようだ(同じシリーズの他のものはある)。買ったときは $199.00 で、それに送料 1,272 円と Import Fees Deposit 1,915 円(多分ドル建てで決まっていたはずだが、 Invoice では JPY になっている)がかかった(勤務先にはこういう時に使える会社の費用補助があるので自己負担はもっと少ない)。

今回購入したのはベアボーンなので、 RAM と SSD を買う必要があった。 RAM は DDR3L で最大 8GB、 SSD は mSATA で、それぞれ次のものを買った。

なお、どちらも滅びかかっている規格のようで、 DDR3L RAM はいくつかの店にあったが、 mSATA SSD は秋葉原ではそもそもほとんどの店に存在せず、あっても 8000 円以上するモデルしか見当たらなかったため Amazon で購入した。ちなみに、 RAM は刺さないと画面にも何も映らないので、動作確認には最低でも RAM が必要。

届いた商品

マザーボードはこのような感じになっている。マザーボードに YANLING のロゴがあるので委託先かもしれない。YANLING のページを見ると、YANLING の N10Plus がほぼ同じ製品であるように見える。筐体裏面には Made in China と書いてあり、時計も中国の標準時に設定されて出荷されてきた。

ファンレスなので音もせずとても静かで、大きさもさすがにポート数の同じスイッチングハブよりは大きいものの、それと比べたくなる程度には小さい(普通の L3 扱えるルータと比べるとむしろ小さい気がする)。

また、 BIOS には「電源オン状態で電力供給が途絶えた場合、電力が復活したら自動でオンに戻る」設定があり、標準で有効になっているようだ。BIOS 画面で AC アダプタを引っこ抜いて落ちた後アダプタを戻したら、自動で OS が起動した。ルータは常時起動していることを想定するので、この機能はありがたい(hp ML115 でも見た気がするので、デスクトップパソコンをあまり使わないから知らないだけでよくある機能なんだろうか)。

なお、 AC アダプタは Protectli 40W Power Supply – Protectli の商品画像と同じ、 CHANNEL WELL TECHNOLOGY なる会社のものがきた。商品紹介ページでは 110-240V と書いてあったり FAQ では 100-240V となっていたりするが、商品画像と同じく 100-240V と書かれたものがきた。アダプタ本体とケーブルの間は PC やモニタの電源でよく見る端子なのでその辺で買えそうなケーブルだった。日本でそのまま使える type-A だがアース付きなので、タップにアースがない場合は3ピン→2ピンをかますか、ケーブルを買い替えることになると思われる。

Ubuntu MATE で動作確認

まず最初に、 RAM だけ買って SSD なしの状態で Ubuntu MATE のインストーラの USB メモリを刺したところすんなり GUI が立ち上がった。

電源ボタンも Ubuntu MATE 側できちんと認識して、押されたらダイアログを出すなりなんなり OS で設定した動作をするようだ。

VyOS 入れてのテスト

SSD が到着したら、とりあえず VyOS を入れてみた。FW1 FW2 FW4A Series Hardware Overview – Protectli の説明通り、 WAN が eth0、LAN が eth1 に割り当たっていた。

また、添付のケーブルを使うことでシリアルポートも利用できた。BIOS 画面をシリアルポートに転送する機能がついていて、 OS が起動した後は OS から見えるようになっているので VyOS もシリアルポート越しに利用できた。VyOS では GRUB で Serial console を選ぶと起動画面もシリアルで流れてくる( GRUB は VGA とシリアルポート両方に表示された)

ただし、 BIOS 画面が出ている状態でのシリアルポートは How to use the Vault’s COM port – Protectli の説明通り 115,200 bps なのに対し、 VyOS の初期設定は 9,600 bps なので、切り替えないと途中で画面が表示されなくなる。BIOS も VyOS も設定項目はあるようなので、使うならどちらかに統一しておいた方がよさそう。

VGA あるから家ならそちらを使えばいい感はあるが、 GPD microPC とか持っていたらシリアルポートが利用できるのが便利なのかもしれない。

インストールしたら、次の二つを参考に VyOS で NAT 構成してみた。まだファイヤーウォールなどは設定していない。インストールも含め、特に問題らしい問題は少なくともデバイス由来のものは起こらなかった。

簡単な速度測定

この状態で、ざっくり NAT 越しに速度を測定してみた。

Protectli で NAT を構成し、 ThinkPad を LAN 側に、部屋の LAN WAN 側にして、部屋の LAN においた ML115 (の上に増設された何かの NIC)と、 ThinkPad の間で NAT 越しの iperf を試してみた。

iperf

[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-20.0 sec  1.65 GBytes   709 Mbits/sec

通信中の Protectli Vault の top

%Cpu(s):  0.0 us,  0.1 sy,  0.0 ni, 99.3 id,  0.0 wa,  0.0 hi,  0.6 si,  0.0 st
KiB Mem:   8051500 total,   286864 used,  7764636 free,    31692 buffers
KiB Swap:        0 total,        0 used,        0 free.   138536 cached Mem

(追記:この後 ThinkPad を測定用とせずデスクトップ/サーバ構成のマシン同士で測定したところ、簡易測定でもスループットが 930 Mbps を超えたので、Protectli Vault FW1 + VyOS のせいで 800Mbps を下回っていたわけではなさそう:VyOS スループット測定 on Protectli Vault FW1 | にろきのメモ帳
(追記:↑しかし ThinkPad も状況により 900Mbps を超えたので原因はよくわからない)

php-fpm on Ubuntu での謎エラーの解決

Ubuntu 18.04 + php-fpm 7.2 + NextCloud で、

Zend OPcache can't be temporary enabled (it may be only disabled till the end of request) at Unknown#0

のようなエラーがログに大量に貯まるので調査。色々ぐぐったところ、 opcache.enable を複数回設定しようとするとよくわからないエラーとして登場するようだ。とりあえず、 /etc/php/7.2/fpm/pool.d/***.conf から opcache.enable と opcache.enable_cli をコメントアウトし、 /etc/php/7.2/fpm/php.ini では有効化されているのを確認することでエラーメッセージは消えたが、想定通りになったかどうかまでは確認できていない。

Windows 版 OpenVPN をクライアントにする時、ローカルで鍵ペアを生成して CSR だけ送る

(2022/12/19 追記)OpenVPN の新しいバージョンにも easy-rsa は同梱されているが、 MSI インストーラー版でデフォルトではなくなっているのと、どちらにせよこの手順では通らない模様。今なら WSL が選択肢に挙がるので、 WSL から openssl コマンドで鍵だけ発行したほうが楽だと考えられる。 OpenSSL での証明書発行手順メモのページで説明したもののうち自己署名を省いた手段とることができる。

OpenVPN でサーバを構築する方法は2x HOW TO | OpenVPNなどのページに掲載されていたりするが、 Windows 版で新規クライアントに対して easy-rsa を用いつつ秘密鍵を端末から出さないで証明書を得る方法について。何分目新しいものはないが、こういうのは既にサーバが立っていると手順通り以外したくなくなる病になりがち(特に easy-rsa で微妙にラップされているので余計になりがち)なのでメモ。基本的にはEasy_Windows_Guide – OpenVPN Communityの簡略版。

クライアント側

  • Community Downloads | OpenVPNよりクライアントをダウンロード
  • インストール。この時、インストールするもの一覧で、 EasyRSA をインストールするオプションのチェックボックスを忘れずにつける。
  • cmd.exe を管理者権限で開く

init-config は vars をリセットするのでインストール時のみ実行。notepad では “set KEY_” で始まる行の環境変数を適宜設定。client-name は(ca の中で)一意なものを設定。

> cd "C:\Program Files\OpenVPN\easy-rsa"
> init-config
> notepad vars.bat
> vars
> clean-all
> build-key client-name

client-name.key と client-name.csr ができるので、 csr は VPN 設計的には秘密にする必要はないので OpenVPN サーバを管理できる端末に送る。key はクライアント端末から出さない。

サーバ側

# cd easy-rsa # ここを読んでいる時点でeasy-rsa のディレクトリが既にあるはずなので移動
# vim ./keys/client-name.csr # コピー方法はなんでもよいが、ここに csr を配置
# . ./vars
# ./sign-req client-name

これで、 ./keys/client-name.crt に証明書が発行される。これも秘密にする必要はないのでクライアント端末にコピーする。

ISUCON 8 予選に参加した話

ISUCON 8 の予選にチーム「ワイハリマ」として yuta1024, yabuuuuu とともに参加していた。ソースコードは GitHub で公開: yuta1024/isucon8 yuta1024/isucon8-infra

一瞬だけなぜか 47k というスコアが出るも、最終的に、最後の方は 33k-36k 程度をさまよいつつ最後の提出が 35,379 点。予選通過ラインは 36,471 点だった模様。競技中は予選通過はもっと遠いものと思っていたら、もう一工夫どころか下手したらベンチマークガチャの引き程度で超えていたかもしれない程度まで近づいていたのか…… 思うところは色々あるが来年がんばりたい。

ということで思い出せる範囲で、自分が実施したことをメモ。

競技前準備

当日の集合のことと、 GitHub のプライベートリポジトリを使用することを決定。その後、個人的な用事により旅立ってしまい前日に戻ってきたが、その間に yuta1024 と yabuuuuu はその間にアプリケーションの配布ツールや想定されたミドルウェアの設定、 SSH 公開鍵配布などを準備してくれていたようだ。ISUCON の日程も自分の不在もずいぶん前からわかっていたし、数日前だと全員いたとしても時間が潤沢にとれたわけでもないので、もう少し早めに(例えばディストリビューションがわかった時点で)動くべきだった。

競技開始

当日集合し作業開始。作業時間は当初のアナウンス通り、 10:00-18:00。

まずは問題を把握。題材はイベントの予約サイトで、管理者はイベントの追加や売り上げの集計が行え、ユーザは席の予約(ランクだけ選んであとはランダム)とそのキャンセル、自分の予約状況の確認が行える。テーブル構成は先ほどのリポジトリの isucon8/db/schema.sql にもとのものが上がっているが、概ねの構成は以下の通り。全てのイベントを一つの会場で実施していることになかなか気付かず、理解するのに少し時間がかかった。

  • ユーザのテーブル。ユーザごとに一行で、普通。
  • イベントのテーブル。公開されているかや価格(一番安い C 席の価格。上位席は席のグレードごとに決まった金額(後述)が加算)などが格納されている。普通。
  • 席のテーブル。S席(番号1-50で価格は(C席と比べた差額が)5000円)みたいなのが S, A, B, C の 4 種類、 1000 席あり、これで 1000 行を構成している。それぞれに id とは別に種別ごとの ID もついている(例えば A 席なら id=51 が 1 番、 id=60 が 10 番……)。なお、会場は一つしかないようで、この席とイベントの相関はない。中身は不変。まあなんというか、要するに明らかに無駄が多い。
  • 予約テーブル。予約ごとに1行だが、キャンセルした予約も参照することがあるため論理削除しか行われない。しかも、キャンセルフラグはわかれておらず canceled_at の時刻が NULL かどうかで判定している。席の空き状況もここで管理しているようだ(ただ、 UNIQUE KEY で二重予約が防止されている)。初期データで19万行程度あるが、そのうちキャンセルされていないのは 15k 程度しかないようだ。もちろん構成としては席テーブルよりはわかるがここも色々と問題になりやすそう。
  • 管理者の一覧。あんまり見ていなかったが、結果的にこれをいじるようなリクエストはあまり問題にならなかった。

また、今回は PHP を選択した。その場合、初期実装は Slim フレームワーク利用だった。時間はかかるが脱却すると速くはなる気はしていたのだが、初期ベンチで明らかに SQL が重かったこともあり、最後まで Slim に載せたままだった。初期状態でスコアは 1k 程度。

与えられた VM が 3 台あったが、初期実装は一台で動作するものだった。

初動

アプリケーションのロジックを主担当とすることになり、ミドルウェアの設定は残りの二人に任せてとりあえず VM のうち 1 台を使って調査開始。最初にどうにかすべきと判断したのはとりあえず席の一覧(1000件)取得後にその一件一件に対して予約状況を確認する SQL 文を発行していたこと(修正途中、別方面で分析を進めていた二人からもここがやばいと報告あり)。席テーブルの内容をハードコードし、ざっくり書き換えたのと、他の二人のミドルウェア改善と合わせてこの時点で 10k 突破(ただ、ベンチごとの揺らぎが激しく、同じコードで 5k を下回ることもあった)

これでも mysql の CPU 使用率がほとんどなので、これはデータベースチューニング回になると判断。

中盤

とりあえず見るまでもなく修正する点をつぶしている間にミドルウェアの整備が進んで kataribe や MySQL のスローログが使えるようになった。/admin/ や / が重いとわかるが、純粋にデータ量が多いため他と同じ処理時間になるわけもなく、他のボトルネックの検討も含めて相談。予約済みのもののみに興味があるクエリでは明らかに無駄で、特にキャンセル済み判定にインデックスが使えていないという yabuuuuu の指摘もあり、キャンセル判定や最終更新時刻など、テーブルにカラムをいくつか追加。変更点は ALTER やサブクエリを使えば SQL 文で完結しそうだったので /initialize の init-db.sh の修正を行い、保存された sqldump には手を付けなかった(その方が後々の変更も楽だし)。追加で必要となったインデックスも追加。

なお、空席選択のコードは初期実装では「空席の中からランダムに選ぶ」になっていたが、ランダムで通るならルール上はどのような規則で選んでも構わないと判断して、手を加える必要があった際にデバッグのしやすい「条件を満たす空席のうち id が最も若いものを選ぶ」コードを書いたところ、「ランダムではない」ことがシステムにバレて失敗扱いになったのはおもしろかった。検出のロジックが少しだけ気になった。

またついでに、潰せそうな SQL 文(SHA256 のためだけにクエリ発行しているクエリなどもあった)も潰してみたが、こちらは効果がほとんどなかった。

この間に他の二人が、ミドルウェア周りの整備および関連コードの修正を進めて DB×1, FE×2 構成に変更になった。MySQL が入っているマシンは MySQL が本気を出せるようになり、この段階で 30k 突破。一回だけなぜか 47,473 点をマークしたが、ベンチを走らせた本人曰く「修正で想定以上に改善したと思ったら、修正が反映されていなかったのに一回だけスコアが上がった」とのことで、理由は謎に包まれている。

また、この時点で必然的に環境が共有になったため、誰かがデプロイをしたくなっても他の人の作業を待つ必要があり、複数台にデプロイする手間も相まってデプロイ頻度が低下してきた。

終盤

時間があれば実施したいことは山ほどあったが、残り二時間を下回ってはそうも言っていられず、改善できそうなところから修正。複数クエリにまたがるトランザクションの削減などを試みるも、効果は限定的。相変わらずベンチごとにスコアが揺らぐ状況は続いていた。

最後の30分はベンチマークガチャに充てよう、などと話しつつ、終了30分前になって実施した再起動試験で、なんと 502 Bad Gateway になるという事件が発生した。再起動後も正常に稼働できるようになっていないと、レギュレーション上当然ながら失格となってしまうため全員で慌てて対処し、かろうじて残った約5分でベンチを回し始めたが、最後のベンチが0点でなすすべなく☀となることは避けたかったので、 17:59:10 に走行し終えたベンチを最後に終了。その時は予選突破はもっと遠い点数であり最後のベンチの点数こそが自分たちの成績になると思っていたが、結果を見た今ではもう一回回していれば結果は変わったかもしれないという大変微妙なところにいたと言える。

反省会

競技終了後、準備不足であったことを感じながら、移動および夕食のため池袋に向かった。サンシャイン60通り商店街周辺から探索を始めたが、三連休の中日の夜でどの店も長い列ができており、徐々に南下しながら探索を行い、最終的には東通り(JR 池袋駅南口の東南東)に到達した。この間に早くも ISUCON 運営の方々による再起動等の試験・集計が完了して公表され、予選突破ラインとの差がベンチマークガチャ程度の差であったことを知った上で、反省会が始まった。

感想

ウェブアプリケーションとして素直な構成でありながら、最初に一台構成で組まれたコードを複数台に分散する要素が活用されており、奇をてらったり知っているかどうかを競うだけのゲームになったりもしなかった。そのため、チューニングらしくて良いと思った去年にも増して楽しめる競技だった。

そして、そのような素晴らしい競技で今回は惜しいところで本選出場を逃したこと、事前準備を早くにしていれば当日時間短縮できそうなところが多くあったところなど、悔しい点もあった。前回の ISUCON 予選は複数台サーバの時計のずれなど、重要な点に気付く必要があり、それには時間があっても気付けなかっただろうと感じたが、今回は時間があればできたと思うことは多くあった。もちろん、 ISUCON の競技としては事前準備が効きすぎてしまうのはよくないだろうと思うし、その想定で情報を掲出している点もあるとは思うが、それでも8時間という短い時間ですべてを出し切るには特にデプロイ周り、時間の使い方や締切、(ISUCON 7 予選で複数 VM となる前例があった今)複数 VM を複数人で活用する方法など、事前準備が避けられない点は準備しておくべきだった。

NextCloud + Collabora で、 Collabora を更新すると Collabora が灰色一色になった

謎現象メモ。

表題の通り、 NextCloud + Collabora で、

  • NextCloud をアップデートして(この時点では無事なので関係ない?)
  • ついでに Collabora も apt で新しいのを入れて再起動すると
  • Collabora が開かれるべき画面で灰色一色になることがある。
  • 理由は謎だが、その後、 NextCloud の管理者用設定画面から、 Collabora の URL を設定するところで適用ボタンを押すと直った。

BlackBerry KEYone で使うためのランチャーを書いて、 Google Play にリリースした

去年、 Nexus 5X がブートループに陥り、買い換えざるを得なくなったので、BlackBerry KEYone を購入していた。キーボードがあるので快適に使っていたが、 Alfred のようなアプリがあるとより便利なのではないかと思った。幸いにも、 KEYone には(それまで使っていなかったが)「便利キー」という名前の、アプリを最大 3 つまで紐づけられて、特に一つしか紐づけなければどの画面でもボタン一つでアプリを起動できるボタンがあったので、そこから呼び出すことにしてアプリを作成、リリースまでした。

作成したアプリは「Blue Line Console」で、 Google Play にリリースした。ソースコードは GitHub のリポジトリに置いてある。

(3/27 追記:画像を一枚も貼っていなかったので、スクリーンショットを追加)

リリースするまでの流れを思い出せる範囲で書いておく。

    • アプリを作ろうと思った
    • とりあえず、 Android Studio をダウンロードしてパソコンに入れ、プロジェクトを作成した。
    • Android Studio は Git との連携が最初からついていて、 .gitignore もちゃんと書いてあったので、 Git でコードを管理できるようにした。
    • とりあえず欲しい機能が実現できるか書き始めてみた。アプリの検索周りが Android 特有の事情でどれくらい影響を受けるかわからなかったので、そこから書き始めた。
    • 動いたが遅かった。アプリ一覧そのものはすぐ取得できるが、アプリの名前の取得が遅いらしいことに気付いた。ぐぐってみると Android: Getting list of device applications – Very Slow – Stack Overflow というページがひっかかり、どうにもならなそうだったので、アプリの名前を SQLite にキャッシュすることにした。
    • レイアウトの画面で、 left / right より start / end のほうが RTL な端末にフレンドリーだよ、という警告がでていたので、 RTL 周りを調べて修正した。端末の言語設定をアラビア語に変えてどのように動作するか調べた(開発者オプションで日本語のまま RTL レイアウトにすることもできたが、どうせなので実際にアラビア語だとどうなるか調べた)。
    • 必要な機能を実装したり、レイアウトを調整したりしていた。名前がまだ決まっていなかったので、パッケージ名は仮置きのまま、アプリの名前やアイコンはデフォルトのままになっていた。
    • 途中で、 Jenkins でビルドできるようにした。gradlew ファイルを実行可能にして、Jenkins に Android エミュレータプラグインを入れて、 Gradle で “build connectedCheck” の二つのジョブを実行するようにした。GitLab からフックするようにして、コミットしたら入れられる apk ができるようにした。
    • 名前が決まったので、クラス名などを決定し、アイコンを作成した。 デフォルトで roundIcon (Android 7.1 (API レベル25)から)と anydpi なアイコン(Android 8.0 (API レベル26)から)が設定されていたが、一旦は無視することにして削除した。なお、後で Google Play にアップロードする操作の途中でアプリのアイコンの高解像度版やヘッダなどが必要になるので、アイコンができたからといってアイコン用の png だけ残して元ファイルを削除してしまうと悲しい思いをする(さすがに消さなかったが)。
    • Google Play にリリースする準備をした。
      • Google Play コンソールから、デベロッパー登録をして $25 を支払った。
      • Google Play App Signing (Google Play アプリ署名)を利用することにしたが、 Google に確認してもらうための電子署名はしないといけないので、 Jenkins の Android Signing Plugin (と Credentials Plugin)を設定した。PKCS#12 な証明書(秘密鍵あり)を keytool コマンドで作成して Jenkins の Credentials プラグインに読み込ませた。方法は後述。
      • フォームから、デフォルトの言語を選んで、アプリのタイトルや説明、スクリーンショットをアップロードした。レーティング(何歳以上じゃないと使ってはいけないとか)の判別のための設問なども必要だった。基本的には必要な作業は画面を見ればわかるようになっていた。非公開な状態で apk のアップロードと説明の記述まで実施した。
      • 完了したらアップロードボタンを押すと割とすぐにアプリのタイトルで検索してインストールできるようになった。

PKCS#12 な証明書の作成

アプリケーションへの署名 | Android Developersに従って署名を作った後、Credentials Plugin に読み込ませるために PKCS#12 に変換した。よくわかっていなかったのでこうしたが、もっといい方法がありそう。

$ keytool -genkey -v -keystore android-build-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
$ keytool -importkeystore -srckeystore android-build-key.jks -destkeystore android-build-key.p12 -deststoretype PKCS12 -srcalias my-alias

Jenkins で Android テスト

(追記)この状態でしばらく使ってみたが、見ての通り一発でインストールが通らないだけでも何が起こっているかいまいちわかりづらいエラーが出るシステムは、何かあった時もやはり何が起こっているかいまいちわかりづらいエラーが出て復旧が面倒という印象だった。次回構築するときは別の方法を検討したいと思う。

優秀なプラグインが公開されているおかげでなんてこともない……はずなのだが、なんか迷走した挙句にすごく簡単にできることがわかったのでメモ。キーワードは「いらんことすんな」。

手順

  • Jenkins スレーブとして構成する。つまり、とりあえず最初に Jenkins スレーブにする。ホームディレクトリは必要だが、sudo できる必要はない。
  • gradle を入れる。
  • Jenkins に “Android Emulator Plugin” を入れる。つまり、 Android SDK はまだ入れない。
  • なんでもいいから Android アプリのテストを試みる。つまり、 Android SDK を自分で入れようなどと考えずにテストを試みる。プラグインが入れてくれるが、失敗した。
  • ここで初めて Android SDK を触る。結局のところ Android SDK を入れようとして完全には headless で入らなかったという状況になっているので、 Jenkins と同じ権限で (workspace)/tools/android-sdk/tools/bin/sdkmanager –list を実行する。
  • 再度テストを試みる。通る。

ここで余計なことをすると、

Warning: File /home/xxxx/.android/repositories.cfg could not be loaded.

とか

['(workspace)/tools/android-sdk']: Does not look like an Android SDK directory

とか、とにかく「なんで???」としか言いようがないエラーメッセージを睨めっこして、ぐぐっても必要な情報が出なくて苦労することになる。

Android SDK のみの Linux へのインストール

Jenkins での自動ビルドなどで、 Android SDK 単体をインストールしたくなることがあるが、その時困った情報をメモ。

手順メモ

Ubuntu 16.04 を使用

  • openjdk-8-jdk, gralde をインストール
  • Android Studio のページから、 SDK のみの Linux 版をダウンロード。sdk-tools-linux-*.zip というファイル名だった。
  • 解凍すると tools というディレクトリができた。
  • /opt/android-sdk を作成し、先ほどのディレクトリは /opt/android-sdk/tools に配置した。環境変数 ANDROID_HOME は /opt/android-sdk に設定。
  • sudo /opt/android-sdk/tools/bin/sdkmanager “platform-tools” “platforms;android-26” 的な感じでインストール
  • /opt/android-sdk はビルドする対象(Jenkins とか)から書き込めるパーミッションに設定
  • (環境構築とは別) Windows 版の Android Studio で作成されたディレクトリを使用するにあたり、 (PROJECTROOT)/graldew を chmod +x する必要があった。

参考サイト

Meltdown, Spectre 対応での性能測定

Meltdown, Spectre の対応で、メモリ空間の分離の処理が重くなるとして色々話題になっているので、深い意味はないけど自宅のマシンで UnixBench を比較。Ubuntu 16.04 on hp microserver Gen8 にて測定。

環境

CPU

$ cat /proc/cpuinfo  | grep 'model name'
model name      : Intel(R) Celeron(R) CPU G1610T @ 2.30GHz
model name      : Intel(R) Celeron(R) CPU G1610T @ 2.30GHz

カーネルバージョン

いずれも Ubuntu 標準のリポジトリの物

環境 カーネルバージョン
対応後 4.4.0-109-generic #132-Ubuntu SMP Tue Jan 9 19:52:39 UTC 2018 x86_64 x86_64 x86_64
対応前 4.4.0-104-generic #127-Ubuntu SMP Mon Dec 11 12:16:42 UTC 2017 x86_64 x86_64 x86_64

結果

広く指摘されている通り、システムコールのオーバーヘッドが大きくなっていることがわかりやすく出ている。

試験名 対応前 対応後 対応後の相対値
System Call Overhead 3237.3 965.2 29.8%
Pipe Throughput 2913.0 1509.0 51.8%
Pipe-based Context Switching 1447.4 809.6 55.9%
Process Creation 1825.5 1570.2 86.0%
Execl Throughput 2016.8 1806.5 89.6%
Shell Scripts (8 concurrent) 2908.6 2739.7 94.2%
Shell Scripts (1 concurrent) 3129.3 2960.0 94.6%
File Copy 1024 bufsize 2000 maxblocks 2592.4 2519.9 97.2%
File Copy 4096 bufsize 8000 maxblocks 4940.0 4831.9 97.8%
File Copy 256 bufsize 500 maxblocks 1712.1 1687.9 98.6%
Double-Precision Whetstone 1229.2 1228.9 100.0%
Dhrystone 2 using register variables 4475.4 4592.7 102.6%

ログ

$ uname -a
Linux storage 4.4.0-104-generic #127-Ubuntu SMP Mon Dec 11 12:16:42 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ ./Run
make all
make[1]: Entering directory '/home/nhirokinet/byte-unixbench/UnixBench'
make distr
make[2]: Entering directory '/home/nhirokinet/byte-unixbench/UnixBench'
Checking distribution of files
./pgms  exists
./src  exists
./testdir  exists
./tmp  exists
./results  exists
make[2]: Leaving directory '/home/nhirokinet/byte-unixbench/UnixBench'
make programs
make[2]: Entering directory '/home/nhirokinet/byte-unixbench/UnixBench'
make[2]: Nothing to be done for 'programs'.
make[2]: Leaving directory '/home/nhirokinet/byte-unixbench/UnixBench'
make[1]: Leaving directory '/home/nhirokinet/byte-unixbench/UnixBench'
sh: 1: 3dinfo: not found

   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

2 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

2 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

2 x Execl Throughput  1 2 3

2 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

2 x File Copy 256 bufsize 500 maxblocks  1 2 3

2 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

2 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

2 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

2 x Process Creation  1 2 3

2 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

2 x Shell Scripts (1 concurrent)  1 2 3

2 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: storage: GNU/Linux
   OS: GNU/Linux -- 4.4.0-104-generic -- #127-Ubuntu SMP Mon Dec 11 12:16:42 UTC 2017
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Celeron(R) CPU G1610T @ 2.30GHz (4589.4 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 1: Intel(R) Celeron(R) CPU G1610T @ 2.30GHz (4589.4 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   16:04:12 up 9 days, 16:38,  1 user,  load average: 1.91, 2.93, 2.06; runlevel 2017-12-29

------------------------------------------------------------------------
Benchmark Run: Mon Jan 08 2018 16:04:12 - 16:32:59
2 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       26624684.7 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     3379.6 MWIPS (9.9 s, 7 samples)
Execl Throughput                               3837.8 lps   (29.6 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        800558.6 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          238528.1 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1921655.9 KBps  (30.0 s, 2 samples)
Pipe Throughput                             1811369.4 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 162381.4 lps   (10.0 s, 7 samples)
Process Creation                               9848.2 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   8493.7 lpm   (60.1 s, 2 samples)
Shell Scripts (8 concurrent)                   1618.4 lpm   (60.1 s, 2 samples)
System Call Overhead                        3039305.9 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   26624684.7   2281.5
Double-Precision Whetstone                       55.0       3379.6    614.5
Execl Throughput                                 43.0       3837.8    892.5
File Copy 1024 bufsize 2000 maxblocks          3960.0     800558.6   2021.6
File Copy 256 bufsize 500 maxblocks            1655.0     238528.1   1441.3
File Copy 4096 bufsize 8000 maxblocks          5800.0    1921655.9   3313.2
Pipe Throughput                               12440.0    1811369.4   1456.1
Pipe-based Context Switching                   4000.0     162381.4    406.0
Process Creation                                126.0       9848.2    781.6
Shell Scripts (1 concurrent)                     42.4       8493.7   2003.2
Shell Scripts (8 concurrent)                      6.0       1618.4   2697.3
System Call Overhead                          15000.0    3039305.9   2026.2
                                                                   ========
System Benchmarks Index Score                                        1408.8

------------------------------------------------------------------------
Benchmark Run: Mon Jan 08 2018 16:32:59 - 17:01:45
2 CPUs in system; running 2 parallel copies of tests

Dhrystone 2 using register variables       52227790.6 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     6760.5 MWIPS (9.9 s, 7 samples)
Execl Throughput                               8672.1 lps   (29.5 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks       1026579.6 KBps  (30.1 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          283351.3 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       2865226.5 KBps  (30.1 s, 2 samples)
Pipe Throughput                             3623761.5 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 578965.5 lps   (10.0 s, 7 samples)
Process Creation                              23001.7 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                  13395.6 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   1744.5 lpm   (60.1 s, 2 samples)
System Call Overhead                        4856018.0 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   52227790.6   4475.4
Double-Precision Whetstone                       55.0       6760.5   1229.2
Execl Throughput                                 43.0       8672.1   2016.8
File Copy 1024 bufsize 2000 maxblocks          3960.0    1026579.6   2592.4
File Copy 256 bufsize 500 maxblocks            1655.0     283351.3   1712.1
File Copy 4096 bufsize 8000 maxblocks          5800.0    2865226.5   4940.0
Pipe Throughput                               12440.0    3623761.5   2913.0
Pipe-based Context Switching                   4000.0     578965.5   1447.4
Process Creation                                126.0      23001.7   1825.5
Shell Scripts (1 concurrent)                     42.4      13395.6   3159.3
Shell Scripts (8 concurrent)                      6.0       1744.5   2907.6
System Call Overhead                          15000.0    4856018.0   3237.3
                                                                   ========
System Benchmarks Index Score                                        2485.8

$ uname -a
Linux storage 4.4.0-109-generic #132-Ubuntu SMP Tue Jan 9 19:52:39 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ ./Run
make all
make[1]: Entering directory '/home/nhirokinet/byte-unixbench/UnixBench'
make distr
make[2]: Entering directory '/home/nhirokinet/byte-unixbench/UnixBench'
Checking distribution of files
./pgms  exists
./src  exists
./testdir  exists
./tmp  exists
./results  exists
make[2]: Leaving directory '/home/nhirokinet/byte-unixbench/UnixBench'
make programs
make[2]: Entering directory '/home/nhirokinet/byte-unixbench/UnixBench'
make[2]: Nothing to be done for 'programs'.
make[2]: Leaving directory '/home/nhirokinet/byte-unixbench/UnixBench'
make[1]: Leaving directory '/home/nhirokinet/byte-unixbench/UnixBench'
sh: 1: 3dinfo: not found

   #    #  #    #  #  #    #          #####   ######  #    #   ####   #    #
   #    #  ##   #  #   #  #           #    #  #       ##   #  #    #  #    #
   #    #  # #  #  #    ##            #####   #####   # #  #  #       ######
   #    #  #  # #  #    ##            #    #  #       #  # #  #       #    #
   #    #  #   ##  #   #  #           #    #  #       #   ##  #    #  #    #
    ####   #    #  #  #    #          #####   ######  #    #   ####   #    #

   Version 5.1.3                      Based on the Byte Magazine Unix Benchmark

   Multi-CPU version                  Version 5 revisions by Ian Smith,
                                      Sunnyvale, CA, USA
   January 13, 2011                   johantheghost at yahoo period com


1 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

1 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

1 x Execl Throughput  1 2 3

1 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

1 x File Copy 256 bufsize 500 maxblocks  1 2 3

1 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

1 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

1 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

1 x Process Creation  1 2 3

1 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

1 x Shell Scripts (1 concurrent)  1 2 3

1 x Shell Scripts (8 concurrent)  1 2 3

2 x Dhrystone 2 using register variables  1 2 3 4 5 6 7 8 9 10

2 x Double-Precision Whetstone  1 2 3 4 5 6 7 8 9 10

2 x Execl Throughput  1 2 3

2 x File Copy 1024 bufsize 2000 maxblocks  1 2 3

2 x File Copy 256 bufsize 500 maxblocks  1 2 3

2 x File Copy 4096 bufsize 8000 maxblocks  1 2 3

2 x Pipe Throughput  1 2 3 4 5 6 7 8 9 10

2 x Pipe-based Context Switching  1 2 3 4 5 6 7 8 9 10

2 x Process Creation  1 2 3

2 x System Call Overhead  1 2 3 4 5 6 7 8 9 10

2 x Shell Scripts (1 concurrent)  1 2 3

2 x Shell Scripts (8 concurrent)  1 2 3

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: storage: GNU/Linux
   OS: GNU/Linux -- 4.4.0-109-generic -- #132-Ubuntu SMP Tue Jan 9 19:52:39 UTC 2018
   Machine: x86_64 (x86_64)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0: Intel(R) Celeron(R) CPU G1610T @ 2.30GHz (4589.4 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   CPU 1: Intel(R) Celeron(R) CPU G1610T @ 2.30GHz (4589.4 bogomips)
          Hyper-Threading, x86-64, MMX, Physical Address Ext, SYSENTER/SYSEXIT, SYSCALL/SYSRET, Intel virtualization
   23:30:18 up 1 min,  1 user,  load average: 0.19, 0.11, 0.04; runlevel 2018-01-16

------------------------------------------------------------------------
Benchmark Run: Tue Jan 16 2018 23:30:18 - 23:59:05
2 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       26767435.5 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     3379.3 MWIPS (9.9 s, 7 samples)
Execl Throughput                               3471.2 lps   (29.6 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        554695.5 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          148162.7 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1609334.7 KBps  (30.0 s, 2 samples)
Pipe Throughput                              914803.6 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 145211.3 lps   (10.0 s, 7 samples)
Process Creation                               8671.7 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   8052.1 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   1534.6 lpm   (60.1 s, 2 samples)
System Call Overhead                         768182.9 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   26767435.5   2293.7
Double-Precision Whetstone                       55.0       3379.3    614.4
Execl Throughput                                 43.0       3471.2    807.3
File Copy 1024 bufsize 2000 maxblocks          3960.0     554695.5   1400.7
File Copy 256 bufsize 500 maxblocks            1655.0     148162.7    895.2
File Copy 4096 bufsize 8000 maxblocks          5800.0    1609334.7   2774.7
Pipe Throughput                               12440.0     914803.6    735.4
Pipe-based Context Switching                   4000.0     145211.3    363.0
Process Creation                                126.0       8671.7    688.2
Shell Scripts (1 concurrent)                     42.4       8052.1   1899.1
Shell Scripts (8 concurrent)                      6.0       1534.6   2557.7
System Call Overhead                          15000.0     768182.9    512.1
                                                                   ========
System Benchmarks Index Score                                        1050.6

------------------------------------------------------------------------
Benchmark Run: Tue Jan 16 2018 23:59:05 - 00:27:51
2 CPUs in system; running 2 parallel copies of tests

Dhrystone 2 using register variables       53596515.9 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     6759.1 MWIPS (9.9 s, 7 samples)
Execl Throughput                               7767.9 lps   (29.5 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        997866.7 KBps  (30.1 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          279350.0 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       2802513.5 KBps  (30.1 s, 2 samples)
Pipe Throughput                             1877145.8 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 323835.7 lps   (10.0 s, 7 samples)
Process Creation                              19784.7 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                  12550.5 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   1643.8 lpm   (60.1 s, 2 samples)
System Call Overhead                        1447857.1 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   53596515.9   4592.7
Double-Precision Whetstone                       55.0       6759.1   1228.9
Execl Throughput                                 43.0       7767.9   1806.5
File Copy 1024 bufsize 2000 maxblocks          3960.0     997866.7   2519.9
File Copy 256 bufsize 500 maxblocks            1655.0     279350.0   1687.9
File Copy 4096 bufsize 8000 maxblocks          5800.0    2802513.5   4831.9
Pipe Throughput                               12440.0    1877145.8   1509.0
Pipe-based Context Switching                   4000.0     323835.7    809.6
Process Creation                                126.0      19784.7   1570.2
Shell Scripts (1 concurrent)                     42.4      12550.5   2960.0
Shell Scripts (8 concurrent)                      6.0       1643.8   2739.7
System Call Overhead                          15000.0    1447857.1    965.2
                                                                   ========
System Benchmarks Index Score                                        1956.5

ISUCON 7 予選参加

ISUCON 7 予選二日目にチーム「ワイハリマ」(yuta1024, nhirokinet, tyabuki)で参加しました。76,904 点でした。

今回の題材は「isutaba」というチャットツールで、

  • ログインすると部屋がたくさんあるので、それぞれの部屋でチャットができる(部屋の権限などはない)
  • 部屋の発言およびほかの部屋の未読バッヂは、ストリーム風にリアルタイムに表示される。それを実現するために、各ブラウザが js で無限に新着を確認する「/fetch」 JSON APIをたたき続ける。
  • ブラウザは /fetch が返ってきてそのレスポンスを処理したら、また次の /fetch をたたく。サーバ側の /fetch 側はデフォルトで 1 秒待機(sleep 1)だが、こちらは変更可能。
  • デフォルトで、 web app 2 台、 db (MySQL) 1 台の計 3 台構成。ただし、構成は自由に変更可能で、 FE サーバの集合は自由に選択可能。
  • デフォルトではユーザアイコンも含めて自由に変更可能で、全部 db に載っている。ユーザアイコンの URL は、デフォルトでは画像の sha + 拡張子。画像への権限管理なし。

という内容でした。

リポジトリ

isubata リポジトリ by チーム「ワイハリマ」

準備内容

最低限、よくある MySQL や nginx の設定、kataribe、公開鍵一覧と配布スクリプトを準備。プライベートリポジトリに関しては、性能に余裕のあるマシンで GitLab を用意し、全員のアカウントを作り、外からも使用可能なようにしておいた。

当日

思い出せる範囲で。個人で書いているので、他の二人の実施内容に関しては違っている可能性がある。

  • 開始が10時から12時に変更だったのでそれに合わせて集合したが、最終的には13時になったので最初の進捗
  • まず、サーバに全員分の鍵や、 MySQL には InnoDB の書き出し間隔の遅延、 MySQL インデックスの追加などを実施。
  • 一旦一台構成に移行し、 icons を MySQL ではなく静的ファイルとして扱うよう変更。(初期段階としては)ある程度伸びる。
  • サーバのミドルウェアを一部は新しいものに更新しつつ、設定をざっくりチューニング。また、設定ファイルを扱いやすくするなどを実施。キャッシュ回りもいじっていたようだ。ここは担当していないので詳細はよくわからないがここで点数が大幅に伸びていた模様。
  • リクエストが多い /fetch, /message について、 Slim 脱却を試みる。テンプレートを使っていなかったのでそれ自体の修正量は少なめ。
    • ここで、 /fetch での sleep(1) が話題に上る。単につぶすと性能が下がる。 /fetch 自体はスコアに勘定されないルールになっており、単に排除するといたずらに負荷をかけることになる。
  • 40k を超えたあたりで、 php-fpm のワーカ数を調整しようとして、 sleep(1) が話題に上る。これが php のプロセス数を食っているようだ。とりあえず増加。
  • 静的ファイルの icons を相手のサーバにも送り付ける口を作り web app を二台に戻すが、性能が上がらない。
  • とにかく /fetch の sleep の問題が大きいということで、 /fetch だけは専用の php-fpm プールに逃がすように変更してスコアが上昇。
  • 同時に、ベンチマーカーのエラーメッセージや kataribe の結果などから、 icons が異常に遅延(nginx 視点でテイルレイテンシ 10 秒)していることに気付く
  • 外向け 100Mbps 、一分間での画像リクエスト約 1.4k ということで、画像ファイル平均 500kB 程度とすると帯域をほぼ使い切っている計算。
  • メモリを使い切ってキャッシュが減っているのでは?という疑惑はあった
  • ベンチマークを何度か走らせると、 +/- 15% 程度は平気で増減する状態であり、ガチャの影響も大きかった
  • icons が大幅遅延するかどうかもガチャ次第だった。
  • web app を二台活用できない理由も、 icons が遅延する(あるいは上位チームがこの何倍ものスコアを叩き出せる)根本原因もわからないが、終盤が近づいたので web app を一台運用することを決定。
  • 再起動試験実施。
  • 再起動後二回目の試験で、運よく過去最高得点が出た。この時終了約15分前だったので、以後外れベンチマークを引かないように全ての作業を終了。

感想

今回は、ウェブアプリケーションとしてはかなり王道なチューニングが主で、それでいて難易度が高く仕上がっていて、良い問題だったと感じました。

まだほかのチームの write up はあまり見られていませんが、それでも特に複数台構成/ローカルファイルシステム同期における /icons の更新日時や、せめてもの二台目の活用方法など、少し読んだだけでも見直すべき部分が色々出てきました。

二日目の通過ラインは 210,464 点で、ここからさらに三倍食えるようにしないといけなかったようです。とはいえ、学びはあったので、今後予選通過を狙えるようにしたいです。