Pixel Pedals of Tomakomai

北海道苫小牧市出身の初老の日常

今日は Rust.Tokyo 2023 の日です

Rust.Tokyo 2023 のために、かなり久々にメルカリさんに来ています。以下は自分のためのメモです。

オープニング

  • 会場紹介
    • 入館証は退館時も必要
    • 18F から出ると戻れないので、出ない
    • 自販機無料
  • ハッシュタグ#RustTokyo2023
  • 2019 年から開催、 2 回目のオフライン開催
  • オフラインで登壇者、参加者の相互交流を目指す
  • オンラインのメリットも活かしたい

IoTプラットフォーム開発におけるRustの活用 / @garasubo さん

  • Actcast
    • エッジ AI デバイス ( ラズパイ ) を管理
    • 指定されたAI アプリを動かす
    • WEB UI 経由
    • クライアント、 Device API 、 WEB UI が Rust
  • 2017 年に導入
    • 高速、軽量、型システム、マルチスレッド
    • ファームウェアのバグは避けたい
  • 使い始めてから今までで、 Rust のエコシステムが大きく変わった
  • 初期リリースはスレッド
    • その後、徐々に async/await 化
    • blocking クレートの利用
    • async/await は伝搬する → 変更料が多く、難しい
    • tokio/futures/blocking 非同期ランタイムの混在
    • tokio ランタイム前提の関数は tokio ランタイム内で呼び出す必要がある
  • エラー型は failure を実装していた
    • メンテナンス中止になり anyhow/thiserror へ変更
    • std の Error トレイとも改善され、使い勝手が良くなった
    • sentry エラー報告ツール、ボイラープレートの現象
    • failure のエラー型のバリアントが 50 以上あった(!)
    • failure を前提としたエラー処理
    • 部分的な置き換え → 新たな小さいエラー型を、旧エラー型に変換
  • ライブラリの変化
    • rusoto から aws-sdk (非公式から公式へ)
    • メンテナンス中止、破壊的変更が入ってくる
    • actix のメンテナがレポジトリ全消去した、など
  • Rust の型システムはメモリーリークは容認する
    • std::mem::forget 、std::rc::Rc 、 join しない thread
  • tokio::select! で終了しない thread があると、どんどんリークしていく
  • CI/CD の時間が長くなる
    • ビルドキャッシュ (sccache, Swatinem/rust-cache) 、 cargo build-timings、 cargo nextest でテストケースの実行時間を計測
  • ビルトインの名前の乱用
    • 例: std::sync::Mutex と tokio::sync::Mutex
    • フルパスの利用、 rename
  • Q). async/await は導入する価値がある?
    • A). 書きやすい。 async/await 前提のライブラリも多い
  • Q). メモリリークの原因を見つけるには?
    • A). 問題が起きた→変更の差分から
    • Q). プロファイラなどでうまく行った例は?
    • A). 今回の例はエッジデバイスでプロファイラは利用不可だった。 AWS 環境であれば、監視で見つかることはある
    • A). Rust ではなく IoT ならではの問題。ブラウザで動く JS とかも同じでしょう
  • Q). no_std ?
    • A). std 。 AI アプリのほうが大きいので、 std を削っても微妙
    • A). そもそもラズパイなので強力
  • Q). mem::forget は使う?
    • A). 使ったことがない。いつ使うのでしょう
  • Q). ラズパイ環境の難しさは?ライブラリに制限が入る?

かにさんタワーバトル / @sadnessOjisan さん

  • 日経電子版
    • fastly → Vessel
    • リポジトリが全て別れており、 CDN でアグリゲート
    • 24 の micro service が Node.js v12 で動いていた
    • 11 ヶ月で v20 まで上げた
  • Node.js はリリースサイクルが早い
    • npm のビルドが通らなくなる
    • アップデートの度に時間がかかる
  • 比較的、安定しているものの技術スタックを変更
    • Node.js VS Golang VS Rust
    • Rust が要件をすべて満たしていそう
  • 社内に Rust 採用事例があった
    • Fastly の Computing@Edge
    • Wave BFF サーバー
  • Rust は batteries-included ではない
    • 依存が多い。 3rd party ecosystem の心配
    • デファクトであれば、採用してもいいのでは
  • Axum
    • HTTP server フレームワーク
    • Hyper と Tower ベース
    • Hyper はプリミティブすぎる HTTP Server
    • Tower は Request を受けて Response を返す関数
    • Services をレイヤによって重ねる
    • Axum は Hyper/Tower のごく薄いラッパ
  • Axum は 3rd party のアプリだが、採用して大丈夫か
    • 密結合を防ぐ
    • 依存を限定する
    • 横断的関心事は Tower のレイヤに押し込む
    • 例えば、 Axum が使えなくなったら Hyper を直接使える
  • Q). Rust 採用にあたり CTO をどう説得した?
    • A). CTO はいない。合議制。小さいところからやっているため
  • Q). 教育コスト、導入コストは?
    • A). 書ける人、書きたい人が少なかった。書きたい人の熱量で開発している。 E2E テストは充実させている
  • Q). DI は?
    • A). コンストラクタインジェクション一択。ライブラリは使っていない

csbindgenによるC# x Rust FFI実践事例 / @neuecc さん

  • Cy#
    • C# の会社
    • OSS 開発
    • ゲーム開発、全部 C# でやる。 C# monorepo
  • C# を使いたいが、 Android NDK ネイティブ APIC++ しか書けない
  • Rust エコシステムが充実
    • cargo build 、 cc/cmake との連携、 bindgen
    • 難しいから選択肢に上がっていなかったが、やってみると罠は少ない
  • csbindgen
  • Rust は unsafe まみれのコードになるが、そこはケアしない
    • Rust/C# の境界を繋いでいるのは、超危険な C なので、自然
    • 外側の Rust/C# できれいな安全な世界を作る
  • 型システムは Rust/C# でほぼ 1-1
  • MagicPhysX
  • YetAnotherHttpHandler
  • NativeCompressions
    • LZ4 / Zstandard が多い
    • C# binding を書いてもいいが、バージョン追随が厳しい
    • native binding が良い選択
  • Q). serde と C# のシリアライザの比較
    • A). 自作のもののほうが良いが、汎用性を持たせると Rust の良さが出ないのでは
    • A). シリアライザ作成者目線として、 serde はもっとパフォーマンス挙げられそう
  • Q). テストは?
    • A). ノーテストライブラリ。生成を流しているので
    • Q). binding を使った場合にどこをテストする?
    • A). C# 側でテストをすれば十分でしょう。 E2E
  • Q). C# - Rust - C のオーバヘッドは無視できる?
    • A). コンパイラオプションで消し飛ばせそうだが、試していない
    • A). Rust のリンカのオプション
  • Q). unsafe 塗れなら Zig のほうがいいのでは
    • A). Rust の開発環境は素晴らしい。安定もしている
  • Q). ref out in の対応は?
    • A). しません。
  • Q). C++/CLI は選択肢に上がらない?
    • A). 上がりません
  • Q). C# er が多いが、 Rust への取り込みは?
    • A). 第二の言語として、キャッチアップしている。使っていく、広めていく

素材メーカーが内製開発でRustを使っている話 / AGC株式会社

  • Rust のチームの立ち上げ
  • 半分はガラス、半分はケミカル
  • データサイエンス → プロダクトの内製開発
    • データサイエンス Python
    • 数理最適化 Rust
    • ソフトウェア・エンジニアリング Rust, OSS 活用
  • データサイエンティストはにわかプログラマ
    • 現場で彼らの Python コードが動くのは考えにくい
    • Python の弱点を補う言語
    • データサイエンス組織からソフトウェア組織へ
  • データサイエンスを、事業に活かしていくためのエンジニアリング
    • AutoML 、 製造プロセスの改善
    • バックエンドサーバで GraphQL のサーバが Rust 製
    • actix-web + async-graphql, sqlx
    • MLflow とのやり取りは自作(Python はクライアントがある)
  • 技術選定
    • SNS、ブログ、実際に使う
    • juniper VS async-graphql, sqlx VS Diesel
  • Rust 歴は半~ 1 年ちょっとのチーム
    • Python はみんな書ける
  • 環境構築、プロジェクト管理は楽
    • Python は pyenv+Poetry VS Anaconda
  • コンパイラが信頼できる、型システム、エラー処理
    • Clippy が優秀
    • Python コードの品質も上がる(型ヒント、イミュータブル)
  • 困った点
    • 学習コストは高い
    • ビルドが長い(集中力が切れる)
    • お手本となるソフトウェアエンジニアがいない (We are hiring)
  • Cargo ワークスペース
    • Orphan rule でパズルが発生
    • newtype パターンでコード量が増えた → 元の構造に戻った
    • 任意のスキーマを持つテーブルデータ → match 文が複雑に
  • The Rust Programming Language の輪読会
    • Rust 経験者が 1 名から 10 名に
  • 問題解決力を鍛える!アルゴリズムとデータ構造
    • 複数チームでの交流
  • Rust という本を大量購入
    • Rust が流行っていると思わせる、印象操作
  • 今後はイベント参加、 OSS 公開など
  • Q). マイグレーションはどうしていますか?
    • A). sqlx CLI を使っている。 gitlab の CI/CD から本番へ
  • Q). PyO3 は使っていますか
    • A). やったことはある。運用はしていない
  • Q). 高級言語からシステム寄りの言語へどうアプローチ?
    • A). 勉強会。覚えのある人を中心に教わる
  • Q). Bazel でビルド時間を削減できる?
    • A). 高性能 PC 。リンカで mold 。分散ビルドはまだしていない
  • Q). データサイエンスは Python だろうが、 Rust へ移行して困ったことは?
    • A). Apache arrow 。全言語でのデータフレーム。困らないだろう
  • Q). mojo を使う可能性は
    • A). 試す可能性はある

Rustがユニークビジョンにもたらした恩恵と苦労 / ユニークビジョン株式会社

  • 2016 年。Twitter の帳票出力で利用(ほかは Ruby
  • 2018 年、 LINE 系で Rust
  • その後、他のプロダクトでも Rust を利用
  • 2023 年には、 Rust のコードが増えている
  • 14 万件の CSV のダウンロードが Ruby では厳しかったため
    • Rust でうまく行った。 15 分程度
  • 大量データ登録、高頻度のバッチなどで Rust の利用
  • LINE は Twitter の 3 倍の負荷に耐えられるように
    • Rust 、 actix-web を利用
  • SNS の情報クロールなどで、 Rust
  • 1 秒以内にレスポンスを返す必要がある WEB hook
  • コンパイラ、 cargo 、 clippy が優秀
    • 言語としても、面白そう
  • Rust によって採用も増える
  • Rust での苦労
    • clone() まつり
    • デプロイ後に動的に調整したい
    • crate 不足
  • Rust の取り組み
    • Slack のチャネル、社外勉強会、スポンサー、 crate の作成
  • twapi
    • 既存のものは API 不足
    • URL エンコードのバグ
    • Twitter API を長く使ってきた経験を生かした
    • twapi-reqwest
    • twapi-v2 ( serdeflatten によって、 API が勝手にフィールドを返してくることに対応)
  • actix-daemon-utils
    • actor をループでやり取り、グレースフルに再起動
  • csv-zip-maker, dynamodb-mutex, redis-batches, era-jp
  • Q). 他の経営陣を説得した?
    • A). 最初は Rust じゃないと動かなかったので。一度入れば使っていける。新しいから採用でもいいなど
  • Q). Ruby に比べて実行時エラーが減ったりした?
    • A). typo はなくなった。
  • Q). clone を解消したら速くなる?
    • A). そんなに変わらない。そもそも速い
  • Q). OSS 公開に工数がかかるのでは?
    • A). そんなにない。ドキュメントくらい
  • Q). 買収後の Twitter API の苦労は?
    • A). どんどん API が変わるようになったのはつらい
  • Q). Ruby から Rust への学習コストは?
    • A). 個人で書いているうちは大丈夫。他のメンバーには難しい。ドキュメントを読んだり、 Slack を使ったり
  • Q). 既存のライブラリを改善せずに書き直したのは?
    • A). スピード感がなかった。自分たちのほうが詳しいという自負があった

並行キャッシュライブラリの開発で得られた知見 / @tatsuya6502 さん

  • キャッシュ : 低速のメディアから取得したデータを高速のメディアに保存
    • インメモリキャッシュ : 容量制限付きの hash map
  • Moka
    • Java の Caffeine キャッシュを参考(作者公認)
    • crates.io Sentry.io のバックエンドサービスで使用
  • future 版と sync 版がある
  • max_capacity time_to_live
  • or_try_insert_with : 無ければ async ブロックを実行する
  • キャッシュの評価指標は、ヒット率
    • ポリシーで決まる。使われなさそうなものを削除
    • Caffeine simulator で測定できる
    • 本番の検索エンジンのディスクアクセスパターンを記録した、公開データを利用
    • Moka は Tiny LFU / LRU よりヒット率が高い
  • LRU の前に LFU Filter が入っている
    • 使用頻度の低いデータの入場を拒否
  • ロック競合
    • Moka は並行キャッシュ
    • スレッドをたくさん用意しても、動かない
    • チャネルによってキャッシュアクセスをまとめて、ロックは誰かが代表して行う
  • Lock free : compare and Swap 命令などを使う。ロックしない
    • Moka では、自前で実装した並行ハッシュテーブル cht で利用
    • LFU フィルタなどの他のデータ構造は、 mutex と一括適用を利用
  • ロック実装に future 対応と未対応があるので注意
  • async を値渡ししたときの振る舞い
    • 容量が 7 倍になって返ってくる(!)
    • コンパイラ側の最適化で、複数コピーされるため
    • 値渡しではなく Box<Pin> を利用するというワークアラウンド
  • 非同期キャンセルは大変
    • .await の途中で poll を辞めて future 毎 drop できる → キャンセル
    • WEB app などでは、接続が切られたらキャンセルすれば便利
    • アプリ側が対応しないと、不整合な状態が起きる
    • Drop trait を利用するのがいい
    • spawn すると、キャンセルの影響を受けない
  • Moka には特定のランタイムがないので、 spawn ができない
    • Shared トレイトで共有しておいて、リトライ
    • リトライ自体がキャンセルされることもある
  • 今後の展望
    • wasm 対応(シングルスレッド)
    • snapshot から復元
  • Q). atomic 命令はインラインアセンブラ? CPU 毎に記述?
    • A). llvm が CPU の命令を抽象化している。標準ライブラリがそれをラップしている。 crossbeam クレート
  • Q). stale while revalidate 機能は?
    • A). ない。アプリ側でロジックを書く
  • Q). read が多いのに RwLock ではなく mutex なのは?
    • A). 内部のデータ構造は get されたときに write が必要。内部的にはほとんどの操作が write を伴う

Rust 業務経験がない開発者で集まって汎用ツールを開発した話 / kajiwara さん

  • Roggol
    • イベントソーシング。 RMU (Read Model Updater)
    • 専用の RMU を実装していたが、すべて同じようなことをしている
    • 取得、加工、格納、オフセットの保存
    • 同じイベントデータストアから、重複なしで各プロセスがデータを取る
    • 設定ファイルによる実行 → 再コンパイル不要
    • OSS 公開を目指す
  • チーム
    • Rust 経験者なし、 Rust 愛は高め
    • 2022/02 から現在も
    • Rust VS Golang VS Scala → 横に並べて実行したいので必要なリソース量の少ない Rust
  • 想定通り
    • コンパイラ、 clippy に怒られる
    • 実行が速い、サイズが小さい
    • 社内の Rust 採用の後押し
    • ポジティブなことは巷で言われている通り
  • 想定外
    • Rust への抵抗は少ない
    • コンパイルはそんなに遅くない(個人の感想)
    • 学習環境の充実 the book, Rust By Example, Rust API Guidelines
    • 外部 crate の充実(乱立には戸惑う)
    • 他の言語を書いたときにソワソワ( clone しなくてもコンパイルエラーがないとか)
  • unwrap はよくない
    • エラーメッセージが開発者にしかわからず、他のチームに聞かれてしまう
    • 自分たちにもわかりにくい
    • unwrap をやめて Result で返す
    • Optionanyhow context で
    • 本当にエラーでも、 expect
    • assert が直ぐ側にあるなら unwarp でも
  • 並列処理は型だけでは不十分
    • Arc<Mutex>clone しても、状態は共有される(知識不足)
    • コンパイラは何も言わない
  • Tonic で protobuf ファイルを扱う
    • protobuf ファイルが先に無ければいけない
    • prost-reflect を使う必要がある
    • 動的な仕組みと Rust を組み合わせるときは注意
  • 報われたこと
    • Scala と比べてイメージファイルが 1/10 程度に
    • CPU、メモリ使用率が安定 → 安心して運用
    • Scala だと、 JVMGC 対策などの運用経験が必要。 Rust では不要だろう
  • Q). crate の選択肢が複数あるときにどうする
    • A). ダウンロード数と更新間隔
  • Q). チーム内でのノウハウの共有は?
    • A). チーム内では同じコードベースを触っているので。チーム外は課題
  • Q). ビルド時に protobuf の形式が不明とは?
    • A). ビルド時は利用者が不明。誰がどの protobuf を使うか不明。利用者はどんな protobuf か知っているので、使える
  • Q). なれない言語での初回リリースのステークホルダとの調整は?
    • A). ステークホルダの声は小さかったので大丈夫。調整は特にしていない

Ferrocene - Rust in Critical Environments / @argorak さん

  • ferrous systems
    • rust-analyzer, Knurling, Bindgen, sudo-rs
    • Training
  • ferrocene
    • language specification, Long Term support
  • qualified tool
    • compiler, specification, test (mapped to specification), Evidence (test output)
  • goal
    • evidence
    • always pass all tests
  • 69,000 additions for codes
  • Paranoid mode for Rust
    • Slow but safety
  • OSS stack
  • Safety Manual
  • Constant testing, merging of upstream
    • automationed

クロージングセッション

  • スピーカーとメルカリさんに感謝
  • Rust.Tokyo
    • プロポーザル募集(今年は多かった)
      • 良いプロポーザルも、トピックの偏りを考慮して落選することがある
      • 数が多いと、会場を大きくしたり採用も増やせる
    • スタッフ募集
    • 大きくすることは目的ではないが、大きくなるとできることが増える