質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.51%
C#

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

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

5回答

3124閲覧

オブジェクト指向(C#),負荷のかかる処理,GCの発生頻度について

ElecDove

総合スコア254

C#

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

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

6クリップ

投稿2017/07/14 02:32

C#で図形を扱う(簡易CAM)ソフトを書いています.

最終的なファイル出力時に大量の図形を並び替えたりつなぎ合わせたりして一つのファイルを作るのですが,この時にシリアライズやデシリアライズ,オブジェクトのnewが大量に生じるためかGCの発生頻度がえぐいことになります.

だいたい処理開始からファイル出力完了まで20秒程度の処理なのですが,VisualStudioのGC発生時のマーク?が埋め尽くされます.秒間数回は発生してるのでしょう...

ここで一般論を伺いたいのですが,このように割と時間・負荷のかかる処理でのGCはこんな頻繁に発生してよいものなのでしょうか.
GCが発生しているということは不要な(一時的な)オブジェクトが大量に発生しているということだと思いますが,やはり避けるべきなのでしょうか.

イメージとして
①できるだけ避けたいが,どうしようもないならしょうがない
②何があっても許されない.どうしようもないと思うならプログラムを最初から作り直すべきレベルの大問題
↑このニュアンスだとどちらに近いですか?

stringの結合はStringBuilderを使用し,StringBuilderのインスタンスはループの外で宣言,Clear()で使いまわしをしています.(StringBuilderを用いるとstring型で+演算子を用いるよりもおよそ30%高速化しました)

おそらく,,,シリアライズ・デシリアライズでオブジェクトの複製を作っているのでその時のMemoryStreamが一番の原因かな,とは思っているのですが…

C#

1using (var memoryStream = new System.IO.MemoryStream()) { 2 var binaryFormatter = new BinaryFormatter(); 3 binaryFormatter.Serialize(memoryStream, this); 4 memoryStream.Seek(0, System.IO.SeekOrigin.Begin); 5 NewObj = (Hoge)binaryFormatter.Deserialize(memoryStream); 6}

GC発生頻度

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

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

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

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

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

guest

回答5

0

https://msdn.microsoft.com/ja-jp/library/f144e03t(v=vs.90).aspxを参照すると、C#のランタイムはJavaと同様世代別GCを行っているように思います。世代別GCでは「生成されたばかりのオブジェクトの多くは生存期間が短く、その中の一部のオブジェクト(GCで使用中であることがわかったもの)は比較的生存期間が長い」という経験則に従います。

上のページで説明されている世代0の領域がいっぱいになるたびにGCが行われますが、通常は比較的生存期間が長いオブジェクトが配置されている世代1,2はGCの対象とせずに、世代0にある「確保されたばかりのオブジェクト」のみに着目してGCするため大量にオブジェクトを生成する期間では世代0の領域のGCが高頻度で行われます。しかしながら上記のアルゴリズムの狙い通り、

(1) 高頻度でGCが行われる世代0のオブジェクトの多くはすぐに開放される
(2) 世代1,2はほとんどGCが行われず世代0(一部の領域)のみGCを行うためGCにかかる時間は短い

という傾向になるためGCが高頻度で動くことは異常というより「期待されている動き」といってよいと思います。ただ

(A) オブジェクトを高頻度で生成するアルゴリズムと生成しなくて済むアルゴリズムの両方が考えられる
(B) 高頻度で生成しなくて済むアルゴリズムを取ることで設計が過度に複雑にはならない

ならオブジェクトの生成を抑えるアルゴリズムを選択することに一定の効果はあると思います。ただそれにこだわりすぎて平易なアルゴリズムが複雑なアルゴリズムになるくらいなら却ってGCに頼った方が有効(複雑すぎるアルゴリズムはバグの原因・保守性を下げる大きな問題になるかも知れないから)ということになると思います。

投稿2017/07/14 03:02

KSwordOfHaste

総合スコア18392

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

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

ElecDove

2017/07/14 13:17

詳しい説明いただきありがとうございます >ならオブジェクトの生成を抑えるアルゴリズムを選択することに一定の効果はあると思います。ただそれにこだわりすぎて平易なアルゴリズムが複雑なアルゴリズムになるくらいなら却ってGCに頼った方が有効(複雑すぎるアルゴリズムはバグの原因・保守性を下げる大きな問題になるかも知れないから)ということになると思います。 とても納得いたしました 確かにオブジェクトの使い回しをしようとするとだいぶスパゲッティになるんですよね・・・
guest

0

ベストアンサー

いつもこんな感じだからGCの頻度は気にしたことありません。
せいぜい、気にするのはメモリの使用量ですかね。
メモリーリークしていて無限にメモリーを消費し続けると動かなくなりますし。

基本は、きれいなコードが正しくて、最適化のために汚くなるならやらないほうがいいと思います。
StringBuilderを使うとか、常識的なことは、当然やるとして、
それ以上のことは、困ってからやるというのが原則です。

早すぎる最適化」はよくありません

とはいえ、メソッドごとの呼び出し回数やかかった時間を計測してくれる機能はVSにあるので、それを使うといいと思います。
あからさまに遅い処理のところが見つかるので、そこをちょこっと改善するだけで大きく変わると思います。

投稿2017/07/14 03:06

kiichi54321

総合スコア1984

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

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

ElecDove

2017/07/14 13:19

回答ありがとうございます >いつもこんな感じだからGCの頻度は気にしたことありません。 >メモリーリークしていて無限にメモリーを消費し続けると動かなくなりますし。 どこかで,(通常動作時)GCの発生頻度は数秒に1回程度くらいが適当で秒間に何度も発生しているようならアルゴリズムを見直したほうがいい という記事?を見かけたので気になっていました >メソッドごとの呼び出し回数やかかった時間を計測してくれる機能はVSにあるので、それを使うといいと思います。 まだVSのデバッガとしての機能にはまったく把握し切れていないので非常に助かります 調べてみたいと思います
kiichi54321

2017/07/14 14:19

パフォーマンス プロファイリング この記事ですね。 https://msdn.microsoft.com/ja-jp/library/ms182372.aspx >どこかで,(通常動作時)GCの発生頻度は数秒に1回程度くらいが適当で秒間に何度も発生しているようならアルゴリズムを見直したほうがいい 初耳。こういうのは、回答に書いたように、困ってからでいいと思う。 この記事の「不幸な実装例」にあるように、ゲームとか携帯とかそういうところの話なのかなと推測。 http://dic.nicovideo.jp/a/%E3%82%AC%E3%83%99%E3%83%BC%E3%82%B8%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3
guest

0

細かく発生する GC はむしろ歓迎すべきもので、それによって不都合がないなら「気にしない」に一票入れときます。

投稿2017/07/14 02:56

hihijiji

総合スコア4150

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

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

0

回数はいくら多くても問題ありません。それより時間を見た方が良いですよ。
パフォーマンスカウンタ .NET CLR Memory% Time in GC
この値が10%以下ならGCがパフォーマンスに悪影響を与えていないので気にする必要はありません。

投稿2017/07/14 11:21

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

ElecDove

2017/07/14 13:20

回答ありがとうございます >パフォーマンスカウンタ .NET CLR Memory\% Time in GC というものがあるのですね まずは調べてみたいと思います
guest

0

.NET の GC は
「1回で100ミリ秒止めるくらいなら、小分けに100回にして1回あたりを1ミリ秒で留める」
という思想でゴミ拾いをするので、頻度が増えるのはおかしなことではありません。

投稿2017/07/14 03:06

tacsheaven

総合スコア13703

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問