バックエンド WAS サーバーに接続する .NET 2.0 WinForms アプリがあります。サーバーに対して行われた HttpWebRequest 呼び出しから返されるデータをデコードするために GZipStream を使用しています。返されるデータは、Apache が圧縮している圧縮された CSV です。サーバースタック全体は、Hibernate-->EJB-->Spring-->Apache です。
応答が小さい場合、パフォーマンスは問題ありません (<50ms)。150KB を超える応答を受け取った場合、解凍に 60 秒以上かかります。ほとんどの時間は GZipStream コンストラクターで費やされているようです。
これは、HttpWebResponse 呼び出しから応答ストリームを取得する場所を示すコードです。
using (Stream stream = this.Response.GetResponseStream())
{
if (this.CompressData && this.Response.ContentEncoding == "gzip")
{
// Decompress the response
byte[] b = Decompress(stream);
this.ResponseBody = encoding.GetString(b);
}
else
{
// Just read the stream as a string
using (StreamReader sr = new StreamReader(stream))
{
this.ResponseBody = sr.ReadToEnd();
}
}
}
編集 1
Lucero からのコメントに基づいて、Decompress メソッドを次のように変更しましたが、GZipStream をインスタンス化する前に ResponseStream を MemoryStream にロードしても、パフォーマンス上の利点は見られません。
private static byte[] Decompress(Stream stream)
{
using (MemoryStream ms = new MemoryStream())
{
byte[] buffer = new byte[4096];
int read = 0;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
ms.Seek(0, SeekOrigin.Begin);
using (GZipStream gzipStream = new GZipStream(ms, CompressionMode.Decompress, false))
{
read = 0;
buffer = new byte[4096];
using (MemoryStream output = new MemoryStream())
{
while ((read = gzipStream.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}
return output.ToArray();
}
}
}
}
上記のコードに基づいて、誰でも問題を確認できますか? これは私には非常に基本的なことのように思えますが、それは私を夢中にさせています。
編集 2
ANTS Profiler を使用してアプリケーションのプロファイリングを行ったところ、60 秒間の解凍中に CPU はほぼゼロになり、メモリ使用量は変化しませんでした。
編集 3
実際の速度低下は、の読み取り中に発生するようです
this.Response.GetResponseStream60 秒全体が、応答ストリームを MemoryStream にロードするために費やされます。そこにあると、GZipStream への呼び出しは迅速です。
編集 4
HttpWebRequest.AutomaticDecompression を使用すると同じパフォーマンスの問題が発生することがわかったので、この質問を閉じます。