ハトネコエ Web がくしゅうちょう

プログラミングやサーバー・Web制作、チームマネジメントなど得た技術のまとめ

Mojo🔥 を Docker🐳 で動かすようにしてみた

随時更新していくかもしれないし、日付が空いたら別記事にするかも。

Mojo をさわってみたのでメモしていく。

Mojo🔥 on Docker🐳

ローカルで動かせると楽なので

github.com

を作ってみた。

ARM CPU の Mac だとまともに動かないので、
Intel チップの Mac をまだ持っていてよかった……。
(ARM CPU でも docker build してみたけど、1時間経っても完了しなかったのでたぶん無理)

所感

  • X(旧Twitter)で「Mojo」と検索しても違う情報ばかり引っかかってつらい……
  • 参考になるリポジトリ: https://github.com/tairov/llama2.mojo
  • GitHub がまだ Mojo に対応していなくて Languages のところに入ってこないのおもしろい
  • GitHub で .mojo ファイルを見てもまだシンタックスハイライトは効いていない
  • Mojo のビルド、わりと速くてスイスイ試せるのはいいところ
  • 変数展開(string interpolation)は今のところないかも?

関数周り

deffn のどちらでも関数の宣言は可能。
def だと Python の世界、fn だと Mojo のルールに則(のっと)ったコーディングが求められる。

Rust の所有権や借用の概念があると聞いていたので、

fn main():
    let x = 100
    let y = 200
    let z = add(x, y)
    print(x, y, z)

fn add(x: Int, y: Int) -> Int:
    print(x, "+", y, "=", x + y)
    return x + y

のようなコードを書いてみたけど、エラーにならずに通った。

Rust だと let z = add(x, y) で x, y の所有権の移動が起きて
print(x, y, z) のところが実行できないよとコンパイルエラーが通るはずだけれど、
Mojo はデフォルトが borrowed (借用)モードになっているようで、
アンパサンド( & )を関数の引数に付けたりしなくていいようになっている。

  • borrowed
  • inout
  • owned

の3種類のアノテーションを引数に付けて管理する方法は、
Rust でややこしくなる参照や参照外しを考えなくて済むようにしていて、
記述のしやすさをサポートしているように思う。

代わりに transfer 演算子 (^) という新しい概念を生み出してはしまったが。
参考: https://docs.modular.com/mojo/manual/basics/#argument-mutability-and-ownership

ここらへんの差異は、
Rust プログラマーにとっては、理解ができてもややこしく感じる要素になりそう。

owned 引数に対して transfer 演算子を使わないとコピーを作成する挙動が発生するなど、
プログラムの実行スピードに関しては、Rust よりも意識して書かないと速さを出せないかもしれない。

Homebrew Tap の SHA256 ハッシュを簡単に更新できるようにする

自分用の Homebrew Tap を作成したい!

nekonenene.hatenablog.com

こちらの記事で作った git-branch-delete-merged-rs
Homebrewbrew install でインストールできたら楽だなあ、と思いました。

そこで、『GoReleaser で Go 製 CLI のリリースを自動化& Homebrew でインストールできるようにする』の記事の『Homebrew でインストールできるようにする』の項を参考に、
homebrew-tap というリポジトリを作って、Homebrew 用の設定を置くことにしました。

github.com

ちなみに公式の説明は、
けっこうサッパリしていてわかりにくいので、作り方を検索したり、
GitHub内で「homebrew-tap」で検索をかけて他の人の例を見てみるのがオススメです。

私はけっこう aws/homebrew-tap を何度も見て参考にしました。
https://github.com/aws/homebrew-tap

自動生成の Formula ファイルを見てみる

brew create --tap nekonenene/homebrew-tap --set-name rust-test --rust https://github.com/nekonenene/git-branch-delete-merged-rs/releases/download/v1.0.4/git-branch-delete-merged_Darwin_x86_64

のようなコマンドを打つと、
/usr/local/Homebrew/Library/Taps/nekonenene/homebrew-tap/Formula/rust-test.rb に以下のようなファイルが作られます。

# Documentation: https://docs.brew.sh/Formula-Cookbook
#                https://rubydoc.brew.sh/Formula
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!
class RustTest < Formula
  desc ""
  homepage ""
  url "https://github.com/nekonenene/git-branch-delete-merged-rs/releases/download/v1.0.4/git-branch-delete-merged_Darwin_x86_64"
  sha256 "5dd726b01b5cb78d0f256c3ba7ee6d0139691d0d39d84525411911de00138481"
  license ""

  depends_on "rust" => :build

  def install
    # ENV.deparallelize  # if your formula fails when building in parallel
    system "cargo", "install", *std_cargo_args
  end

  test do
    # `test do` will create, run in and delete a temporary directory.
    #
    # This test will fail and we won't accept that! For Homebrew/homebrew-core
    # this will need to be a test that verifies the functionality of the
    # software. Run the test with `brew test rust-test`. Options passed
    # to `brew install` such as `--HEAD` also need to be provided to `brew test`.
    #
    # The installed folder is not in the path, so use the entire path to any
    # executables being tested: `system "#{bin}/program", "do", "something"`.
    system "false"
  end
end

ダウンロードするファイルのURLと、
そのファイルをSHA256でハッシュ化した値
を記載する必要があります。

ハッシュ値は以下のようなスクリプトで取得することができます。

curl -fL https://github.com/nekonenene/git-branch-delete-merged-rs/releases/download/v1.0.4/git-branch-delete-merged_Darwin_x86_64 | shasum -a 256

5dd726b01b5cb78d0f256c3ba7ee6d0139691d0d39d84525411911de00138481  -

しかし、各OS・CPU種類ごとにバイナリファイルを作成している場合、
それぞれに対してこのコマンドを実行するのはなかなかに億劫(おっくう)です。

SHA256ハッシュ値をカンタンに取得できるようにする

というわけで作成したのが、この update_config.rb です。

configs ディレクトリに

{
  "inputs": {
    "github_url": "https://github.com/nekonenene/git-branch-delete-merged-rs",
    "version": "v1.0.4",
    "filename_template": "git-branch-delete-merged_{os}_{cpu}"
  }
}

のようなJSONファイルを置いてから

ruby update_config.rb configs/git-branch-delete-merged.json

を実行すると、必要なバイナリファイルを見に行って、
https://github.com/nekonenene/homebrew-tap/blob/v1.0.0/configs/git-branch-delete-merged.json のように
outputs キーの中に URL と SHA256 ハッシュ値のペアを入れたJSONファイルへと更新してくれます。

外部ライブラリへの依存がないので、実行前に gem install が不要なのも便利なところです。

あとは config_provider.rb でそれをパースしたものを、
Formula/git-branch-delete-merged.rb で使うような作りになっています。*1

これによって、バージョンアップ時に Formula ファイル側を変更する必要がなくなりましたし、
新たな Formula を足すときも、既存の Formula ファイルをほぼコピペするだけで使い回せるようになりました!

もし便利に感じましたら、 https://github.com/nekonenene/homebrew-tap
update_config.rb などを、お好きにコピーしたり改変したりしてお使いください!

*1:config_provider は aws/homebrew-tap を基に作成しました

【最速レポ】ISUCON夏祭り2023、最高すぎたのでレポートします!!

本日こちらのイベントに参加してきました!

めちゃくちゃ良いイベントでしたので、さっそくレポートを書きたいと思います。

( https://twitter.com/isucon_official/status/1695377159685349705 より引用 )

なんで参加したの?

私が ISUCON に参加したのは ISUCON 8 でした。
同僚といっしょに3人で出て、
「ま、とりあえず出ることが大事でしょ!」って軽い気持ちでノー勉で臨んだら、
きれいに0点を獲得しました(笑)

ゼロ♥ ゼロ♥ ゼロ♥ ざぁ〜〜〜〜こ♥♥♥

その後、転職があったり忙しかったりで参加はできていなかったのですが、
そのうちいつか出よう・・・と意識はしていました。

同僚が別のISUCON練習会的なもの(CTO協会主催)に参加していてうらやましかったので、
このイベントを見つけたときにすぐ申し込みました!

ちなみに、チームタピオカのメンバーの1人に、
「こういうイベント見つけてさ……」と話したら「自分も行こっかなー」と言ってたんですけど
結局来てなかったです!!! おいぃぃぃぃいいい!!!!! 🤪

めっちゃ夏祭りだった

イベントの名前は 『ISUCON夏祭り2023』 でしたが、
まさか本当に夏祭り会場と化しているとは・・・!
行ってみて驚きました。

射的やってる!!!!!!!!!!

大人気でした。
おそらく人生初めての射的で、テンション爆上がりでした。
2発使っても倒せなかったのですが、隣の人は2発とも倒していてプロでした。

他にも風船ヨーヨー釣り、お面のくじ引き、ラムネなどドリンクの配布をやっていて、
完全に夏祭りでした。

イベントスタッフ視点で考えると、
射的のための銃のレンタルや、風船ヨーヨー釣りのための水槽の用意、当日水を張ってそれを捨てる手間など、
当日までの準備・設営・撤収が大変すぎて、これをやり切っているのすごいなあ・・・と感じました。

写真だと伝わりにくいんですが、夏祭りスペースはこんな感じでした。大盛況です。

企業ブースも常に人がいました。
これは、企業ブースをすべて回るスタンプラリーを達成すると
ISUCOIN(イスコイン)がもらえるというボーナスがあったことも貢献していたと思います。

よく考えて作られているイベントでした。

こちらが偉大なる ISUCOIN(イスコイン)。
入場時に1枚もらえて、キラキラ光る素敵なノベルティーに、
最初から気持ちが盛り上がりました。
4枚集めるとお楽しみ抽選会の抽選券と交換できます。

ハンズオンがすごく勉強になりました

rosylilly さんがおこなってくださいました!
今回のイベント参加の一番の目的のハンズオン!

とてもタメになりました、ありがとうございました。
(ちなみに、5時起き&2時間半×2のハンズオンを成し遂げたrosylillyさんは、交流会の頃には魂が抜けていました・・・おつかれさまでした・・・)

最初にアンケートを取ってくださったんですが、
参加者はISUCON未参加の人が多数でした。

内容は、完全なハンズオンというよりは、時間の関係で講義メインで、
https://github.com/catatsuy/private-isu のWebアプリとベンチマークを立ち上げてみるところまでを全員にやってもらいつつ、
ボトルネックとなる部分の見つけ方や実際の直し方、
スコアが上がっていく様子はrosylillyさんがおこなって見せていくという形式でした。

private-isu は画像ファイルと db dump がそれぞれ1GBある関係で、
みんなが休憩時間の開始とともにダウンロードするも、
さすがに重くなって、20分の休憩時間中にダウンロードが終わらないという珍事件もありました(笑)

役立つ話がいろいろあったのですが、改めて文章に直すと長くなってしまうので、
ハンズオンを聞きながら書いていたメモの一部をここに貼っておきます。

  • 8時間かけてチューニングし続ける競技でなく、8時間かけてデプロイし続ける競技
    • くり返しお話されていた大事な概念
  • そのときの流行りが問題に影響することがあるので、そこを知っておくことが対策になったりする。
    • 例えばそのときの流行に関連して nginx でなく envoy が使われたり、MySQL 8.0 への移行の過渡期には、MySQL 5.7 から 8.0 への移行ができるとスコアアップできる問題が出たこともあった
  • アプリからは呼び出されていないのに、マニュアルには「バルクリクエストができます」と書いてあって、バルクリクエストをすると実際速くなるようなこともw
  • Goでやると
    • go fmt などの兼ね合いでコンフリクトが起こりやすいところが欠点
    • 型情報があるのでエラーが起こりにくいことが利点
    • 実行速度の話はよく出てくるが、実際のところISUCONではそこはほぼ影響しない
  • GitHub Copilot めっちゃ便利。関数名や変数名を書くと、代わりにコードを書いてくれる
  • なんとなくの手順
    • ウェブアプリをさわってみて、routing を見てみて、なんとなくどんなアプリかを把握
    • Developer Tools でどういうものが見えるか見る
      • 本番のベンチマークは、わざとログインに失敗したりするなど、カバレッジを満たすようにいじわるなリクエストもおこなうように作っている
      • 返ってくるレスポンスが同じになるようになればいい
        • だから、フルスクラッチでコードを書き直す宗派もいる。そっちのほうが楽な人も
  • ISUCON特有のエンドポイント: initialize
    • DBリセットをおこなう
    • 今回でいうと db_initialize メソッドがあるが、例えば memcached を使うなら、そこのメソッドで削除をおこなう必要がある
    • CREATE TABLE と db_initialize メソッドを合わせてみると、テーブルの足りていないインデックスがわかるだけでなく、ベンチマークが何件のデータを作っているのかわかる
  • 運営による再起動計測
    • 11211ポートで動く偽memcachedがあって、それに気付いても、再起動後に元の偽memcachedが再起動後に立ち上がってポートぶつかって……という事例があった
  • 最初の初期データを無くしてしまうとインスタンス立て直しになるので注意
  • ベンチマークの score を取得したら、そのスコアで score-1234 などブランチを切っておくかタグを付けるとわかりやすい

その他にも、いろいろな知識と心得を得られました。
ありがとうございます。

また、ハンズオンの終わりに、自分の気になっていた
「3台のサーバーってどう使い分ければいいの?」という質問にも答えてくださりました。

もちろんそのときの問題によるけれど、
よくやるのは2台をアプリケーションサーバーにして1台をDBサーバーにするやり方とのこと。

DBサーバーについては、
MySQLだけだとCPU負荷とdisk I/Oの負荷がある一方、メモリ負荷はそんなないので、
そこの余ったメモリリソースを埋めるよう、 memcached や redis など KVS 系のDBを入れていると伺って
「なるほど〜〜〜!!!!」とめっちゃタメになりました。

最後の交流会

午後のハンズオンが終わり、しばらくすると交流会でした!

ISUCONに興味ある層なだけあって、
技術的なチャレンジを普段からされている方が多く、楽しい時間でした。

参加者全員の写真撮影があり……
(一番最初に貼った集合写真の撮られる側の視点ですねw)

このイベントの運営代表をしてくださった Shoco さんの
お誕生日をお祝いするケーキが登場するなど、
優しさあふれるとても素敵な会でした。

とてもいいイベントで、参加できてよかったです。

運営スタッフの方々、
知見を共有してくださった登壇者の方々、
わかりやすいハンズオンをおこなってくださった rosylilly さん、
会場を提供してくださったヤフー株式会社さん、
交流会で突然話しかけても優しく応えてくださった方々、みなさまありがとうございました!

次回も楽しみにしています!!!!!!!!!
>>> 突然の運営への圧 <<<

急に思い出したからここで書きますが、
お昼のクイズ大会、ISUCONに詳しくないから心配だったけど、
詳しくない人もわかる問題が多くていい難易度で楽しめました!
ありがとうございました。