Wydajność dekompresji GZipStream jest niska
Mam aplikację WinForms .NET 2.0, która łączy się z serwerem WAS zaplecza. Używam GZipStream do dekodowania danych wracających z wywołania HttpWebRequest na serwer. Zwracane dane to skompresowany CSV, który kompresuje Apache. Cały stos serwerów to Hibernate -> EJB -> Spring -> Apache.
W przypadku małych odpowiedzi wydajność jest dobra (<50 ms). Gdy otrzymam odpowiedź> 150 KB, dekompresja zajmuje ponad 60 sekund. Większość czasu wydaje się spędzać w konstruktorze GZipStream.
Oto kod pokazujący, gdzie otrzymuję strumień odpowiedzi z wywołania 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();
}
}
}
Edytuj 1
Opierając się na komentarzu Lucero, zmodyfikowałem metodę Dekompresję do następującej, ale nie widzę żadnej korzyści z wydajności po załadowaniu ResponseStream do MemoryStream przed utworzeniem instancji GZipStream.
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();
}
}
}
}
Czy na podstawie powyższego kodu każdy może zobaczyć jakieś problemy? Wydaje mi się to dość podstawowe, ale doprowadza mnie to do szału.
Edytuj 2
Profilowałem aplikację przy użyciu Profiler ANTS, a podczas dekompresji w latach 60 procesor jest bliski zeru, a zużycie pamięci nie zmienia się.
Edytuj 3
Rzeczywiste spowolnienie wydaje się być podczas odczytu
this.Response.GetResponseStreamCałe lata 60. spędzają ładując strumień odpowiedzi na MemoryStream. Gdy już tam będzie, połączenie z GZipStream jest szybkie.
Edytuj 4
Odkryłem, że użycie HttpWebRequest.AutomaticDecompression wykazuje ten sam problem z wydajnością, więc zamykam to pytanie.