C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: for文を抜けない。。


(過去ログ 38 を表示中)

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■19950 / inTopicNo.1)  for文を抜けない。。
  
□投稿者/ みちる (7回)-(2008/06/03(Tue) 00:15:24)

分類:[ASP.NET (C#)] 

C#開発です。

原因が分からず困っております。お力をお貸し下さい。
C#で10万件のデータを配列にて扱います。
テスト状態で以下内容を試しました。

string型に配列のデータをfor文で回して格納するものです。
一つのデータはstringで30文字以内です。
確認したところ100件ぐらいまでは格納できています。
その後for文後にブレイクポイントを置き、実行しますが、そこにこないでそのまま固まってしまっています。
なんどやっても駄目でした。

あと100件ぐらいの件数でためしたところstring型にきちんと文字が入っていました。

10万件だと駄目で、何件までいけるのかもわかりません。

どういった原因なんでしょうか。
引用返信 編集キー/
■19951 / inTopicNo.2)  Re[1]: for文を抜けない。。
□投稿者/ Azulean (134回)-(2008/06/03(Tue) 00:23:09)
> その後for文後にブレイクポイントを置き、実行しますが、そこにこないでそのまま固まってしまっています。
> なんどやっても駄目でした。

> あと100件ぐらいの件数でためしたところstring型にきちんと文字が入っていました。
> 10万件だと駄目で、何件までいけるのかもわかりません。
時間が掛かっているだけという可能性は、否定できるんですか?
単純計算でも、100件にかかった時間のおよそ1,000倍はかかるんですから、100件に10秒かかれば、10,000秒(約167分=約2.8時間)かかりますよ。

> どういった原因なんでしょうか。
100件でどのくらいかかっているかを計測し、またその1,000倍は単純計算でどのくらいになるか求めて下さい。
その上で、予想よりも大幅に遅くなるのであれば、現在のコードを示して下さい。
引用返信 編集キー/
■19952 / inTopicNo.3)  Re[1]: for文を抜けない。。
□投稿者/ 魔界の仮面弁士 (755回)-(2008/06/03(Tue) 00:39:14)
No19950 (みちる さん) に返信
> string型に配列のデータをfor文で回して格納するものです。
> 一つのデータはstringで30文字以内です。
> 確認したところ100件ぐらいまでは格納できています。

たとえばループ中で、string 型変数に対して
 s += textData[i] + "\r\n";
のような単純連結を繰り返していたりはしませんか?

もしそうなら、StringBuilder を使う事を検討してみてください。
引用返信 編集キー/
■19953 / inTopicNo.4)  Re[1]: for文を抜けない。。
□投稿者/ 倉田 有大 (266回)-(2008/06/03(Tue) 00:42:22)
No19950 (みちる さん) に返信
> C#開発です。
>
> 原因が分からず困っております。お力をお貸し下さい。
> C#で10万件のデータを配列にて扱います。
> テスト状態で以下内容を試しました。
>
> string型に配列のデータをfor文で回して格納するものです。
> 一つのデータはstringで30文字以内です。
> 確認したところ100件ぐらいまでは格納できています。
> その後for文後にブレイクポイントを置き、実行しますが、そこにこないでそのまま固まってしまっています。
> なんどやっても駄目でした。
>
> あと100件ぐらいの件数でためしたところstring型にきちんと文字が入っていました。
>
> 10万件だと駄目で、何件までいけるのかもわかりません。
>
> どういった原因なんでしょうか。

1000件、一万件にして、はかられてみては?
単純に処理に時間がかかっているだけでは。

引用返信 編集キー/
■19955 / inTopicNo.5)  Re[2]: for文を抜けない。。
□投稿者/ みちる (9回)-(2008/06/03(Tue) 01:16:49)
No19953 (倉田 有大 さん) に返信
> ■No19950 (みちる さん) に返信
>>C#開発です。
>>
>>原因が分からず困っております。お力をお貸し下さい。
>>C#で10万件のデータを配列にて扱います。
>>テスト状態で以下内容を試しました。
>>
>>string型に配列のデータをfor文で回して格納するものです。
>>一つのデータはstringで30文字以内です。
>>確認したところ100件ぐらいまでは格納できています。
>>その後for文後にブレイクポイントを置き、実行しますが、そこにこないでそのまま固まってしまっています。
>>なんどやっても駄目でした。
>>
>>あと100件ぐらいの件数でためしたところstring型にきちんと文字が入っていました。
>>
>>10万件だと駄目で、何件までいけるのかもわかりません。
>>
>>どういった原因なんでしょうか。
>
> 1000件、一万件にして、はかられてみては?
> 単純に処理に時間がかかっているだけでは。
返信有難うございます。

30分ほど放置しましたが無反応でした。
ただ遅いだけということですが、
10万件のデータというのはデータベースから持ってきたもので、
ためしにそれだけのコードで
10万件のデータを配列に格納する為for文で回して格納するのは10秒も掛からず格納されました。
その配列をそのままstringに格納する処理をすると固まります。

stringBuilderとのことですが、明日試してみます。
引用返信 編集キー/
■19958 / inTopicNo.6)  Re[3]: for文を抜けない。。
□投稿者/ Azulean (135回)-(2008/06/03(Tue) 07:24:06)
StringBuilderで試した結果で問題が残っているのであれば、コードを示して下さい。
現状の文章では、forの中身の何がまずいのか特定できないですよ。
引用返信 編集キー/
■19961 / inTopicNo.7)  Re[1]: for文を抜けない。。
□投稿者/ Algol (24回)-(2008/06/03(Tue) 09:30:08)
2008/06/03(Tue) 11:00:32 編集(投稿者)
2008/06/03(Tue) 09:40:28 編集(投稿者)

前投函を盛大に勘違いしてたお詫びにサンプルを作って計測してみました。
参考になれば…

・計測内容
1. 1,000,000件x30文字の配列を作成
2. string.Join メソッドを使った連結
3. StringBuilderクラスを使った連結(キャパ指定なし)
4. StringBuilderクラスを使った連結(キャパ指定あり)
5. += を使った文字列の連結

・計測結果
1. 15ms
2. 141ms
3. 430ms
4. 137ms
5. 時間がかかりすぎ最後まで到達しなかったので1,000件毎10,000件までの計測
  1000 :   120ms
  2000 :   336ms
  3000 :   697ms
  4000 :  1291ms
  5000 :  2349ms
  6000 :  3679ms
  7000 :  5131ms
  8000 :  6877ms
  9000 :  8848ms
 10000 : 11109ms

・結論
お手軽 = string.Joinメソッド
速さ = StringBuilderクラス(キャパ指定あり)

・サンプルソース

//配列作成
string[] testArray = new string[1000000];
//受け取り用文字列
string resultString = "";

//計測
Stopwatch testTime = new Stopwatch();

//配列作成
testTime.Start();
for (int count = 0; count <= testArray.Length - 1; count++)
{
    testArray[count] = "123456789012345678901234567890";
}

testTime.Stop();
Debug.WriteLine(string.Format("1.[{0}ms]", testTime.ElapsedMilliseconds));
testTime.Reset();

//単純にJoinで
testTime.Start();
resultString = string.Join("", testArray);

testTime.Stop();
Debug.WriteLine(string.Format("2.[{0}ms]", testTime.ElapsedMilliseconds));
testTime.Reset();
resultString = "";

//キャパ指定なし
StringBuilder stringBuilder = new StringBuilder();

testTime.Start();
for (int count = 0; count <= testArray.Length - 1; count++)
{
    stringBuilder.Append(testArray[count]);
}
resultString = stringBuilder.ToString();

testTime.Stop();
Debug.WriteLine(string.Format("3.[{0}ms]", testTime.ElapsedMilliseconds));
testTime.Reset();
resultString = "";

//キャパ指定あり
stringBuilder = new StringBuilder(30000000);

testTime.Start();
for (int count = 0; count <= testArray.Length - 1; count++)
{
    stringBuilder.Append(testArray[count]);
}
resultString = stringBuilder.ToString();

testTime.Stop();
Debug.WriteLine(string.Format("4.[{0}ms]", testTime.ElapsedMilliseconds));
testTime.Reset();
resultString = "";
stringBuilder = null;

//+=の場合
testTime.Start();
for (int count = 0; count <= testArray.Length - 1; count++)
{
    if((count % 1000) == 0)
        Debug.WriteLine(string.Format("{0} : [{1}ms]", count, testTime.ElapsedMilliseconds));

    //リミッタ
    if (count >= 10000) break; 

    resultString += testArray[count];
}

testTime.Stop();
Debug.WriteLine("End");

引用返信 編集キー/
■20008 / inTopicNo.8)  Re[3]: for文を抜けない。。
□投稿者/ PATIO (75回)-(2008/06/04(Wed) 11:09:39)
No19955 (みちる さん) に返信
> ただ遅いだけということですが、
> 10万件のデータというのはデータベースから持ってきたもので、
> ためしにそれだけのコードで
> 10万件のデータを配列に格納する為for文で回して格納するのは10秒も掛からず格納されました。
> その配列をそのままstringに格納する処理をすると固まります。

配列と言うのが固定長配列なのか可変長配列なのかわかりませんけれど、
stringに追加すると言う処理を想像してみてください。
可変長で文字列を編集する場合、動的にメモリの確保や開放を随時行なう必要が
あると思います。これを10万回も繰り返したら多分かなりの負荷になる思います。
一般的に文字列編集を伴う処理は重いので配列に単にセットする処理と同じレベルで
考えるのは拙いと思いますよ。

恐らく皆さんが勧めておられるStringBuilderクラスはこの辺の効率を考慮した
クラスなんだと思うのでそちらを使って見られると状況が変わるのではないかと思います。

引用返信 編集キー/
■20029 / inTopicNo.9)  Re[2]: for文を抜けない。。
□投稿者/ なちゃ (134回)-(2008/06/04(Wed) 12:48:16)
例えば1レコード100文字とした場合、単純に文字列を連結してしまうと、
最後の方では1レコードにつき1000万文字分のメモリ確保とコピーが発生するわけです。
平均すると500万文字×10万、コピーだけでおよそ1TBの処理です。

引用返信 編集キー/
■20031 / inTopicNo.10)  Re[3]: for文を抜けない。。
□投稿者/ なちゃ (135回)-(2008/06/04(Wed) 13:03:16)
おっと、30文字だったら300GBくらいかな?

引用返信 編集キー/
■20033 / inTopicNo.11)  Re[4]: for文を抜けない。。
□投稿者/ 魔界の仮面弁士 (758回)-(2008/06/04(Wed) 13:51:53)
2008/06/04(Wed) 14:09:32 編集(投稿者)

# シグマ記号が、U+2211: N-Ary Summation になっていましたが、
# 機種依存文字らしいので、U+03A3: Greek Capital Letter Sigma に
# 差し替えました。

No20031 (なちゃ さん) に返信
> おっと、30文字だったら300GBくらいかな?

30文字×10万レコードだったら、単純計算で300万なので、
UTF-16 換算で 600万バイト、5.7 MB 程度では無いですか?


…いや、1 レコードあたりではなく、コピー量の総計の事かな。
という事は、
 Σ(30文字×N回)
なので、N = 1〜10万として、150,001,500,000 文字。

3千億バイトなので 約279GB。なるほど。そのぐらいでしょうね。


StringBuilder なら、概算で 6 MB 程度で済む処理が、
String 連結だと、279GB になってしまう換算ですね。怖い怖い。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -