ハイサイ!オースティンやいびーん。んな ガンじゅー?
TLDR
-
- BbPressというWordPressのBBSプラグインに旧BBSを移植しないといけない
-
- BbPressのツールに入っているインポーターを使うと、移植に8時間以上かかる試算だった
- Rustで同様なツールを半日で作ったらなんと1分台まで縮められた
問題
20年以上運営されている、独自開発のBBSを、WordPressのBbPressプラグインによるBBSに移植しないといけない。
20年以上も使っているので、あれこれガタが来ていて、保守コストが割に合わなくなっていました。今後は極力低メンテナンスで運営できるように、サイト自体をWordPressに移植してBBSをBbPressで再現するという計画でした。
最初に試したこと
BbPressには別のBBSシステムから移植するのを手伝うアダプターが何種類か用意されています。残念ながら、今回の移植対象となる古いBBSは常識外れた独自実装です。悪く言っても、BBSの常識というものがほとんどない時期に立ち上げられたからなんとも非難できません。
そこで、BbPressに移植するために試したのは、独自のBbPressアダプターを実装することでした。
その結果
その結果、なんとかきちんと移植はしてくれるのですが、その速度が恐ろしく遅く、BBSの返事を20件/秒ほどのスピードでゆっくりとしか動かない上に、内部のキャッシュで大量のメモリーを使ってしまうため、数時間以上連続して動かしていると、大体クラッシュするのです。
何万件もある対象の旧BBSだと非常に現実的ではないのです。ましてや、移植している間はサービスを停止しないといけないので、多大な損失を生む、認められざる事態になります。
そこで思いついたこと
最近、筆者はRustに没頭しており、遊びと勉強目的でWP_QueryをRustで実装したばかりでした。
そこで、そのwp_query_rsにWPのWP_MetaとWP_Postの機能を追加しておけば、古いデータベースを読んで、そのまま新しいWordPressにBBSを移植できるのではないかと思ったのです。
BbPressの移植のシステムおよびソースコードをほぼ全文デバッグで読んでいた筆者だったので、なんとか実装できたのです。
Rustで実装してみたら
なんと5分まで移植の処理時間を削ることができたのです。
このような工夫をしたら更に早くなった
色々とRustの機能を使って更にチューニングしたらより早くなりました。
BBSスレッドの移植後WP_Post.IDと、旧IDをキャッシュ化
移植が終わったスレッドに対して、そのスレッドが保有する返事も移植していくのですが、返事の外部キーのスレッドの旧IDを毎回データベースに問い合わせているとそれだけ打撃を喰らいます。
RwLock<HashMap<u64, u64>>という具合に、複数のスレッドから読めるようにしたHashMapに新ID対旧IDのセットを入れるようにしました。
返事のWP_Metaを別のスレッドで並行して入れるように
最初はWP_Postの作成とそれに付随するBbPress用のWP_Metaを同じスレッドで作業していました。これもWP_Metaを一個ずつINSERT INTOの書き込みをしているのです。
どうせ同じデータベースに書き込みをさせているわけだから、大して早くもならないだろうとは思ったものの、やってみたら1分半短縮できました。
MySQLをまだ最大に働かせていなかったということでしょうが、酷使でしょうね。
極論を言えば、wp_postmetaにINSERTしているのを一回にすれば、もっと早くなるでしょうね。
返事の新ID・旧IDをキャッシュ化
旧BBSには、スレッドへの返事に対して一階層まで更に返事を重ねることができるように設計されていました。
移植された返事とその子返事の関係性をいちいちデータベースにという合わせていると遅いので、スレッドと同様にキャッシュ化したら、また1分ほど早くなりました。
まとめ
結局、無事にマイグレーションのツールをRustで実装することができました。おかげでメンテナンスの時間を10分枠で取ることができそうでめでたいめでたい。売り上げに変換したら、僕の半日ほどの価値はあるのでしょう。
筆者としてはこんなに早くRustを実用で活かせるなんて夢にも見ていなかったのでワクワクが止まりません。