Featured image of post 【目次】PerlとMooで弾幕シューティングを作ってみよう(全6回)

【目次】PerlとMooで弾幕シューティングを作ってみよう(全6回)

Flyweightパターンを学ぶ全6回のシリーズ目次。弾幕シューティングを題材に、大量オブジェクトのメモリ効率化テクニックを習得します。

弾幕シューティングの弾を素朴に1000発作ると、メモリはどれだけ使われるのか。同じ見た目の弾を1つのオブジェクトで共有すると、どこまで減るのか。Perl と Moo で実際に測りながら、Flyweight パターンにたどり着く全6回の連載です。

各話では、コードを書く前にまず Devel::Size で計測します。パターン名は最終回まで出てきません。作っていくうちに、気づけば Flyweight になっている流れです。

このページは目次を兼ねた案内板です。まず読むなら「まず読むなら」の2本から、パターンの用語から押さえたいなら「各回の要点」から選んでください。

まず読むなら

  • 第1回: 弾を1000発撃ちたい!メモリの限界 — 素朴に作った Bullet が1発約600バイト、1万発で約6MB になる計測回。この連載の問いがすべてここにある。大量のオブジェクトを作るコードを抱えているなら、この1本だけでも測り方が持ち帰れる
  • 第3回: BulletFactoryで弾を使い回そう — 同じ種類は作り直さず、あれば同じオブジェクトを返すキャッシュの回。//= 1行で書けるので、Flyweight に限らず使い回しの書き方として読める

読む前に

  • 対象は Perl 入門者で、Moo の has と new が読めれば足ります。前提シリーズは「Mooで覚えるオブジェクト指向プログラミング」です
  • コードは Perl v5.36 以降を前提にしています。メモリの計測には Devel::Size を使います
  • 計測値は筆者の環境での一例です。環境によって変わるので、傾向として読んでください

各回の要点

第1回: 弾を1000発撃ちたい!メモリの限界

形状・色・サイズが全弾で同じなのに、弾ごとに持っている。1発あたり約600バイト、10000発で約5.8MB と測り、共有できる属性と弾ごとに違う属性を分けます。


第2回: 弾の種類と位置を分けて考えよう

形状・色・サイズを BulletType に切り出し、位置と速度だけを弾ごとのハッシュに残す。弾100発分は60.8KB から25.2KB になります。内部状態と外部状態という用語もここで出てきます。


第3回: BulletFactoryで弾を使い回そう

同じ種類の弾を何度頼んでも、同じ BulletType を返す BulletFactory を作ります。1000発の弾が参照する BulletType は5つで、弾の配列は約245.8KB です。


第4回: 外部状態を渡して弾幕を描こう

BulletType は位置を持たず、render が描画のたびに座標を受け取る。だから同じオブジェクトを複数の弾が共有できます。放射状と螺旋状に弾を動かします。


第5回: 完成!弾幕シューティングエンジン

BattleField クラスに、弾の生成・移動・描画をまとめます。放射状と螺旋の弾幕パターンで、68発を3種類の BulletType で動かします。


第6回: これがFlyweightパターンだ!

作ってきたものが Flyweight パターンだったと明かし、各クラスを役割に対応づけます。複製する Prototype との違いも表で比べます。


学習のポイント

このシリーズで扱う技術要素:

技術要素内容
内部状態と外部状態共有できる状態と、弾ごとに違う状態を分ける
FlyweightFactoryキャッシュで同じ種類のオブジェクトを使い回す
//= 演算子「なければ作る」を1行で書く
Flyweight パターンGoF の構造パターンの一つ

読み終えると

  • 弾の配列が参照する BulletType は種類の数だけ、という作りが書ける
  • 共有するオブジェクトと、渡し直す外部状態の線引きができる
  • Devel::Size で、自分のコードのオブジェクトの大きさを測れる

関連シリーズ

共有ではなく複製でオブジェクトを増やす Prototype パターンのシリーズも、最終回で比べています:

comments powered by Disqus
システム開発・AIワークフローのご相談は Meetsource へ
Hugo で構築されています。
テーマ Stack は Jimmy によって設計されています。