🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

4323閲覧

【C#】 パフォーマンスプロファイラにて、どの変数に対してGCが行われたかがわからない

JumpActionGames

総合スコア29

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2019/12/10 06:11

編集2019/12/10 06:29

【C#】 パフォーマンスプロファイラにて、どの変数に対してGCが行われたかがわからない

C#で作成中のゲームのメモリ使用量がどこかでdisposeなどを忘れていたせいで、すごく上がっており、GCで下がってまた上がってを繰り返していました。 どの変数が不要(GC対象)がわかれば、問題を解決できます。
そこで、VisualStudioのパフォーマンスプロファイラで見てみたところ、char[]などがててきて、GCがいつ行われたかしかわからなく、GCがどの変数(インスタンス)に対して行われたのかがしりたいです。
できるだけdisposeとかで対処したいから、GCが行われたインスタンスをdisposeしたらOKということです。
これくらいしか書くことないですw(エラーコードとかはないから)
##使用ツールなど
IDE:VisualStudio 2019
OS:Windows10
言語:C#
フレームワーク: .Net
フレームワークのバージョン:多分最新

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2019/12/10 07:04 編集

> メモリ使用量がすごく上がっている それが何か問題を招いているということでしょうか? 「下がってまた上がって」だと、長い目で見たときにメモリ使用量は増え続けていないのでしょうか。 GCの行われている変数を知ることは、何か真の問題を達成するための手段のように思いますので、その真の問題を質問に記載すべきと思います。
JumpActionGames

2019/12/10 06:29

修正しました。 C#で作成中のゲームのメモリ使用量がどこかでdisposeなどを忘れていたせいで、すごく上がっており、GCで下がってまた上がってを繰り返していました。 どの変数が不要(GC対象)がわかれば、問題を解決できます。
YAmaGNZ

2019/12/10 06:55

Disposeをしていないのであれば参照が残っているということでしょうからGC対象にはならないのではないですか?
guest

回答2

0

こんにちは。
コメントを見ていたら解決済みになったため、補足的な回答を残します。

.NET において、メモリが「大きく上がって、大きく下がって」を繰り返すのは「正常な動作」です。言い換えると、「そうなることを回避する手段は存在しない」です。

.NET のメモリの管理はほぼ全て GC に任せられています。任せられているということは、自分たちでそれをどうすることもできません。それは IDisposable をどうしているかとも関係ありません。

IDisposable について勘違いしているようなのですが、IDisposable の役割は「メモリの解放」ではなく、「リソースの解放」です。
「リソース」とは、メモリの上に構成される、オープンとクローズの2つの性質を備えたオブジェクトという、「メモリ」よりも上位の抽象的概念です。
Dispose により「リソースの解放」を行うことは、.NET のメモリの消費量には影響しません。メモリの破棄を行うのは GC であり、Dispose を行ったかどうかとは無関係なのです。

GC はゴミとなったメモリでもしばらく蓄え続け、あるタイミングで一気に解放します。そのため、大きく上がって下がってを繰り返すグラフになります。
これは、GC を実行すること自体がそこそこコストがかかる動作なので、ある程度溜め込んで一気にやった方が (速度的に) 効率的だからです。メモリの消費を最小限に抑えることを諦め、速度を優先したということです。

もし、なんとしてもメモリ使用量グラフを平坦に保ちたいのであれば、何かオブジェクトを使い終わる度にすぐさま「手動で GC を実行する」ことでおそらく実現できるでしょう。
ただし、実行速度はお話にならないほど低下すると思います。

投稿2019/12/10 08:14

編集2019/12/10 08:20
tamoto

総合スコア4243

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

C#で作成中のゲームのメモリ使用量がどこかでdisposeなどを忘れていたせいで、すごく上がっており

もし上記文章が「メモリリークが発生した真の原因」である場合の回答です。

リソースの解放(Dispose)が必要なオブジェクトにはIDisposableインターフェースが実装されているので、まずはプロジェクト内に該当のオブジェクトが使用されているかを確認してください。

IDisposableなオブジェクトを見つける方法の1つは以下の通りです。
0. IDisposableなオブジェクトを1つ見つける
0. IDisposableと書かれたテキスト部分をダブルクリックで選択し、右クリックでメニューを表示
0. 「すべての参照を検索」を選択

これで、プロジェクト内で定義されているIDisposableなオブジェクトが全て表示されるはずです。

その一覧を参考に、各IDisposableなオブジェクトを生成している処理に対して適切なタイミングでDisposeメソッドを呼んでください。

これで、Dispose忘れによるメモリリークは解決すると思います。

また、「Disposeメソッドを呼んでください」と書きましたが、リソース解放に便利な構文としてusingステートメントがありますので、可能ならDisposeメソッドではなくこちらを使用してください。

投稿2019/12/10 06:44

編集2019/12/10 07:08
BluOxy

総合スコア2663

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2019/12/10 06:46

つまり、Dispose忘れが問題なら「どの変数に対してGCが行われているか」は知る必要がありません。
JumpActionGames

2019/12/10 07:27

それならdispose忘れではないです。 すべてdisposeしています。
JumpActionGames

2019/12/10 07:29

ですが、ゲームですので、重要なマップデーターがありますので、それはdisposeできません どうすればいいですか?
BluOxy

2019/12/10 07:34 編集

重要なマップデータとはIDisposableを実装しているオブジェクトを指しているのでしょうか。 もしそうなら、そのオブジェクトをDisposeできないのはなぜでしょう。 そのオブジェクトに何かのデータを保持する必要性があるのかが疑問です。 データを保持する場所が適切でない可能性が高いです。
JumpActionGames

2019/12/10 07:35

それとBitmapデーターも必要なので、Disposeできません。(しません)
BluOxy

2019/12/10 07:35

int[]はIDisposableを実装していないので、Disposeは呼べません。
BluOxy

2019/12/10 07:37

BitmapオブジェクトはIDisposableですが、それは必要性がなくなったときにDisposeすれば良いように感じます。
JumpActionGames

2019/12/10 07:39

Bitmap1にはマップの全体の風景を映しておいて、Bitmap2は一部をくりぬいた(横スクロールゲームなので)マップの風景です。 bitmap2はdisposeできますが、Bitmap1はdisposeするとまた描画しないとダメ(fotとifのながーいいコード)ですから、どうすればいいですか
JumpActionGames

2019/12/10 07:43

だが、GCが実行されたときはゲームに問題はありません。 どういうことでしょうか?
BluOxy

2019/12/10 07:44

極論、Bitmap1をアプリケーション実行中にずっと使用するのであれば、アプリ終了時のイベント等でDisposeすることになります。(その設計が良いかは別の話ですが)
BluOxy

2019/12/10 07:44

不必要にリソースを抱え続けないよう、どこか適切なタイミングでDisposeできれば問題ありません。
JumpActionGames

2019/12/10 07:45

じゃあこの問題はどうすればいいですか?
JumpActionGames

2019/12/10 07:46

GCって不要なのをdisposeしてるという仕組みでしょうか? それだったらGCでどれがdisposeされてるか知りたいです
JumpActionGames

2019/12/10 07:48

GCのおかげでメモリが大きくてエラーとかは防げてますが、メモリが上がってGCで下がるの繰り返しだとなーんかよくないなぁという感じです
maisumakun

2019/12/10 07:49

> GCって不要なのをdisposeしてるという仕組みでしょうか? いえ、GCとDisposeは別件です。
BluOxy

2019/12/10 07:51 編集

> GCが実行されたときはゲームに問題はありません。 > GCって不要なのをdisposeしてるという仕組みでしょうか? GCはCLRの管理下にあるリソース(マネージドリソース)を解放します。IDisposableで抱えているようなリソース(アンマネージドリソース)は、CLRの管理下ではないので解放しません。 なので、GCが実行されたときはマネージドリソースの量が減るはずです。 アンマネージドリソースを解放するには開発者側で解放する必要があります。 具体的にはDisposeメソッドです。
YAmaGNZ

2019/12/10 07:50

なんかDisposを実行した瞬間にメモリ使用量が減るという勘違いをしているような気がします。 動作させ続けてメモリ使用量がどんどん増加するというのであれば問題ですが、増加→GC実行で減る→増加・・・と繰り返すがある値より増加しないのであれば正常な動作な気がします。
JumpActionGames

2019/12/10 07:51

マネージドリソースの開放はどうやってするんですか? Dispose以外のGCが使ってる関数などでお願いします
BluOxy

2019/12/10 07:52

> マネージドリソースの開放はどうやってするんですか? GCはCLRの管理下にあるリソース(マネージドリソース)を解放します。
JumpActionGames

2019/12/10 07:53

>YAmaGNS 正常ですが、もしゲームを公開した時に、タスクマネージャーで見たらメモリがぐにゃぐにゃしてたらなんか嫌じゃないですか? だから安定させたいんです
JumpActionGames

2019/12/10 07:54

Dispose以外でマネージドリソースを開放したいです。 どうすればいいですか?
maisumakun

2019/12/10 07:55 編集

> タスクマネージャーで見たらメモリがぐにゃぐにゃしてたらなんか嫌じゃないですか? ゲーム自体がスムーズに動くのであれば、そんなことを気にする人はたぶんいませんし、そのために開発工数をかけてメリットがあるものでもないです。
BluOxy

2019/12/10 07:54

メモリが上下するのは、newをした時点で動的にメモリが確保される訳ですから、仕方ないと思いますが…。
JumpActionGames

2019/12/10 07:57

MessageBox.Show(new string("あいうえおおおおおおおお")); これってメモリとられますか?
YAmaGNZ

2019/12/10 07:59

メモリ使用量を一定にするのであれば、使用する最大限を開始時にメモリに持つしかないと思います。
JumpActionGames

2019/12/10 08:02

MessageBox.Show(new string("あいうえおおおおおおおお")); このように関数の引数なのでnewを使ううとメモリってとられるんですか?
BluOxy

2019/12/10 08:20 編集

デフォルトで.NETアプリケーションにはメモリの上限値が設定されていますから、例えメモリ使用量が上下していても、その上限以上にメモリ使用量が達することはありません。直前にOutOfMemoryExceptionが発生します。 newはインスタンス化なので、ヒープメモリに確保されます。 stringは例外で、newを使わなくても扱うことができますが、これもヒープメモリに確保されます。 解放はどちらもGCのタイミングで行われます。
JumpActionGames

2019/12/10 08:06

あ、じゃあ気にしなくていいんですね!!
maisumakun

2019/12/10 08:06

> あ、じゃあ気にしなくていいんですね!! えっ?
BluOxy

2019/12/10 08:10

えっと、マネージドリソースについては、GCが勝手にやってくれるのでメモリを気にする必要はありませんが、Disposeが必要なオブジェクト(IDisposableなオブジェクト、すなわちアンマネージドリソース)は別です。 ここを区別できるようにしてください。 一応もう1度書いておきますが、IDisposableなオブジェクトにはusingステートメントを使うか、Disposeを呼び忘れないようにしてください。
JumpActionGames

2019/12/10 08:10

>解放はどちらもGCのタイミングで行われます。 それなら気にしなくていいんですね! ということです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問