我有一个连接到后端 WAS 服务器的 .NET 2.0 WinForms 应用程序。我正在使用 GZipStream 解码从对服务器进行的 HttpWebRequest 调用返回的数据。返回的数据是 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.GetResponseStream整个 60 年代都用于将响应流加载到 MemoryStream 中。一旦它在那里,对 GZipStream 的调用就会很快。
编辑 4
我发现使用 HttpWebRequest.AutomaticDecompression 会出现同样的性能问题,所以我要结束这个问题。