- PR -

HttpWebRequest で OutOfMemory 発生

1
投稿者投稿内容
未記入
常連さん
会議室デビュー日: 2004/08/26
投稿数: 34
投稿日時: 2008-11-25 14:22
VisualStudio 2003 C# で開発しています。

マルチスレッドで、webアプリケーションにアクセスし、
レスポンス時間を計測するツールを作成しています。
15000スレッドを600秒間実施(1秒間に25回のリクエスト)した場合、
OutOfMemoryが発生し、異常終了していまいます。
原因および対処方法のご教授お願いします。

以下、ソースです。

using System;
using System.Threading;
using System.Net;

namespace ConsoleApplication1
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
Class2 class2 = new Class2();
class2.Run();
}
}

class Class2
{
Thread[] m_thread;
const string url = "http://xxxxx"; //リクエスト先URL
int threadCount = 15000; //スレッド数
double rumpUp = 600; //時間

public void Run()
{
m_thread = new Thread[threadCount];
TimeSpan ts = new TimeSpan((long)((rumpUp / threadCount) * 10000000));

for(int i = 0; i < threadCount; i++)
{
//スレッド実行
m_thread[i] = new Thread(new ThreadStart(AccessUrl));
TimeSpan st = new TimeSpan(DateTime.Now.Ticks);
m_thread[i].Start();
TimeSpan ed = new TimeSpan(DateTime.Now.Ticks);

//スレッドの間隔を調整
if(ts > ed.Subtract(st))
{
System.Threading.Thread.Sleep(ts.Subtract(ed.Subtract(st)));
}
}

//スレッドが全て終了するまで待機
while(true)
{
if(IsThreadsAlive())
{
break;
}
System.Threading.Thread.Sleep(100);
}
}

private bool IsThreadsAlive()
{
for (int i = 0; i < m_thread.Length; i++)
{
if (m_thread[i].IsAlive)
{
return false;
}
}
return true;
}

private void AccessUrl()
{
TimeSpan st = new TimeSpan();
TimeSpan ed = new TimeSpan();

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.ContentType = "application/octet-stream";
req.Timeout = 100000;
req.Method = "POST";
req.KeepAlive = true;
req.ContentLength = 0;

st = new TimeSpan(DateTime.Now.Ticks);

//レスポンスを取得
using(HttpWebResponse res = (HttpWebResponse) req.GetResponse())
{
ed = new TimeSpan(DateTime.Now.Ticks);

//コンソールに結果を出力
System.Diagnostics.Debug.WriteLine(res.StatusCode + " " + ed.Subtract(st));
res.Close();
}

}

}
}
なかむら
ベテラン
会議室デビュー日: 2008/11/11
投稿数: 67
お住まい・勤務地: 福岡
投稿日時: 2008-11-25 14:32
スレッド数が15000って・・・多過ぎませんか?

_________________
Nakamura Blog
なりたて管理者
常連さん
会議室デビュー日: 2008/11/14
投稿数: 26
投稿日時: 2008-11-25 15:05
一度に全部動かそうとすればOutOfMemoryは出ると思いますよ

確認して欲しい事
1:レスポンスの確認も大事ですが確認しようとしているWEBアプリケーションは15000のリクエストを必要とするのか?またそれを実行出来る環境にあるのか?(サーバのスペック等)
2:WEBアプリケーションのレスポンスを確認するのに15000スレッドを実行しないと確認出来ないのか?

もし必要なテストの場合、
出来るかどうか分からないですがこういう事は出来ないですか?
1.使用したいメモリ領域を確保してから実行してみる
2.使用終わったオブジェクトはどんどんクリアする(ガベージコレクションはいつ実行されるか分からない為)
3.1の領域が一杯になったら一時停止する。開放されたら再度実行

VisualStudio 2003 C#で組んだ事は無いので実際にどう組むかは分かりませんが
他の言語で開発をした時に試してみた方法です。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-11-25 15:18
引用:

未記入さんの書き込み (2008-11-25 14:22) より:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);


良くは知りませんが、これの Close って要らないんでしょうか?
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2008-11-25 15:26
引用:

未記入さんの書き込み (2008-11-25 14:22) より:
マルチスレッドで、webアプリケーションにアクセスし、
レスポンス時間を計測するツールを作成しています。
15000スレッドを600秒間実施(1秒間に25回のリクエスト)した場合、
OutOfMemoryが発生し、異常終了していまいます。


スレッドを作るたびにスタック用のメモリが確保されることは承知している?
スタック用のメモリは、デフォルトでは1スレッドにつき2MB確保される。
15000スレッド作るためには、そのため30GBのメモリが必要になるんだけど・・・。

スタックサイズに適当に小さな値を指定すれば、作成できるスレッドの数は増えるよ。
ただし、適切なスレッドサイズを算出する方法はないので、むやみに小さくすることはお勧めできない。

言っちゃ悪いが、設計から見直す必要があるんじゃないかと...
大量のスレッドを作らなくても済むような実装を検討するか、あるいはFiberやThreadPoolを使って実装することを検討してください。

1

スキルアップ/キャリアアップ(JOB@IT)