2014年5月9日金曜日

スレッドスロットルなんか普通しなくてもいいのにね

すごくCPUも使うし、たくさんリクエストくるしー、なサイトを動かしてると、リクエストの上限を決め打ちしてしまいたくなるでしょー。そういうこともあるんです。

個別アプリケーションごとにVMがあったりとかー、そういうんだと、そんな時は maxConcurrentThreadsPerCPU とかでー、でしょうか。あ、maxWorkerThreads とかでも。

なんでそんなことが必要なんですか。そもそもCPU Throttlingでいいじゃないですかー。と、いうのもあるんですけど、そもそもマシンパワーのあまりない環境とかだと、返事が返ってこないです。解決方法はいろいろあるなかで、強制的にリクエストをキューから取り出さなきゃいいじゃないと思った結果がSetMaxThreads。

private int ThreadPoolThrottle
{
get
{
return int.Parse(ConfigurationManager.AppSettings["ThreadPoolThrottle"] ?? "0");
}

}

if (ThreadPoolThrottle > 0)
{
// 重いテンプレートの場合これ。
int workers;
int completions;
System.Threading.ThreadPool.GetMaxThreads(out workers, out completions);
System.Threading.ThreadPool.SetMaxThreads(ThreadPoolThrottle, completions);

}

アプリケーションスタート時に実行。


詳しくは↑を。

処理時間がすごく長いわけではないなら(これ重要)、スレッド減らして、っていう方法もありなんじゃないかなー、ないかなー。パフォーマンステストの数値としてはいい感じで。その時の数値はちょっと出しにくくすいません。

public ActionResult Index()
{
var start = DateTime.Now;
var hasher = System.Security.Cryptography.RIPEMD160Managed.Create();
while ((DateTime.Now - start).TotalSeconds < 1)
{
var hash = hasher.ComputeHash(new byte[1024 * 1024]);
Thread.Sleep(10);
}

return View();
}

こんなアクション(1000msの間CPUいっぱい使う、Sleepはちょっとあったほうが本物の挙動に近しいのでなんとなく)があったとして、abで確認してみるとそーねー、てなりますけど、だからなに、ともなります。

SetMaxThreadsで4にしたとき。



abが-n 40 -c 4の時と-c 40の時で同じ、っていうね。マシンパワーないとずいぶん結果は違うけど、まぁ、いいでしょう。

それだけなんすけどね。そのほうがよくなることもありますねー、って。CPU性能足りないときや、スレッドにスロットルかけて、全体最適のほうに倒すとか。設定はやみくもにはできなくて、実環境で調整していかないとうまくいかないんだけど、CPU性能足りないんだけど、リクエスト多くて、チューニングも難しい、って時にはぜひどうぞ。あ、あと、マシン占有できるならconfigでどうぞ。できないときだけね。

dotnetConf2015 Japan

https://github.com/takepara/MvcVpl ↑こちらにいろいろ置いときました。 参加してくださった方々の温かい対応に感謝感謝です。