2009-10-05 5 views
3

J'ai une application .NET 2.0 WinForms qui se connecte à un serveur WAS backend. J'utilise GZipStream pour décoder les données provenant d'un appel HttpWebRequest fait au serveur. Les données renvoyées sont CSV compressé, compressé par Apache. La pile entière du serveur est Hibernate -> EJB -> Spring -> Apache.Les performances de la décompression GZipStream sont médiocres

Pour les petites réponses, les performances sont bonnes (< 50ms). Quand je reçois une réponse> 150 Ko, il faut plus de 60 secondes pour décompresser. La majorité du temps semble être passé dans le constructeur GZipStream.

Ce code montre l'endroit où je reçois le flux de réponse de l'appel 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(); 
    } 
} 
} 

Modifier 1

Basé sur le commentaire de Lucero, j'ai modifié la méthode Décompresser à ce qui suit , mais je ne vois aucun avantage de performance de charger le ResponseStream dans un MemoryStream avant d'instancier le 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(); 
    } 
    } 
} 
} 

Basé sur le code ci-dessus, quelqu'un peut-il voir des problèmes? Cela me semble assez basique, mais ça me rend fou.

Edit 2

I profilées l'application en utilisant ANTS Profiler, et dans les années 60 de décompression, l'unité centrale est proche de zéro et l'utilisation de la mémoire ne change pas.

Edit 3

Le ralentissement actuel semble être au cours de la lecture de

this.Response.GetResponseStream
Les années 60 entièrement passé le chargement du flux de réponse dans le MemoryStream. Une fois qu'il est là, l'appel à GZipStream est rapide.
Modifier 4

Je trouve que l'utilisation HttpWebRequest.AutomaticDecompression présente le même problème de performance, donc je ferme cette question.

+0

Voter pour fermer parce que la décompression est pas la question correcte. – Armbrat

+0

Lorsque vous dites que l'ajout du flux de mémoire n'a pas amélioré les performances, mesurez-vous en fait le temps nécessaire pour compresser séparément le temps qu'il faut pour écrire toutes les réponses dans le flux de mémoire? Mon soupçon est, étant donné que le processeur est proche de zéro, que le goulot d'étranglement n'est pas le zipping, mais à quelle vitesse vous pouvez télécharger la réponse. –

+0

Avez-vous résolu ce problème? – rolls

Répondre

1

Essayez d'abord charger les données dans un MemoryStream puis décompressez le MemoryStream ...

+0

J'ai essayé ceci - voir la question modifiée. Merci pour la suggestion. – Armbrat

+0

Je vois. Est-ce que le temps est encore passé dans le constructeur du flux GZip, ou maintenant ailleurs? – Lucero

+0

Ceci est (autant que je sache) passé dans le constructeur du flux GZip. – Armbrat

0

Désolé de ne pas répondre directement à votre question, mais avez-vous regardé SharpZip encore? Je l'ai trouvé beaucoup plus facile à utiliser que Gzip. Si vous avez de la difficulté à résoudre votre problème actuel, peut-être que cela faciliterait la tâche.

http://www.icsharpcode.net/OpenSource/SharpZipLib/

+0

J'ai essayé SharpZipLib et il présente les mêmes mauvaises performances que System.IO.Compression.GZipStream et DotNetZip. Je vais passer par la source SharpZipLib pour voir si quelque chose me saute aux yeux. – Armbrat

+0

Intéressant ... J'ai un gros fichier xml qui est environ 70 megs non compressé qui décompresse en environ 15 secondes sur un système. Je commence à me demander si c'est vraiment lié à votre code. Pourriez-vous jeter un coup d'œil à votre antivirus sur ce système? Peut-être qu'il raccroche. Nous avons eu des problèmes majeurs avec Etrust d'IBM en train de raccrocher des fichiers pendant beaucoup plus longtemps qu'ils ne le devraient. Je peux fournir un échantillon de code si vous voulez mais encore une fois je pense que ce n'est pas lié au code. –

+0

J'essaie de penser à quoi d'autre pourrait être votre cou de bouteille. Vous pourriez essayer d'exécuter un testeur de mémoire sur ce système. Peut-être qu'il a une RAM défectueuse? Je ne fais que du brainstorming pour toi. Juste semble étrange. –

1

DotNetZip a une classe GZipStream qui peut être utilisé comme une solution de remplacement pour le System.IO.Compression.GZipStream.

DotNetZip est gratuit. NB: Si vous ne faites que GZipStream, alors vous avez besoin de l'Ionic.Zlib.dll, pas de l'Ionic.Zip.dll.

+0

J'ai essayé d'utiliser la bibliothèque DotNetZip/Zlib mais j'ai trouvé le même problème de performance. – Armbrat

+0

Si c'est le cas, il semble que ce ne soit pas le DeflateStream. Peut-être que vous avez un problème de mémoire. Peut-être devriez-vous tester plus d'itérations - il est difficile de tirer des conclusions sur les performances basées sur une seule itération, un seul essai. – Cheeso

+0

Je ne suis pas ce que vous voulez dire par "tester plus d'itérations"? C'est l'une des nombreuses demandes adressées au même serveur. La majorité des requêtes ne récupèrent que ~ <10k données. C'est la seule "grande" requête, et c'est seulement ~ 150k. – Armbrat

0

Je vais laisser tomber mes trois cents sur le sujet, juste pour avertir les utilisateurs C# qu'un 7Zip semble exposer son API en langage C#.Je pense que vous connaissez tous très bien l'outil 7Zip, et au moins pour moi, quelle que soit la qualité de son API, sachant que cela aide énormément à améliorer la gestion des fichiers/flux ZIP.

ref: http://www.splinter.com.au/compressing-using-the-7zip-lzma-algorithm-in/