くりにっき

フルスタックキュアエンジニアです

mysql2-nested_hash_bindを作った

ISUCON合わせで作ったやつ第n弾です。*1

github.com

モチベーション

達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践:書籍案内|技術評論社(通称ISUCON本) を読んでた時に

SELECT
  `posts`.`id`,
  `posts`.`user_id`,
  `posts`.`body`,
  `users`.`account_name` AS `users.account_name`,
  `users`.`authority` AS `users.authority`,
  `users`.`del_flg` AS `users.del_flg`
FROM `posts`
INNER JOIN `users` ON `posts`.`user_id` = `users`.`id`

のようにカラム名ドットが含まれるSELECT文を https://github.com/jmoiron/sqlx に渡すと users の部分をいい感じにGoのstructに詰め替えてくれると書かれていたのですが、Rubyでも同じことをやりたくてモンキーパッチgemを作りました。

使い方

READMEが全てなんですが、 using Mysql2::NestedHashBind::QueryExtension を書いたスコープで Mysql2::Client#queryMysql2::Client#xquery にモンキーパッチを仕込みます。

require "mysql2-nested_hash_bind"

using Mysql2::NestedHashBind::QueryExtension

db = Mysql2::Client.new(
  host: ENV.fetch("MYSQL_HOST", "127.0.0.1"),
  port: ENV.fetch("MYSQL_PORT", "3306"),
  username: ENV.fetch("MYSQL_USERNAME"),
  database: ENV.fetch("MYSQL_DATABASE"),
  password: ENV.fetch("MYSQL_PASSWORD", ""),
  charset: "utf8mb4",
  database_timezone: :local,
  cast_booleans: true,
  symbolize_keys: true,
  reconnect: true,
)

rows = db.query(<<~SQL)
  SELECT
    `posts`.`id`,
    `posts`.`user_id`,
    `posts`.`body`,
    `users`.`account_name` AS `users.account_name`,
    `users`.`authority` AS `users.authority`,
    `users`.`del_flg` AS `users.del_flg`
  FROM `posts`
  INNER JOIN `users` ON `posts`.`user_id` = `users`.`id`
SQL

rows.first
#=> {:id=>1, :user_id=>445, :body=>"test", :users=>{:account_name=>"sue445", :authority=>false, :del_flg=>false}}

頑張りポイント

ISUCONで利用するということでパフォーマンスチューニングを頑張りました。

具体的には https://github.com/evanphx/benchmark-ipsベンチマークをとりつつ https://github.com/tmm1/stackprof でgemのボトルネックを調べてボトルネックになってた箇所を改善してます。

stackprofで見つかったボトルネックの1つに Symbol#to_s があったのでfreezeされたStringを返す Symbol#name を使おうとしたのですが、Symbol#name が使えるのがRuby 3.0以降だったのでこのgemもRuby 3.0以降でしか使えないようにしてます。

ベンチマークのコードとレポートは https://github.com/sue445/mysql2-nested_hash_bind/tree/main/benchmark に置いているのでどれくらいオーバーヘッドあるかはここを見てください。

*1:まだOSSにしてないものを含めたらこの手のツールを5〜6個作ってる気がするので何番目かなんて正直把握していない

Ruby 3.1.2 with YJIT vs Ruby 3.2.0-dev with YJIT

tl;dr;

  • Ruby 3.2.0-devのYJITはRuby 3.1.2のYJITに比べてパフォーマンスが向上して、特にメモリ使用量が大きく削減されている

モチベーション

ISUCONの事前講習*1で講師の人が「RubyはISUCON前になるとパフォーマンス改善系のコミットが入るので、自分たちのチーム(白金動物園)ではいつもruby-headを使っている」と言っていたのですが、Ruby 3.2.0-devだとRust実装のYJITが入っているのでISUCONで使うためにどれくらい性能改善してるか知っておきたかったのが一番大きなモチベーションです。

Ruby 3.2.0-devの何がすごいか

Ruby 3.1系のYJITはC実装でしたが、Ruby 3.2系ではRust実装に変更されています。

techracho.bpsinc.jp

ただしRust実装のYJITは現時点ではpreview版などにも含まれていないため、Rust実装のYJITを利用するためにはRuby 3.2.0-dev( https://github.com/ruby/ruby のmasterブランチ)を利用する必要があります

Ruby 3.2.0-devでRust版のYJITを使う方法

  • Rustの処理系をインストールして --enable-yjit をつけてRubyをビルドする必要がある
    • YJITを使わない場合にはRustのインストールは不要
  • さらに実行時に --yjit を渡す

Ruby 3.2.0-devをYJITを有効化してビルドする方法は id:koic さんの下記エントリが詳しいです

koic.hatenablog.com

計測対象のアプリケーション

達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践:書籍案内|技術評論社(通称ISUCON本) で紹介されてる https://github.com/catatsuy/private-isu を利用しました。

github.com

  • ベンチマーカー
  • 競技用サーバー 2台 *2
    • インスタンスタイプ: c5.large(vCPU 2, メモリ3.75GiB)
    • EBS: gp3 20GB
    • 2台の振り分けは下記
    • pumaのworkerプロセスは3つ
      • vCPU 2なので1.5倍してworkerは3プロセス起動させています *3

どの過去問を使うかにもよると思いますが、他にも何種類かやった感じだと3.2.0-devが3.1.2より悪くなってることはなかったです。(Ruby以外にボトルネックが残ってる状態だとメモリ以外はあまり変化はなかった)

使ったバージョン

Ruby 3.1.2(安定版の最新のRuby)とRuby 3.2.0-dev(7/2時点のmasterブランチでビルドした超最新のRuby)で比較してます。

isucon@isucon-01:~$ ~/local/ruby/versions/3.1.2/bin/ruby --version
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]

isucon@isucon-01:~$ ~/local/ruby/versions/3.2.0-dev/bin/ruby --yjit --version
ruby 3.2.0dev (2022-07-02T10:41:02Z master 7b78aba53a) +YJIT [x86_64-linux]

isucon@isucon-01:~$ ~/.cargo/bin/rustc --version
rustc 1.62.0 (a8314ef7d 2022-06-27)

比較

  • 競技用サーバーをisucon-01, isucon-02のようなホスト名で動かしてDatadogでメトリクスを収集
  • 今回はpumaを動かしてるisucon-01のメトリクスのみ掲載
  • 素の状態だと十分に性能が発揮されないので8時間の素振りでできるだけの改善を行った状態で、最後にRuby 3.2.0-devにしています

CPU

ホスト全体

CPU使用率はあまり変化なし。過去問の種類によっては3.2.0-devでちょっと減ってることがあった(誤差かも?)

Ruby 3.1.2 + YJIT

Ruby 3.2.0-dev + YJIT

pumaのmasterプロセスとworkerプロセスをピックアップ

Datadogのプロセスインテグレーション を使ってpumaのmasterプロセスとworkerプロセスのメトリクスだけ調べたのが下記になります。(具体的にはpsコマンドでとれるCPU使用率をvCPUの数で割った値をグラフに出している)

余談ですがpumaやMySQLやnginxなどISUCONで頻出のミドルウェアはプロセス単位でメトリクス見れるようにしとくとモニタリングが楽ですね。

Ruby 3.1.2 + YJIT

Ruby 3.2.0-dev + YJIT

こっちだとトータルで10%程度CPU使用率が下がってます。(誤差かも?)

Memory

ホスト全体

Ruby 3.2.0-dev + YJITだとホスト全体のメモリ使用量のトップラインがだいたい5%程度削減されています

Ruby 3.1.2 + YJIT

Ruby 3.2.0-dev + YJIT

pumaのmasterプロセスとworkerプロセスをピックアップ

pumaのプロセス単位で見ると劇的に減ってるのが分かると思います。

Ruby 3.1.2 + YJIT

Ruby 3.2.0-dev + YJIT

id:inductor さんが下記ブログで書いてるようにRuby 3.1のYJITだとメモリを喰う問題がありますが、Ruby 3.2.0-devで改善されているのが嬉しいところ。

blog.inductor.me

Ruby 3.2.0-devをデプロイした瞬間のグラフ

Ruby 3.2.0-devをデプロイした瞬間のメモリのグラフを見るとpumaのメモリが一気に減ってるのが分かりやすいです。

1番目のグラフで一瞬サーバ全体のメモリ使用量が増えてるのは多分 bundle install でnative extensionがビルドされていたからだと思います。(Rubyのマイナーバージョンが変わるとgemのインストール先も変わるため)

スコア

Ruby 3.2.0-devにするだけでスコアが1割弱上がりました。

Ruby 3.1.2 + YJIT

{"pass":true,"score":38720,"success":37371,"fail":0,"messages":[]}

Ruby 3.2.0-dev + YJIT

{"pass":true,"score":40574,"success":39244,"fail":0,"messages":[]}

まとめ

  • ビルドにRustの処理系が必要になることを除けばRuby 3.2.0-devのYJITは最高

*1:https://isucon.net/archives/56735884.html

*2:本当はnginxとpumaを分けた上でpumaを2台にして計3台構成にしたかったが、nginxとpumaを別サーバーに分けるとbenchがうまく動かなかったのでこの構成になった

*3:https://zenn.dev/rosylilly/articles/202201-config-turn#workers

Macでsudo無しでdockerコマンドを使えなくなってハマった

tl;dr;

  • docker.sock のパスがおかしくなってた。

コンテキスト

Macを利用してるんですがいつの頃かsudo無しでdockerコマンドが使えなくなっていました。

$ docker run --rm -it ubuntu:focal
docker: Cannot connect to the Docker daemon at unix:///Users/sue445/docker.sock. Is the docker daemon running?.
See 'docker run --help'.

sudoをつければdockerコマンドが使えるのでそこまで困らなかったのだけど、sudo無しでdockerを実行しないといけない案件が出てきてしまったので頑張って調査しました。

環境

  • M1 Mac (macOS 12.4)
  • Docker Desktopのdockerを使いたい

調査内容

M1 Macだとsudoつけないとdockerコマンドが叩けないんだけど、別で持ってるIntel Macだとsudo無しでdockerコマンドが使えたので差分を調べました。(macOSのバージョンはどっちも同じ)

dockerコマンドの実体

M1 Mac(sudoをつけないとdockerコマンドを叩けない環境)での実行結果

$ which docker
/opt/homebrew/bin/docker

$ ls -l /opt/homebrew/bin/docker
lrwxr-xr-x  1 sue445  admin  36  1 14 16:17 /opt/homebrew/bin/docker -> ../Cellar/docker/20.10.12/bin/docker

Intel Mac(sudoをつけなくてもdockerコマンドを叩ける環境)での実行結果

$ which docker
/usr/local/bin/docker

$ ls -l /usr/local/bin/docker
lrwxr-xr-x  1 root  admin  54  9  2  2021 /usr/local/bin/docker -> /Applications/Docker.app/Contents/Resources/bin/docker

Docker Desktopを入れてるのにhomebrewのdockerを参照していておかしくなってる???

下記コマンドでhomebrewで入れているDockerをアンインストールしたんだけど、それでもまだsudo無しでdockerコマンドが実行できない

$ brew uninstall docker

$ ls -l /usr/local/bin/docker
lrwxr-xr-x  1 root  wheel  54  9  2  2021 /usr/local/bin/docker -> /Applications/Docker.app/Contents/Resources/bin/docker

~/docker.sockのパーミッションを調べる

冒頭のエラーメッセージに

Cannot connect to the Docker daemon at unix:///Users/sue445/docker.sock

があったのでパーミッションがどうなってるか調べた

M1 Macでの結果(sudoをつけないとdockerコマンドを叩けない環境)

$ ls -l ~/docker.sock
srw-------  1 sue445  staff  0  1 14 17:09 /Users/sue445/docker.sock

Intel Macでの結果(sudoをつけなくてもdockerコマンドを叩ける環境)

$ ls -l ~/docker.sock
ls: /Users/sue445/docker.sock: No such file or directory

マジ!?

けどこの設定を見る感じDocker Desktopは ~/.docker/run/docker.sock の方の設定を使ってそうなんだよなあ

$ cat ~/.docker/contexts/meta/fe9c6bd7a66301f49ca9b6a70b217107cd1284598bfc254700c989b916da791e/meta.json
{"Name":"desktop-linux","Metadata":{},"Endpoints":{"docker":{"Host":"unix:///Users/sue445/.docker/run/docker.sock","SkipTLSVerify":false}}}

$ ls -l /Users/sue445/.docker/run/docker.sock
srwxr-xr-x  1 sue445  staff  0  6 14 15:36 /Users/sue445/.docker/run/docker.sock

/Users/sue445/docker.sock の設定がどこにあるか見つからなかったので試しにシンボリックリンクを貼ってみた

ln -s ~/.docker/run/docker.sock ~/docker.sock

再実行

$ docker run --rm -it ubuntu:focal
Unable to find image 'ubuntu:focal' locally
focal: Pulling from library/ubuntu
11e23ac719b3: Pull complete
Digest: sha256:fd92c36d3cb9b1d027c4d2a72c6bf0125da82425fc2ca37c414d4f010180dc19
Status: Downloaded newer image for ubuntu:focal
root@f1188ddf7c6e:/#

キタ━━━━(゚∀゚)━━━━!!

おかしくなってた原因と思われるもの

一時期Limaの検証を行っていてその時にhomebrewでdockerを入れた記憶があるので、それが原因かもしれないです。(全然自信ない)

AWS Certified Solutions Architect - Professional(AWS SAP-C01)に合格した

AWS Certified Solutions Architect - Professional(AWS SAP-C01) について

aws.amazon.com

AWS Certified Solutions Architect – Associateに合格した時のエントリは下記。

sue445.hatenablog.com

Associateが中級だとするとProfessionalはそれよりも難しい上級の資格になります。

勉強方法

試験勉強の期間は2ヶ月くらいです。

参考書

この2冊を買って勉強しました。

Kindleで買えるのが多分この2冊くらいしかなかったと思います。参考書に載ってた問題は2回ずつ解きました。

後者の本はKindleのハイライトに対応してたので、間違えた問題の解説の要点をハイライトしておいて試験の直前に軽く復習するのに便利でした。

動画講座

Associateの時にUdemyの動画講座にお世話になったのでProfessionalでも受講しようと思ったんだけど英語の講座しかなくて断念。

英語でも日本語字幕見ればいいのかもしれないけど、目に負荷が集中して眠くなるのであんまり好きじゃないんですよね...

公式のサンプル問題

参考書だけじゃなく公式のサンプル問題や模擬試験も解きました。

ソリューションアーキテクト - プロフェッショナル (SAP-C01) サンプル試験問題

explore.skillbuilder.aws

Skill Builderの方は無料で受講できるのですが今年の6月末までしか受けられないのでギリギリセーフでした。

感想

試験は1000点満点で750点が合格ライン(正答率75%)なのですが、参考書や模擬試験だと良くて65%しか取れなかったので記念受験のつもりで受けたので本当に受かるとは思わなかったです。

実際の試験も75問全部解き終わった時点で残り10分きってたので全然問題を見直す余裕がなかったです。

試験解き終わってアンケートに回答したらすぐに試験の合否が出るのですが *1、そういうわけだったので「合格」の文字を見て思わず二度見か三度見くらいしました。

ちなみに合格時のスコアは790点だったのでかなりギリギリでした。(あと2~3問間違ってたら不合格だった...)

AWS Certified Solutions Architect - ProfessionalのGCP版にあたる Professional Cloud Architect は既に持ってるので、これでAWSGCPでプロフェッショナルアーキテクト二刀流になりました。

www.credly.com

www.credential.net

おまけ

 ↓ 15分後

*1:正式な認定証は数日後

なるべくお金をかけずに個人アプリを運用したい

前々からこの手のことを書きたいとは思ってたけど id:k0kubun さんの下記エントリに触発されて書きました。

k0kubun.hatenablog.com

tl;dr;

  • HerokuやFirebaseを駆使すれば割と無料でいける
  • 若干お金を払えばもっと選択肢は増える

個人アプリ開発

  • 2001~2002年あたりから個人HPでアプリを公開。後にVectorにも公開
    • アカウントは残ってるのでいまだにVectorからのレポートメールが毎月届いてます
  • 2009年くらいから色々ウェブアプリを開発

前提

Heroku

jp.heroku.com

メリット

  • レコード数が少なければPostgreSQLが無料で使える
    • 執筆時点で1万レコードまで無料 *1
  • アドオンが充実しててRedisやMemcachedも小規模なら無料で使える
    • 無料で使えるがクレジットカードの登録は必要
  • git pushだけでデプロイできるお手軽さ
  • Herokuのコンソールから機微情報を環境変数としてセットできる
    • 個人アプリをOSSとして公開する時に地味に助かるやつ
  • Deploy to Herokuボタン があるのでgemみたいに個人アプリを他の人に気軽に配布できる
    • 今だとDockerイメージで固めてDocker Hubとかで配布ってのもできるけど実行環境含めて配布できるのは強い

デメリット

  • コールドスタートがあるのでRailsみたいに起動に時間のかかるアプリは不向き
  • 東京リージョンはEnterpriseでしか使えないので日本国内からアクセスするようなウェブアプリの場合レイテンシの関係で不利。(Enterpriseじゃない普通のHerokuだとusかeuのみ)

特にPostgreSQL, Redis, Memcachedが無料で使えるので、業務でサーバサイドアプリを作っていてその延長で個人アプリも作ってみたいという場合にはとっつきやすいんじゃないでしょうか。

色々思うところはあるんだけどHeroku便利なんすよね、、、

GCP

Google App Engine

cloud.google.com

  • Herokuと同じくらいにできたPaaS老舗
  • 国内外問わず他のPaaSも色々できたんだけどことごとくサービス終了したのでHerokuとAppEngineしか勝たんって思ってる

メリット

  • オートスケールがあるのでアクセス数に応じてインスタンスが自動で増減する
    • ただしインスタンスが増えるとその分費用も発生する
    • 追記:一応HerokuにもDynoのオートスケーリングはあるんだけど、Performanceプラン以上(1 Dyno辺り最低月250ドル)じゃないと使えないので個人アプリだと厳しいのではと思います。(FreeプランかStandardプランだとコンソールから手動でのDyno数変更のみ)
  • 静的ファイルはサーバサイドアプリとは別のフロントエンドサーバから配信する設定にできる

デメリット

  • Heroku同様コールドスリープがある
  • GCPだと無料のRDBが使えないので別のSaaSを併用する必要がある
    • Cloud SQLは個人アプリだと高くて使いづらい(最低スペックでも月12ドルかかる)し、AppEngine使ってるのにDB用にGCEインスタンスを作るのもかなり微妙
    • 完全無料で済ませるならDatastoreやFirestoreのようなGCPのKVSを使う必要があるが、RDBと全然違うのでそれなりに学習コストはかかる

AWSでやろうとするとApp Runnerなんだけど完全無料でやるのは難しいんじゃないかなあ、、、

Cloud Run

  • DockerイメージをCIでビルドする手間を惜しまなければ全然あり
  • Cloud Runの無料枠も潤沢にあるので個人アプリ開発で使うには十分なんだけど、ビルドしたDockerイメージを置くContainer Registryの費用が発生するので若干の費用は発生すると思います

Firebase

  • https://primap.web.app/ をFirebase Hostingで動かしてるんだけど爆速でいい
    • 以前Fastlyが世界的な障害になった時にプリマップも落ちていたのでFirebase HostingのバックエンドはFastlyだと思います。どおりで速いわけだ
  • その他Cloud FunctionsやFirestore辺りも使ってます

プリマップのアーキテクチャについては下記エントリに詳しく書いてます。

sue445.hatenablog.com

sue445.hatenablog.com

Cloud Functions

  • 画面が不要だとFaaSでもいいですね
  • 個人Slackで運用してる雑ボット類は数年前まではVPSで動かしてたんですが、サーバの管理するのが面倒になって今は全部Cloud Functionsで動かしてます
  • 無料枠が潤沢なので個人アプリで使うには十分
  • AWSだとLambdaに相当し、Lambdaも無料枠が潤沢にある
  • Secret Managerにある機微情報をFunctionに設定することができるんだけど、Functionの呼び出し毎にSecret Managerの読み取り費用が発生するためそこだけ注意
    • 無料枠を超えたら1万回アクセス毎に月0.03ドル *2
  • 実はCloud FunctionsのデプロイでもバックエンドでContainer Registryが使われている関係でGCSの費用が発生します
    • 規模にもよるけど自分が運用してるアプリだと月0.01~0.05ドルくらい

Cloud Functionsで思い出したけど先日Ruby 3.0サポートがGAになってますね

cloud.google.com

GitHub Pages

  • 静的ファイルしか使わないんであればGitHub Pages最強
  • GitHubにコミットされたファイルしかGitHub Pagesで公開できないので、mainブランチが更新された時にGitHub Actionsでビルドしてgh-pagesブランチにcommitしてpushするひと手間がある

2022/8/14追記

GitLab Pages同様にブランチにコミットしなくてもGitHub Pagesにデプロイできるようになった!!!!(超便利)

github.blog

GitLab Pages

  • GitHub PagesのGitLab版なんだけど、こっちはGitLab CIのartifactをGitLab Pagesで公開するためGitHub Pagesのようなcommit & pushが不要なので嬉しい

2022/5/7 17:00追記:ブコメレス

id:anonruru

とても参考になる。1つだけ、tldrがtrdrになってたのが気になった。

指摘ありがとうございます。typo修正しました

シレン5の原始に続く穴を99F踏破した

原始に続く穴って?

以下「原始」と呼称

立ち回り

詳しい数字は覚えてないけど原始だけで1年前後、100回以上は余裕でプレイしてると思う。(シレン5全体だとプレイ回数950回、プレイ時間700時間くらい)

ちなみにシレン5だと救助システムがあって倒れても他のプレイヤーに助けてもらえるけど、僕は救助システムは使わずにノーミスクリアを目指してました。

wikiの下記ページはむっちゃ見てた。

seesaawiki.jp

seesaawiki.jp

特に50F以降はずっとモンスターテーブル見ながらやってたと思う。

序盤

  • 10Fのマゼルンゾーンだと隕石装備か朱剛石装備だったと思う
  • 28Fでギリギリ身かわし香の壺が出たのでしあわせの札でクロスカートを吹き飛びカートにレベルアップさせて吹き飛ばしの矢を1000本くらい稼いだと思う
    • とはいえ身かわし状態だと札も当たらないので実際に稼いだのは29F。同じフロアのガラ中流魔道士が怖かったけど魔法ダメージの印があったのでゴリ押せた

中盤

  • 金喰い剣+盾。この辺で道具感血の腕輪(まがい物の方)をゲット
  • 白紙の巻物が店売りしてたので所持品を全部売った後にタダの巻物でギタンを荒稼ぎした時の様子が下記

  • 50Fくらいから即降りモードに移行
  • その後ギタンが尽きて死を覚悟したけど道具感血のおかげで埋蔵金部屋を何回か引き当てることができてよかった
  • 通路で矢を打ちまくって安全確保しながら歩いた

終盤

  • この辺で昼の盾を拾ったのでメイン盾に変更
  • ドレッドラビや大物荒らしに遭遇しなかったのは完全に運がよかった...
  • 催眠無効の印がなくてゲンナマゲイズが怖かった以外は安定
  • 火力的には終盤でも普通に殴り合えたんだけど回復アイテムがなかったので吹き飛ばしの矢を打ちまくって撃破することが多かった
  • 94Fで大部屋モンスターハウスが出た時は死を覚悟したけど冷えびえ香の壺でイッテツ戦車を無効化できたのは大きかった
    • とはいえ96F以降のアビスドラゴンゾーンは冷えびえ香の壺や回復アイテムがなかったので生きた心地がしなかった。(炎半減の印があってもきつい)

PlantUMLで描いた図をGitHubのリポジトリでいい感じに管理したい

tl;dr;

  1. pumlファイル*1を作成
  2. pumlファイルからsvgファイルを作成
  3. リポジトリにはsvgファイルを埋め込む

モチベーション

GitHubでMermaidがサポートされましたが *2、Mermaidで描けないタイプの図があってたまにPlantUMLを使いたくなるので備忘。

ちなみにGitLabやesaやQiita辺りはPlantUMLをサポートしてるのでこの手のハックはしなくていいです。

実際の例

実際の例を見てもらった方がいいと思うので自分のリポジトリを見せます。

他にもうまいやり方は色々やり方はありそうだけど思いついてないです。

pumlファイルを作成

https://github.com/sue445/primap/blob/9cf14512dcc7efc5ee21c627b933bcd81687898b/function/_img/overview.puml

Goのリポジトリなのでビルドターゲットから外すために_img/ のようなディレクトリにしましたが、ディレクトリ名は何でもいいと思います。

pumlファイルからsvgファイルを作成

手元でPlantUMLのjarファイルを管理したくないので僕はよく https://hub.docker.com/r/think/plantuml を使ってます。

Makefile に下記のようなタスクを置いておけば make puml2svgsvgが作れる。

.PHONY: puml2svg
puml2svg:
  cat _img/overview.puml | docker run --rm -i think/plantuml -tsvg > _img/overview.svg

https://github.com/sue445/primap/blob/9cf14512dcc7efc5ee21c627b933bcd81687898b/function/Makefile#L54-L56

Makefile にしないまでもpumlからsvgを作るコマンドくらいはREADMEに書いてた方が他の人もメンテできるようになって便利。

リポジトリにはsvgファイルを埋め込む

README.md で下記のように書けば表示できます。

![overview](_img/overview.svg)

https://github.com/sue445/primap/blob/9cf14512dcc7efc5ee21c627b933bcd81687898b/function/README.md#overview

メリット

余談

なんとなく自分のリポジトリを見ていて「この図はMermaid移行した方がよさそうだなー」と思ったんですが、これを消した後に別のリポジトリでPlantUMLを管理したくなった時に自分が困るので後から調べられるようにしたいというのがこのエントリの本当の目的です。

2022/04/13追記

PlantUMLからMermaidに移行した

github.com