SlideShare a Scribd company logo
1 of 39
shared_ptrとゲームプログラミングでのメモリ管理
@DADA246
自己紹介
• ゲームプログラマやってます
• 家庭用からモバイル、業務用まで幅広く書いてきました
アジェンダ
• はじめに
• メモリリーク
• メモリ断片化
• 処理速度
• まとめ
今回の話の対象
• ハード:OSとゲームが動作するコンピュータ
• ソフト:C++によるネイティブクライアント
• ゲーム:アクションゲームなど、リアルタイム性が問われる
ジャンル
• 開発規模:中規模~大規模
ゲームプログラムの特徴
• フレームレートが安定している(60fps,30fps…)
→スワップアウトが発生しない
→実行時メモリサイズが物理メモリサイズに収まっている
メモリ管理の種類
• メモリ固定管理
→ゲーム起動時に確保されたメモリのみ使用して、ゲーム中は
OSからメモリ確保を行わない方式
• メモリ動的管理
→ゲーム動作中にメモリが必要になった時点でOSからメモリを
確保して、メモリが不必要になったらOSにメモリを返却する方式
→今回の話はコチラ
なぜメモリの動的管理?
• 近年の中規模~大規模ゲーム開発ではレベルデータ、グラ
フィックスリソース、サウンドなど、ゲームが扱うデータが増え
ている
→ゲームをデータドリブンで動作させる必要がある
→メモリを動的管理にすると、メモリによる制限が減るので、
多彩なデータを動作させることができる
試行錯誤
• ゲームが多彩なデータを扱えると、ゲームデザイナやアー
ティストが思いついたアイデアを試行錯誤できる
→メモリの動的管理を行うことで、「一時的にメモリを使用する
が、ゲームが面白くなりそうなデータ」を試すことが出来る
ゲームシーケンス
• メモリの動的管理を行うことで、シーケンスごとにメモリ構成
が大幅に異なるゲームを作ることが出来る
• 例:FPS
レベルプレイでは大量のゲームオブジェクト、AI、ネットワークに
メモリを割り当てるが、カットシーンではそれらの代わりにグラ
フィックスリソースにメモリを割り当てる
メモリ動的管理の問題
• メモリの動的管理にはメリットが多いが、問題点もある
メモリリーク
メモリ断片化
処理速度
→これらの問題点を解決する
メモリリーク
• std::freeやdeleteを書き忘れると発生する
• メモリ解放を他のプログラマに委ねるインターフェースでも
メモリリークは発生しやすい
void Sample()
{
void* pBuffer = std::malloc(1024);
Player* pPlayer = new Player();
}//メモリリーク発生
void Register() { m_pPlayer = new Player(); }
//呼び忘れるとメモリリークする
void UnRegister() { delete m_pPlayer; }
RAII
• Resource Acquisition Is Initialization
• オブジェクトの生存時間とリソースを結びつける
• 基本的にこの設計を守ればメモリリークは起きない
• 実装の一例として、shared_ptrを利用する
shared_ptr
• newとdeleteは使わずにshared_ptrを使う
• 各種モジュールごとにshared_ptrで分離させておくと、生ポイ
ンタを扱わずに済む
class Player
{
private:
std::shared_ptr<Collision> m_collision;
std::shared_ptr<Sound> m_sound;
}
クラスの所有
• クラスを直接所有してInitialize()するのではなく、shared_ptr
にしてコンストラクタで初期化する
→C++の言語設計に従うことで、RAIIを実装しやすくなる
コンストラクタとデストラクタを活用する
Player::Player()
{
m_life.Initialize();
}
Player::Player()
{
m_life = std::make_shared<Life>();
}
メモリリークは発生する?
• バイナリデータ読み込みなど、shared_ptrを使わずに
std::mallocを使う場合もある
→RAIIを守るのが基本だが、std::freeを書き忘れることがある
→メモリリークが発生する
→この場合はメモリリーク検出ツールで対応する
カスタムアロケータ
• あらかじめメモリの確保、開放時にデバッグ情報を保存できる
カスタムアロケータを作り、OSのアロケータを切り替えておく
→デバッグ情報をログ出力することでメモリの状態を把握できる
ゲーム
デバッグ情報の保存
アロケータ
void* _cdecl operator new (size_t size)
{
//カスタムアロケータ呼び出し
}
メモリリーク検出ツール
• ゲームプログラムにおいて、メモリリークが問題になった時のメ
モリ状態を考える
• メモリリークしているアドレスは開放されない
→メモリの生存時間が長いアドレスはメモリリークの可能性が高い
→アドレスに日付をつけるとメモリの生存時間を計算できる
struct Node
{
int64_t address;
int64_t size;
int64_t date;
}
生存時間の長いアドレス
• 常駐データなど、メモリ確保後に解放しないデータもある
• メモリ確保時にコールスタックを保存して、ログ出力に含める
→コールスタックが1回のみ記録されているものは常駐データ
→同一コールスタックが複数回記録されているものはメモリリー
クの可能性が高い
• コールスタックはRtlCaptureStackBackTraceなどで取得できる
メモリリーク検出ツール
• 同一のコールスタックから、生存時間の長いメモリを複数回確保
している箇所はメモリリークしていると判断できる
→エージングなどの自動テストに組み込むことで、メモリリークを自
動的に検出できる
struct Node
{
int64_t address;
int64_t size;
int64_t date;
int64_t backTraceHash;
}
//keyはbackTraceHash
std::map<int64_t,std::vector<Node>> nodes
for(auto it = nodes.cbegin(); it != nodes.cend(); ++it)
{
if( 1 < it->second.size() )
{
auto memoryLeak = it->second;//メモリリーク発見!
}
}
アジェンダ
• はじめに
• メモリリーク
• メモリ断片化
• 処理速度
• まとめ
メモリ断片化
• メモリ断片化とは何か
→メモリの確保と解放を繰り返すことで、連続したメモリが確保
出来なくなる
→メモリの確保に失敗することになる
連続したメモリ領域
• ゲームから見て連続したメモリ領域はMMUの有無で変わる
MMUが有る場合は仮想アドレス空間
MMUが無い場合は物理アドレス空間
• ハードウェア構成によって断片化のしやすさが変わる
→メモリ戦略が変わってくる
MMU非搭載の場合
• 物理アドレス空間の断片化に気をつける必要がある
• 低コストの組み込みマシンの場合が多いので、処理性能を
考えると、メモリ固定管理の方が適している場合もある
例:物理メモリ16MByte程度の
組み込みハードウェアなど Physical memory
MMUが搭載されている場合
• MMUを搭載していて、仮想アドレス空間と物理メモリ量に差が
ある場合
→仮想メモリ空間の大きさに頼る
• フレームレートを維持するというゲームの特性上、ソフトウェア
の規模が物理メモリ量に収まるサイズになることを利用する
Virtual memory Physical memory
断片化対策
• 例:64bit Windows8.1
→プロセスあたりの仮想メモリ空間は128TByte
→ページ単位のブロックアロケータを使い、仮想メモリ断片化は
気にしない
• Windowsのlow fragmentation heapが参考になる
• 断片化よりもアロケータの適切なページ管理が重要
断片化対策
• MMUを搭載していて、仮想アドレス空間と実メモリに差が少
ない場合(32bitコンピュータにGByte単位の実メモリを載せて
いる場合など)
→仮想アドレス空間の断片化に気をつける必要がある
• 例: 32bit Windows XPで、メモリ使用量2GByteのゲーム
Virtual memory Physical memory
断片化対策
• 仮想アドレス空間と実メモリに差が少ないマシンでメモリ断片
化を防ぐには?
→生存時間の長いメモリを減らす
→生存時間の長いメモリと、生存時間の短いメモリのアドレスを
離す
Virtual memory Physical memory
生存時間の長いメモリを減らす
• shared_ptrの相互参照を減らして、一つのshared_ptrを削除
すると、所有しているshared_ptrが削除されるようにしておく
→シンプルに大量のモジュールを作り直すことが出来る
メモリの生存時間が短くなるので、ゲームが長時間駆動に耐え
やすくなる
• デバッグ機能など依存関係が
増えやすいものはweak_ptrにする
shared_ptr
shared_ptr shared_ptr
生存時間の長いメモリを減らす
• ゲームシーケンスの切り替え時にモジュールを作りなおすよ
うにする
• シーケンス間のデータ移行のためのモジュールを作ることも
ある
void LevelClear()
{
std::shared_ptr<Status> status = m_level->GetStatus();
m_level = std::make_shared<Level>(status);
}
生存時間の長いメモリを減らす
• シングルトンなど、グローバルインスタンスは極力使わない
→デバッグモジュールなど、グローバルインスタンスになりやす
いものもある
• グローバルインスタンスはゲーム開始直後など、他のメモリ
アロケーションが走る前にメモリを確保して、断片化された領
域を作らないようにする
グローバルインスタンス→
Virtual Memory
空き領域→
断片化対策
• 生存時間の長いメモリと、生存時間の短いメモリのアドレスを
離す
→アロケータを複数用意する
Double Ended Stack allocatorを使うこともある
Virtual Memory
VRAM
• 物理アドレス空間の断片化に気をつける必要がある
(GPUによっては仮想アドレスに対応している場合もある)
• 断片化しやすいが、いざとなったらメモリコンパクションを実
装することもできる
→リソースをハンドルで管理していることが多いため
VRAM
アジェンダ
• はじめに
• メモリリーク
• メモリ断片化
• 処理速度
• まとめ
処理速度
• ある程度メモリ確保を高速化した上で、その処理速度に見
合ったゲームにする
→Win32のHeapAllocなど、Kernel-landで実行されるアロケータ
ではなく、User-landで実行される独自のカスタムアロケータを用
意する
• メモリ動的管理ではメモリ確保が頻繁に実行されるので、メ
モリ固定管理よりも処理が重いと言われることはあるが、こ
れは開発環境の良さとのバランスの問題
メモリ動的管理の問題点と解決方法
• メモリリーク → RAII(shared_ptr)とメモリリーク検出ツールで解決
• メモリ断片化 → 仮想アドレス空間の広さを活用して解決
• 処理速度 → アロケータを高速化しつつ、処理速度に見合った
ゲームにすることで解決
メモリが不足したら?
• メモリが不足しないようにゲームを作るのが基本
→自動テストやエージングを繰り返して、メモリ使用量を把握する
• メモリリークとメモリ断片化を解決してもメモリが不足する場合は、
ゲームに対してデータが大きすぎるので、データを修正する
auto player = std::make_shared<Player>();
player->Update(); //playerは必ず存在する
まとめ
• メモリの動的管理が可能になったことで、ゲーム上で多彩な
データを動作させることが可能になった
→ゲームデザイナやアーティストのクリエイティビティを引き出し
て、もっとゲームを面白くしよう!
Questions?
ご静聴ありがとうございました

More Related Content

What's hot

【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!Unity Technologies Japan K.K.
 
RPGにおけるイベント駆動型の設計と実装
RPGにおけるイベント駆動型の設計と実装RPGにおけるイベント駆動型の設計と実装
RPGにおけるイベント駆動型の設計と実装Koji Morikawa
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14Ryo Suzuki
 
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~UnityTechnologiesJapan002
 
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTERUE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTERエピック・ゲームズ・ジャパン Epic Games Japan
 
なぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリングなぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリングSatoshi Kodaira
 
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?京大 マイコンクラブ
 
UE4 LODs for Optimization -Beginner-
UE4 LODs for Optimization -Beginner-UE4 LODs for Optimization -Beginner-
UE4 LODs for Optimization -Beginner-com044
 

What's hot (20)

UE4とUnrealC++について
UE4とUnrealC++についてUE4とUnrealC++について
UE4とUnrealC++について
 
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
 
GPU最適化入門
GPU最適化入門GPU最適化入門
GPU最適化入門
 
RPGにおけるイベント駆動型の設計と実装
RPGにおけるイベント駆動型の設計と実装RPGにおけるイベント駆動型の設計と実装
RPGにおけるイベント駆動型の設計と実装
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
 
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
 
60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編
 
猫でも分かるUE4を使った VRコンテンツ開発 超入門編 2021
猫でも分かるUE4を使った VRコンテンツ開発 超入門編 2021猫でも分かるUE4を使った VRコンテンツ開発 超入門編 2021
猫でも分かるUE4を使った VRコンテンツ開発 超入門編 2021
 
C++ マルチスレッド 入門
C++ マルチスレッド 入門C++ マルチスレッド 入門
C++ マルチスレッド 入門
 
60fpsアクションを実現する秘訣を伝授 基礎編
60fpsアクションを実現する秘訣を伝授 基礎編60fpsアクションを実現する秘訣を伝授 基礎編
60fpsアクションを実現する秘訣を伝授 基礎編
 
Mask Material only in Early Z-passの効果と仕組み
Mask Material only in Early Z-passの効果と仕組みMask Material only in Early Z-passの効果と仕組み
Mask Material only in Early Z-passの効果と仕組み
 
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
 
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTERUE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
 
なぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリングなぜなにリアルタイムレンダリング
なぜなにリアルタイムレンダリング
 
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
 
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
バイキング流UE4活用術 ~BPとお別れするまでの18ヶ月~
 
UE4で”MetaHumanを使わずに”耳なし芳一になる10の方法 | UE4 Character Art Dive Online
UE4で”MetaHumanを使わずに”耳なし芳一になる10の方法 | UE4 Character Art Dive OnlineUE4で”MetaHumanを使わずに”耳なし芳一になる10の方法 | UE4 Character Art Dive Online
UE4で”MetaHumanを使わずに”耳なし芳一になる10の方法 | UE4 Character Art Dive Online
 
UE4 LODs for Optimization -Beginner-
UE4 LODs for Optimization -Beginner-UE4 LODs for Optimization -Beginner-
UE4 LODs for Optimization -Beginner-
 
UE4のスレッドの流れと Input Latency改善の仕組み
UE4のスレッドの流れとInput Latency改善の仕組みUE4のスレッドの流れとInput Latency改善の仕組み
UE4のスレッドの流れと Input Latency改善の仕組み
 
Riderはいいぞ!
Riderはいいぞ!Riderはいいぞ!
Riderはいいぞ!
 

Similar to shared_ptrとゲームプログラミングでのメモリ管理

パソコン選び(抜粋)
パソコン選び(抜粋)パソコン選び(抜粋)
パソコン選び(抜粋)Eiji Matsumoto
 
第8回テックヒルズIBM資料
第8回テックヒルズIBM資料第8回テックヒルズIBM資料
第8回テックヒルズIBM資料Tomoari Yasuda
 
ゲームの仕様書を書こう2 仕様書に記載する機能内容
ゲームの仕様書を書こう2 仕様書に記載する機能内容ゲームの仕様書を書こう2 仕様書に記載する機能内容
ゲームの仕様書を書こう2 仕様書に記載する機能内容Sugimoto Chizuru
 
ゲームインフラコンテナ実践導入
ゲームインフラコンテナ実践導入ゲームインフラコンテナ実践導入
ゲームインフラコンテナ実践導入Hiroki Tamiya
 
実体験に基づく、少人数制作によるシューティングゲームの提案
実体験に基づく、少人数制作によるシューティングゲームの提案実体験に基づく、少人数制作によるシューティングゲームの提案
実体験に基づく、少人数制作によるシューティングゲームの提案IGDA Japan
 
Amazon Game Tech アマゾンゲームテクノロジー - Amazon Game Tech - GTMF 2018 OSAKA
Amazon Game Tech アマゾンゲームテクノロジー - Amazon Game Tech - GTMF 2018 OSAKAAmazon Game Tech アマゾンゲームテクノロジー - Amazon Game Tech - GTMF 2018 OSAKA
Amazon Game Tech アマゾンゲームテクノロジー - Amazon Game Tech - GTMF 2018 OSAKAGame Tools & Middleware Forum
 

Similar to shared_ptrとゲームプログラミングでのメモリ管理 (7)

パソコン選び(抜粋)
パソコン選び(抜粋)パソコン選び(抜粋)
パソコン選び(抜粋)
 
Reinvent2017 recap-gaming-session-2
Reinvent2017 recap-gaming-session-2Reinvent2017 recap-gaming-session-2
Reinvent2017 recap-gaming-session-2
 
第8回テックヒルズIBM資料
第8回テックヒルズIBM資料第8回テックヒルズIBM資料
第8回テックヒルズIBM資料
 
ゲームの仕様書を書こう2 仕様書に記載する機能内容
ゲームの仕様書を書こう2 仕様書に記載する機能内容ゲームの仕様書を書こう2 仕様書に記載する機能内容
ゲームの仕様書を書こう2 仕様書に記載する機能内容
 
ゲームインフラコンテナ実践導入
ゲームインフラコンテナ実践導入ゲームインフラコンテナ実践導入
ゲームインフラコンテナ実践導入
 
実体験に基づく、少人数制作によるシューティングゲームの提案
実体験に基づく、少人数制作によるシューティングゲームの提案実体験に基づく、少人数制作によるシューティングゲームの提案
実体験に基づく、少人数制作によるシューティングゲームの提案
 
Amazon Game Tech アマゾンゲームテクノロジー - Amazon Game Tech - GTMF 2018 OSAKA
Amazon Game Tech アマゾンゲームテクノロジー - Amazon Game Tech - GTMF 2018 OSAKAAmazon Game Tech アマゾンゲームテクノロジー - Amazon Game Tech - GTMF 2018 OSAKA
Amazon Game Tech アマゾンゲームテクノロジー - Amazon Game Tech - GTMF 2018 OSAKA
 

shared_ptrとゲームプログラミングでのメモリ管理