toshi00.log

いろいろ試したい

Web Speed Hackathon 2021 mini に参加しました

Web Speed Hackathon 2021 mini が2021年12月4日〜2022年1月3日にかけて開催され,これに参加してきました.重たい短文投稿サイトをチューニングし高速化することを目指すコンテストです.

自分が参加できたのは終了直前の数日だけなのですが,多くのことを学ぶことができました.

f:id:toshi00p:20220111171901p:plain

スコアはLighthouse を用いて計測されます(→詳細).満点は720点です.
初期計測で79.02点,最終計測で649.21点です.最終9位でした.振り返りつつ,復習のために行ったことを記録しておきます.

対応するコミットをそれぞれの項目に記載しましたが,一つのコミットに複数の変更が入っている場合があります.また,各項目はジャンルごとに並んでおり,順番と効果は関係しません.

github.com

  • やったこと
    • NODE_ENV
    • webPack
      • Tailwind CSSのpurge
      • cssnanoの導入
      • Babel
    • assetsの軽量化
      • WOFF2を使うようにする
      • Font Awesomeの必要なアイコンだけ読み込み
      • 投稿画像のリサイズとwebPへの変換
      • アイコン用画像のリサイズとwebPへの変換
      • GIFのリサイズとwebMへの置き換え
    • 依存パッケージの最適化
      • moment
        • 必要な部分だけ読み込み
        • momentの削除
      • Preactへの置き換え
      • bluebird(gifler,omggifを使わない)
      • lodash
      • jQuery
      • pako
      • AudioContextの読み込みを削除
      • image-size
      • normalize.cssを読み込まない
    • webfont.css
      • 使用していないフォントをwebfont.cssから削除
      • font-displayをblockからswapに
    • scriptの非同期読み込み
    • JavaScript
      • 投稿データのキャッシュ
      • ページ最下部かのチェックを1回だけに
      • 画像のトリミングをCSSに置き換え
      • コンポーネントの大きさ指定をCSSで行う
      • 音の波形を事前計算しておく
      • 規約ページの後半を遅延ロード
    • バックエンド
      • babel-nodeではなくnodeを使う
      • brotli圧縮
    • CDN(Cloudflare)の導入
  • もっとできそうなこと
続きを読む

Bug Shooting Challenge #6で優勝しました!

f:id:toshi00p:20211110093356p:plain

2021年11月6日,mixi Bug Shooting Challenge #6に参加してきました.自分と他2人で構成された3人チームdeltaが最優秀チームに選ばれました!やった〜〜

チャレンジ内容は話さないように言われています.大雑把に言うと「ログやソースコードからシステムの不具合を見つけ出し修正する」という流れを繰り返すチャレンジです.作業はチームで役割分担しながら行います.自分も,主にログの解析やバグの再現,一部コード修正を行いました.実際にありそうなバグばかりで,バグ探しをするのが楽しかったです.

f:id:toshi00p:20211108232836j:plain 開催前には,お菓子やお昼ごはん,パーカーなどが届きました.嬉しい!
チームのみなさん,運営の方々,本当にありがとうございました.

mixi.connpass.com

非安定マルチバイブレータ回路で遊ぶ

非安定マルチバイブレータ回路をいくつかの方法で作成しました。回路自体はシンプルなものですが、実際に組み立ててLEDが光る様子を見ると面白いですね。

この内容は、セキュリティ・キャンプ全国大会2021オンラインの中で体験したことをもとに作成しています。

  • 回路図
  • ブレッドボード
  • ユニバーサル基板
  • 空中配線?
  • KiCadでアートワーク練習

回路図

f:id:toshi00p:20211004032834p:plain
非安定マルチバイブレータ回路の回路図

続きを読む

Arduino for VSCodeでボード選択ができない

f:id:toshi00p:20210930193948p:plain

問題

Arduino for Visual Studio Codeのバージョンを v0.4.6 に上げたらArduino Board Configurationが「No results found」しか言わなくなりました。

解決

f:id:toshi00p:20210930194541p:plain 拡張機能 > 別のバージョンをインストール > v0.4.5 と選択して、古いバージョンに戻すと治りました。 すでにいくつかIssueも建てられているようです。すぐに解決されるような気もしますが、アップデートしたことを忘れて地味に困ったので参考までに。

github.com

github.com

ICTSC2021 夏の陣に参加しました!

f:id:toshi00p:20210929194154j:plain
8/28,29のICTSC2021 夏の陣にチームPizzaで参加しました。

最終的に2100点で6位です。3位と100点差で、もう1問解ければ……という感じでした。5位とは同点、4位とは50点差です。 復習を兼ねて自分の提出した問題について書きます。

チームメンバーが書いた参加記もあります → ICTSC夏の陣に参加してきました

1日目

触った問題を順番に書いていきます。解説や問題の詳細は ICTSC2021 | ICTSC Tech Blog が詳しいです。

14. Webサーバーが立ち上がらない (50点)

Webサーバが立ち上がらない | ICTSC Tech Blog
とりあえず一番簡単そうな問題を取りました。python3 app/index.py するとflaskがないよ!って怒られているという問題です。

色々と問題背景はあるようですが、とりあえずflaskをインストールすれば終わります。こんな簡単でいいのか?と不安になりながら提出しました。

$ pip install Flask

3. なんでだ!?(150点)

なんでだ!? | ICTSC Tech Blog
冗長化したらHostAからHostBにpingが通らなくなった!という問題です。

HostA → RTA → HostB という通信経路がだめなようです。冗長化した!という設定を無視して、通信可能な経路に対してstaticルーティングを設定しました。50点しかきませんでした(それはそう)。とりあえず放置して次の問題に行きます。

トラブルがあったようで、2日目の朝にこの問題はなくなりました。セーフ。

13. サーバー気象予報(150点)

サーバ気象予報 | ICTSC Tech Blog
APIサーバー周りが微妙で、アプリケーションがうまく動かないという問題です。

サーバーの3000番でexpressサーバーが動いているはずですが、確認したら何もありません。

$ npm start

をすると、レスポンスが帰ってくるようになるのでexpressサーバーに問題がないことは確認できました。あとは自動的に起動するよう設定します。

方法はいくつかあると思いますが、今回はサービスファイルを書いて自動起動を有効化することにしました。サービスファイルを初めて書いたので、不十分or危ない部分があるかもしれません。こんな感じでapi_server.serviceを書きました。

[Unit]
Description=server.js - weather api
After=network.target

[Service]
Type=simple
User=user
ExecStart=/usr/bin/node /srv/api/server.js
Restart=on-failure

[Install]
WantedBy=multi-user.target
$ sudo systemctl enable api_server

また、CORSの設定にも問題があるようです。Nginxの設定を変更して対応します。

$ sudo vi /etc/nginx/nginx.conf

最終的に以下のようになりました。

~~~
server {
          listen 80;
          server_name api.test;

          location / {
            proxy_pass http://192.168.4.102:3000;

            add_header Access-Control-Allow-Origin '*';
            add_header Access-Control-Allow-Methods 'GET, POST';
            add_header Access-Control-Allow-Headers 'Content-Type';
          }
        }
~~~

サービスファイルを書いたことがなくて、少し詰まったものの問題特定から解決まで比較的サクサクと進めることができました。
また、本題から外れるのですが、expressサーバーに少し気になる挙動があります。

expressサーバーが、気温・湿度データのPOSTリクエストに対してレスポンスを返さない実装となっています。そのため、POSTリクエストを送信するとクライアント側でタイムアウトが発生します。動作に問題はありません。しかし、コンソール上にエラーが表示されるため、さっと修正を入れました。

7. 対向につながらにな。。(150点)

対向につながらにな。。 | ICTSC Tech Blog

ルーターの情報を確認していった結果、経路情報の配布されていない部分がありました。じゃあ配布すればええやろ!って配布します。

set protocols ospf redistribute bgp

動きました。

解説を読むと、OSPFの設定を入れることで解決することが多いようです。なるほどなぁ。
vyOSの知識があまりなく、経路情報再配布の方法を調べるのにかなり時間をかけてしまいました。インターネットって難しい。

2日目

解ける問題が残っていなくてあまり手の動かない1日でした。

2. 頑固なindex.html( 0 /150点)

頑固なindex.html | ICTSC Tech Blog

調べましたが、原因がわからずチームメンバーに引き継ぎました。Welcome to ICTSCという文章の載ったファイルを探してみようと思いつつ、Helloで検索するという謎ミスをしました。惜しい?解いてくれたチームメンバーに感謝。

6. iscsi targetにログインできない!(200点)

iscsi targetにログインできない! | ICTSC Tech Blog

iscsi-targetに設定されたaclの名前がiscsi-initiatorに設定された名前と異なっていたことが原因のようです。
ターゲットサーバーにて設定を確認すると、iqn.2021-07.192.168.18.11:initiatorがありました。一方でイニシエーターサーバーのInitiatorNameはiqn.2021-07.192.168.18.1:initiatorでした。よく見ると11と1で名前が異なっています。

公式の解説とは逆なのですが、イニシエーターサーバーのInitiatorNameを変更することで対応しました。具体的には、/etc/iscsi/initiatorname.iscsiを編集し、11のほうで統一します。

正直、iscsiを全く知らなかったので厳しかったです。調べていたら偶然解けました。

全体を通して

全体として知識が足りず、200点問題以上が厳しいという感覚でした。 チームメンバーのおかげで、あとちょっとで表彰台というところまで戦えて楽しかったです。お疲れさまでした!

ISUCON11予選 tetoraの記録

ISUCON11予選に学生チームtetoraとして、 @tesso@ras と一緒に参加しました。

結果として 31075点までしか点数を伸ばせず、予選突破とはなりませんでした。来年またがんばります。 ISUCON予選から時間が立ってしまい、忘れた部分も多いですが、自分の担当したことをなんとなく書いておきます。

やったこと

自分は主にDB周りを担当しました。振り返ってみると何もできていません……難しいなぁ
以下自分の関わった部分です。

初動

最初の50分何をするかある程度打ち合わせていたので、かなりスムーズだったと思います。 初手のベンチでは1000点ちょっとくらいでした。 開発用のスクリプトを配ったり、バックアップを取ったり、ドキュメントの読み合わせをしました。

DBはMariaDB 10.3でした。事前の情報でサーバーはUbuntuとあったので、Ubuntu20.04でmysql8.0が入っているかも!? と予想していました。流石にそんなことはないか。

複数台の準備だけしておく

複数台構成にするときDBの接続がミスりがちだったので先に設定変更をしておきました。 CPUがきついなぁとなっていたので、初手3台構成で試しても良かったかもしれません。(この先、修正すればするほど点数が下がって苦しみました)

DBにインデックスを貼った

slow query logを見つつ、適当にIndexを貼りました。

INDEX idx_jia_isu_uuid_timestamp(`jia_isu_uuid`, `timestamp`),
INDEX idx_jia_isu_uuid(`jia_isu_uuid`)

これだけで20000点くらい出て驚きました。 実際はjia_isu_uuidとtimestampの複合インデックスだけでも良かったのかな?わからず。

DBチューニングをする

秘伝のタレ(?)を入れました。ほとんど効果なし。

bulk insertをする?

POST /api/condition/:jia_isu_uuid に時間がかかっていることがわかったので、クエリを一本にまとめようと考えます。
……と思って、アプリケーションを見るとすでに修正が入っていました。チームメンバーに感謝。

ただ、このあたりから修正すればするほど点数が下がります。サーバーのさばける件数は増えたけどタイムアウトも増えたのでしょうか?原因はわかりませんでした。改善の効果を計測できずISUCON中かなり苦しかったです。

GET /api/trendを修正する

最新のデータ1件だけ取ってくればいいよね!となったのでN+1になっていた部分も合わせて修正します。SQL文を書いて必要なデータだけを取ってくるようにしました。ただ、この修正はあまり良くなかったかもしれません。ISUCON11 予選問題実践攻略法にあるように、LIMITだけかければ十分なのかも? N+1の修正に意識が行き過ぎて、一つ一つの修正に時間をかけてしまいました。

ちなみにこの頃、nginxのキャッシュ?やアプリケーションのログを止めるなどについてもいつの間にか修正が入っていました。チームメンバーに本当に感謝。

ここから先、沼……

この先、複数台構成せず、アプリケーション側でのオンメモリキャッシュにも手を出していきます。点数が伸びず、エラーも出て厳しかったです。 きちんと覚えていないのですが、チームで役割分担しつつ/api/isu, /api/trend, /api/condition/:jia_isu_uuidあたりのAPIがオンメモリになりました。点数は増えません(なんで?)

最終的にオンメモリ実装でバグが出て、自分の実装した部分は利用されずに終わりました。 そうこうしているうちにポータルサイトが落ち、ベンチマークが一時的に回せなくなりました。ポータルサイトが負荷によって落ちている間に簡単に再起動試験をしました。

終了直前

複数台構成に手を出します。オンメモリをある程度諦めて、nginxで3台のサーバーにリクエストを振り分けました。 ただ、さすがに時間が足りません。3台構成が終わって中途半端な状態でベンチを回してタイムアップ。dropProbabilityの変更までは間に合いませんでした。

反省

  • もっとできることがあった
    • isu_conditionテーブルにlevelカラムを追加するなど、もっとDB側で対応できることがあった
    • クライアントキャッシュを利用できたが気づかなかった
  • N+1の修正に固執して時間をかけすぎた
  • 無限にバグらせてしまった
  • マニュアルにかかれていた点数計算周りをあまり理解できなかった

ISUCON10に参加したときと比較するとだいぶ手が動くようになりました。ただ、実装力や知識が全然足りていません。また、来年がんばります!