5

バックエンド 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.GetResponseStream
60 秒全体が、応答ストリームを MemoryStream にロードするために費やされます。そこにあると、GZipStream への呼び出しは迅速です。
編集 4

HttpWebRequest.AutomaticDecompression を使用すると同じパフォーマンスの問題が発生することがわかったので、この質問を閉じます。

4

4 に答える 4

1

DotNetZipには、System.IO.Compression.GZipStreamのドロップイン置換として使用できるGZipStreamクラスがあります。

DotNetZipは無料です。

注意:GZipStreamのみを実行している場合は、Ionic.Zip.dllではなくIonic.Zlib.dllが必要です。

于 2009-10-05T20:04:45.520 に答える
1

最初にデータを MemoryStream にロードしてから、MemoryStream を解凍してみてください...

于 2009-10-05T19:55:24.307 に答える
0

質問に直接答えないで申し訳ありませんが、SharpZipはもう見ましたか?Gzipよりもはるかに使いやすいことがわかりました。現在の問題を解決するのに問題がある場合は、おそらくそれがタスクをよりよく実行するでしょう。

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

于 2009-10-05T20:01:52.377 に答える
0

7Zip はその API をプレーンな C# で公開しているように見えることを C# ユーザーに通知するためだけに、この話題に 3 セントを投じます。皆さんは 7Zip ツールをよく知っていると思いますが、少なくとも私にとっては、その API がどれほどうまく設計されているかどうかに関係なく、ZIP ファイル/ストリームの処理のパフォーマンスが向上するという点で大きな助けになることを知っています。

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

于 2012-08-23T09:47:59.067 に答える