プロが教えるわが家の防犯対策術!

C#のメモリやGCについて、ご教授ください。

現在、以下のようなソースのメモリ軽減、処理速度(実行速度)上昇をしたいと思っています。

class setString{
void setString(List<List<List<string>>> data, ref string outputData){
int lCount1 = data.count();
for(int lc1 = 0; lc1 < lCount; lc1++){
List<List<string>> l1 = data[lc1];
int lCount2 = l1.count();
for(int lc2 = 0; lc2 < lCount2; lc2++){
List<string> l2 = l1[lc2];
switch(lc2){
case 0: name += l2[lc2]; break;
case 1: age += l2[lc2]; break;
cade 2: sex += l2[lc2]; break;
}
}
outputdata += "¥n";
}
}
}

このsetString関数のメモリ、時間軽減を考えています。
※実際はわざわざ再宣言してListをつくるような処理はしていません。引数は上記ソース引数のListの各要素をアドレス配列で受けます。l2のアドレスでListを取ってきて、ループさせる、みたいな。諸事情で、引数自体の見直しは一旦考えず、ただただ上記の関数内の処理をどうにかしたいと考えています。

個人的に懸念している点は、メモリ使用量です。
上記の作りだと、毎回Listを作って、メモリ食いをしています。
マネージ、アンマネージの知識が薄く、GCがどれほど有用なのか、という点が分かりかねており、対処法に悩んでいます。
ちなみに、インターフェースになってきて、IDisposableクラスの継承は困難です。

たとえば、for単位で関数を作り、呼び出し後にGC.Colect();を足すとどうでしょうか?

void setString(List<List<List<string>>> data){
int lCount1 = data.count();
l1Set(data, lCount1);
GC.Colect();
}
void setl1(List<List<List<string>>> data, ref string output){
int lCount1 data.count();
for(int lc1 = 0; lc1 < lCount; lc1++){



}
}
※上記のように、set2、set3を作る形です。setStringの関数呼び出し後のようにGC.Colect();を足して変化があるのかは謎で、あくまで方法案です。

foreachよりforが速度は勝ると思ってforは推奨方針、refなどを使って等も考えたのですが、いまひとつピンと来ていません。
メソッド分けは有用やこういうのがスマート、などあればお教えください。
お手数ですが、宜しくお願い致します。

質問者からの補足コメント

  • set1の引数間違えました。
    ListとListCountとref outputになります。

      補足日時:2018/07/01 22:27
  • 更に誤りがありました。
    name、age、sexに代入ではなく、outputDataに+=で足します

      補足日時:2018/07/01 22:29

A 回答 (3件)

ループ内での文字列の継ぎ足し連結は非常識。


また、ガベコレを頻繁に行うとメチャ遅くなります。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
ループ内の文字列連結は今回のことでつくづく学びました。
GC多発で遅くなるというのは初めて伺いました。
これまではDisposeがあれば幸いですが、無いときでメモリに困ったら、とにかくGC.Colect乱射みたいな行為に走っていました。
今後気を付けます。

お礼日時:2018/07/02 23:42

同じく


name
age
sex
の取扱いの問題だとおもいます。

この関数の内部で最適化できる要素が見つかりません。

ごみも貯めてませんので、ごみ捨ても無意味とおもいます。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。
とりあえずkmeeさんからお教えいただいた、StringBuilderへの切り替えで概ね平常運転してくれました。
実際はそこそこのステップ数になるメソッドでしたが、投稿にあたって簡略化しようとしたところ、あまりうまくいかず、読みづらくなってしまいすみません。

お礼日時:2018/07/02 23:38

「毎回Listを作って」なんてこと、してませんけど?



List<List<string>> l1 = data[lc1];
List<string> l2 = l1[lc2];

ここのことを「毎回Listを作って」と言っているのなら、間違っています。
Listは参照型であり、ここでは「参照値を覚えるための変数(高々数バイト分」しか使われません。
ここでメモリを圧迫するとは思えません。


文字列連結が効いてるように思います
https://dobon.net/vb/dotnet/string/stringbuilder …
    • good
    • 1
この回答へのお礼

見るのが遅くなりました。
StringBuilderを使ってみたところ、非常に速度が上がりました。
メモリに関しては、Listではなく、※記載のList要素アドレス配列などを持つクラスオブジェクトが邪魔をしていたようです。
勘違いでした。すみません。
ご回答ありがとうございました。

お礼日時:2018/07/02 23:34

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!