平常運転

アニソンが好き

過去記事とかは記事一覧で見れます

ISUCON13に羽つき表参道のお茶会で参加してトップ30を逃した

isucon.net

id:chaya2zid:rmatsuoka と組んだ羽つき表参道のお茶会で参加した。
最終スコアは46,618。最高スコアはそのちょっと前に48xxxくらいを出してた。後から確認したら46,934だからほぼ変わらなかった。。終わってみたら30位が49xxxという感じだったのでベストでも及ばなかった訳だけど、やってる途中は正直そこまで食い込めると思っていなかったので意外というか、ここまでいけるなら僅かな得点の上積みに貪欲になればよかったというか……。いい順位につけられたことは嬉しかったし、ここまで来たならISUCON5以来超久々に名札ほしかったぜ〜という気持ちもある。おつかれさまでした。

リポジトリ(追記: 11/27 14:42)

github.com

アウトライン

  • 言語は Go
  • 指揮官ポジションをやりつつアプリ起点の改善をやってた
    • サーバー分割をしたり Redis をインストールしたりは流れで受け持ってた
    • 指揮官ムーブとしては結果のスコア的に良かったんだろうけど、プレイヤーとしてはいまいちだった
  • 終始 mysqldumpslow と CPU 利用率とにらめっこしていた
  • サーバー分割は (PowerDNS + DNS MySQL), (NGINX + app + Redis), (app MySQL) の3台

もうちょっと詳細な感想

今回二人と組むのは初めて(というか二人は初参加とのことだった)で、休日に何度か過去問をオンラインで解いて練習した。当日は弊社の東京オフィスに集まってオフラインでやった。対面の方が捗るのは間違いないな〜というように思った。

DNS がお題に来たのはビビったけど、サーバー負荷を見ると CPU が支配的かつ MySQL が激重という状況だったので MySQL で実行時間の長いクエリを順番に潰していくという作戦になった。当初はボトルネックが他に変わるタイミングが来るのかなと思ってたけど、我々としては最後までそこが支配的という感じだった。mysqldumpslowの結果を上から順に潰していったけど、やりきったという訳ではなくてまだ潰すべきクエリは全然残っていた。事前の練習ではアプリの CPU プロファイリングから改善するのもやってたんだけど、今回は pprof のエンドポイントを入れすらしないまま終わった。
ユーザー統計は上位にいたので Redis にランキング部分を移した。動画統計は僕らの範囲ではあまり上位に上がってこなかったので無視した。(やったらよかったとは思う)。モデレーションのクエリもメチャクチャじゃんとは思ったけど、上位にあんまり上がってこなかったのでコメントを全件 select してるところに配信IDの絞り込みを追加しただけとかだったと思う。

で、クエリを見てインデックスを貼ったあたりで PowerDNS からのクエリが(インデックスを貼っても)長いクエリに残っていたので、割と早い段階で DNS のサーバー分離を選択した。PowerDNS の設定の書き方でちょっとハマりつつも13時前くらいに分離していたっぽい。
その後は id:chaya2z さんに DNS サーバーのことはお任せとして、 id:rmatsuoka さんと僕で引き続きアプリ側の改修をやっていった。アプリとDBの分離は16時くらい?にしれっとやった気がする。複数台構成でスコアを出すには最終的に複数台のリソースを全部使い切ることになるため、ある程度目処が立った時点で早めに分けたらいいじゃんという気持ちでやった。同僚や知人チームの話を聞くに3台ぶんリソースを使えたことでスコアを稼げた寄与は大きいように思う。(最終的にはアプリ乗ってるサーバーの CPU は余ってしまったが…)

個人的には If-None-Match でアイコンを 304 で返す実装ができなかったのが辛い。結果的には多分これができてたら30位入れてた気もするんだよな。。 原因は簡単で、 If-None-Match ヘッダの中身は etag をダブルクオートで囲った物 が入っているので、値を取り出すにはreq.Header.get('If-None-Match')的なことをしたあとクオートを剥がさなければいけなかった。。

developer.mozilla.org

他にも Redis に入れるコードをミスりまくったり NGINX のキャッシュ設定を全然うまく書けなかったり、個人的には手の速さと正確さどちらも反省という感じだった。DNS サーバーも分離後は id:chaya2z さんが模索しているのに任せっぱなしだったのをもっとチームの問題として取り組めばよかったかなというのも思う。
ただ、 id:rmatsuoka さんに着実にクエリの対応を入れてもらえたし、 id:chaya2z さんには DNS サーバーを押しつけお任せした上でインフラチューニングもやってもらえたのもありがたかった。そういう良かったところから翻って考えると、リーダーポジションの僕が立てた対処方針は大まかには良かったのだろうと思うし、サーバー分割の勘も大外しはしなかったのだろうし、リーダーポジションとしての責務はある程度果たせたんじゃないかなと思う。

ということでおつかれさまでした。今年も楽しく ISUCON できて皆様に感謝です。

来年はトップ30になりて〜〜〜〜〜。

「技育祭」の勉強会で話した

このエントリは特に意味がなくて、社のブログに自分の文責で載せた記事へのポインタを自分のブログにも置いておこうというだけです。

developer.hatenastaff.com

特におもしろ裏話とかもないです。そういえば事前収録でないリモート登壇ははじめてだったかも? このご時世、リモートと物理開催と比べて物理はよかったな〜と思うこともいろいろあるけど、リモートであれば話す側も聞く側もある程度環境の融通が利くのは良いことですね。(登壇を口実に東京に遊びに行く、みたいなことができないという話でもある。)
今回は最近引っ越したばかりの弊社京都新オフィスからお送りしました。

Homebrew Formula の CI を GitHub Actions で行う

ビールの話ではなくてパッケージマネージャの話です。

主に macOS 向け*1のパッケージマネージャ Homebrew の Formula のテストをする話だったり、特に GitHub Actions で CI する仕組みを少し調べてみました、という話をします。

このエントリははてなエンジニア Advent Calendar 2021の19日目です。昨日は id:onk さんの ブログから技術記事を抽出・集約してワイワイする - id:onk のはてなブログでした。

qiita.com

ちなみに、本稿ではさも我が物のように Mackerel の Homebrew Tap を取り上げており、実際今年の夏までは Mackerel の開発チームにいたのでそんなに間違っていなかったのですが、夏以降は別のプロダクトの開発チームにいるので今は Mackerel の開発当事者ではなくなっているということは念のため付記しておきます。なのでこのエントリの中身は全て趣味です。勝手にネタにしてごめんね! > Mackerel チームのみんな

*1:Linux でも使えることは使えますが、ほとんどのケースでは macOS で使われているでしょう……

続きを読む

GitHub Discussions の更新を Slack に通知する (with GitHub Actions)

タイトルでほぼ全て。

f:id:astj:20211115184855p:plain
動いている様子

github.com

2021/11/15 現在の Slack の GitHub 連携では GitHub Discussions の更新を Slack に通知することが出来ない。そのうちできるようになるだろうとは思うものの、それまでの間のつなぎとして GitHub Actions による通知を作った。
Webhook ベースの物と比べると GitHub Actions の workflow 起動のオーバーヘッドがある分若干(十数秒程度?)通知が遅れてしまうことなどもあり少しイケてない節はあるが、そのうち公式のツールでできるようになるまでのつなぎとしては許容可能な品質だろうと思っている。
GitHub からの Webhook を変換して Slack に投げ直す HTTP エンドポイントを作る、とかだと格好いいけれど、つなぎとして使う前提であれば外部に何かプロビジョニングせずに GitHub と Slack の間で完結することにもいくらか価値があるのではないか、と思う。多分。

中身の実装は非常に素朴で、丁寧な手書きで JSON ペイロードを組み立てている。複数行入ることがある texttoJSONエスケープしていることがかわいらしいポイント。

          PAYLOAD: "{\"attachments\":[{\"mrkdwn_in\":[\"text\"],\"fallback\":\"New Comment on ${{ github.event.discussion.html_url}}\",\"author_name\":\"${{ github.event.comment.user.login }}\",\"author_link\":\"${{ github.event.comment.user.html_url }}\",\"author_icon\":\"${{ github.event.comment.user.avatar_url }}\",\"title\":\"Comment on #${{github.event.discussion.number}} ${{ github.event.discussion.title}}\",\"title_link\":\"${{ github.event.comment.html_url}}\",\"text\":${{ toJSON(github.event.comment.body) }},\"footer\":\"${{ github.event.repository.full_name}}\",\"ts\":${{ steps.timestamp_transform.outputs.comment_created_at}}}]}"

組織内のプライベートリポジトリの通知を Slack 通知するだけ、くらいのつもりで作ったのであまり人間の悪意は想定していない。何かあったらこっそり教えてください。

HTMLFormElement.submit は validation を無視するし submit イベントを発火しない

日記です。タイトルでほぼすべてがオチてしまった。

const form = document.querySelector('form#ultra-form');
form.submit();

みたいな感じで、 <form>JavaScript から submit することができるんだけど、この HTMLFormElement.submit は HTML Living Standard ではこう定義されている:

Submits the form, bypassing interactive constraint validation and without firing a submit event.

https://html.spec.whatwg.org/multipage/forms.html#htmlformelement

つまり、例えば下のような HTML form の場合、 submit ボタンをクリックした場合は (1) username が入力されていないと validation が通らないので submit できない し、 (2) onsubmit が false を返せば submit は中止される のだけど、HTMLFormElement.submit はそれらをすべてバイパスして問答無用で実際に form を送信してしまう。

<form id="ultra-form" onsubmit="..." action="...">
  <input name="username" required />
  <input type="submit" />
</form>

若干直感に反する気もするけどそういう感じらしい。ので、 submit ボタンを押すのと同等のアクションとしてはこれを使ってはいけない。

じゃあこういう時に何を使うといいかというと HTMLFormElement.requestSubmit というのが数年前に提案されている。こいつは submit ボタンをクリックするのと同様のバリデーションが走るし、 onsubmit によってキャンセルされることもある、というより自然な仕草が実現される。

Requests to submit the form. Unlike submit(), this method includes interactive constraint validation and firing a submit event, either of which can cancel submission.

The submitter argument can be used to point to a specific submit button, whose formaction, formenctype, formmethod, formnovalidate, and formtarget attributes can impact submission. Additionally, the submitter will be included when constructing the entry list for submission; normally, buttons are excluded.

https://html.spec.whatwg.org/multipage/forms.html#htmlformelement

やったじゃん、と思うわけですが、

caniuse.com

Safari ではまだ使えません。 WebKit レベルでは実装されていて、最新の Safari Technology Preview では「開発」メニューから選べる実験的機能扱いになっている。

f:id:astj:20210716165550p:plain

こちらからは以上です。WebKit の話は id:cockscomb さんに教えてもらいました。

masawada slotmachine - behind the scene

このエントリは masawada advent calendar 2020 ではありません。

adventar.org

この12月は前述の masawada advent calendar のために masawada slotmachine というものを作った。

astj.github.io

astj.github.io

非常に素朴な JS のオモチャという感じだけど、いちおう Next.js で書いている。静的ページの上で React をなんか動かす、もしかしたら複数エンドポイント作るかも(実際作った)という要件から、興味はあるものの触ったことのなかった Next.js を選んでみたという感じ。

github.com

そもそも元々はこのアドベントカレンダーでは全然別のことをやろうと思っていたのだけど、いろいろあって直前で断念してしまって他のネタを考える必要がアリ、全然ネタが思い浮かばないなか辛うじてひねり出したのが今回のスロットという感じ。なので実装も突貫工事のめちゃくちゃで、ソースコードはまあ薄目で遠くからそっと見る程度にしてもらえると。。今回書いたコードに仕事のコードレビューで遭遇したらめっちゃ文句言うと思う。

あとは Next.js の感想。Next.js 便利ですねみたいなことを今更言っても何周遅れだという感じではあるけど便利だった。規約に従って React コンポーネントを書いていくとエンドポイントが誕生していって、 SSR とか SPA とかの細かいことを気にする必要もなくて開発体験が良かった。勿論今回の規模ならまあなんとでもなるという話はあると思っていて、もっと大規模な物を扱ったり、(今回は GitHub Pages に html と js を置く静的ビルドだったのに対して)サーバーありの動的なものを作ったりするともっと難しさとか、逆にありがたみも増えたりするのであろう。またなにか機会があったら使ってみたい。

ソースコードの質はさておくと、アドベントカレンダーの締切駆動にすることで久々にインターネットおもちゃみたいなのを自分で作ることが出来て良い体験だったなと思っている。要件定義も技術選定も実装もデプロイも、なんならデザイン*1も全部自分でやって作るというのは実はだいぶ久々だったと思う。普段仕事でやってるときはチームで分業して大きな物を作る感じなので、たまにこういう活動をしておかないと小回りとかを見失ってしまうな〜と思ったりした。

そういえば今年は masawada さんとオフラインでお会いしたことあったっけ。1月の納会ではきっと会ってるな。東京勤務の同僚と会う機会がめっきりなくなりましたね。2020年ももうすぐ終わりです。

こちらからは以上です。

*1:今回は100点満点で7点みたいなことしかしてない

Apple M1 Mac で mackerel-agent を動かす

このエントリは Mackerel Advent Calendar 2020 の16日目です。遅刻です。

qiita.com

昨日は kazeburo さんでした。

kazeburo.hatenablog.com

今日は Apple M1 Mac で mackerel-agent を動かす話をします。
前日の "Apple M1 Mac で Go を動かす" の続きというつもりで書き始めましたが、気がつけばあまり関連性のないエントリになりました。

blog.astj.space

disclaimer

筆者 (id:astj) はこれを書いている現在 Mackerel の開発チームメンバー、いわゆる「中の人」です。

また、 Mackerel は mackerel-agent による Mac の監視を正式にはサポートしていません。開発チーム内に Mac ユーザーのエンジニアが多いことからある程度メンテナンスされているという実態はありますが、 Mackerel として正式に動作保証をしているものではない、という背景はご留意ください。

正式なサポート対象についてはヘルプをご確認ください。

mackerel.io

2022/2/8 追記

現在は、特別な手順を踏まなくても Homebrew tap 経由で Apple Silicon Mac 上で mackerel-agent を動かすことができます。
mackerel.io

Apple Silicon への対応はこのエントリで告知されていました:
mackerel.io

以下の内容は2020年末時点での古い内容となります。

続きを読む