0

zipファイルから情報を抽出する方法を作っています。すべてのzipファイルには1つのテキストファイルのみが含まれます。メソッドが文字列配列を返すことを目的としています。

dotnetzipを使用していますが、ひどいパフォーマンスが発生しています。各ステップのパフォーマンスをベンチマークしようとしましたが、すべてのステップでパフォーマンスが遅いようです。

c#コードは次のとおりです。

        public string[] LoadZipFile(string FileName)
    {
        string[] lines = { };
        int start = System.Environment.TickCount;
        this.richTextBoxLOG.AppendText("Reading " + FileName + "... ");
        try
        {
            int nstart;

            nstart = System.Environment.TickCount;       
            ZipFile zip = ZipFile.Read(FileName);
            this.richTextBoxLOG.AppendText(String.Format("ZipFile ({0}ms)\n", System.Environment.TickCount - nstart));

            nstart = System.Environment.TickCount;
            MemoryStream ms = new MemoryStream();
            this.richTextBoxLOG.AppendText(String.Format("Memorystream ({0}ms)\n", System.Environment.TickCount - nstart));

            nstart = System.Environment.TickCount;
            zip[0].Extract(ms);
            this.richTextBoxLOG.AppendText(String.Format("Extract ({0}ms)\n", System.Environment.TickCount - nstart));

            nstart = System.Environment.TickCount;
            string filecontents = string.Empty;
            using (var reader = new StreamReader(ms)) 
            { 
                reader.BaseStream.Seek(0, SeekOrigin.Begin); 
                filecontents = reader.ReadToEnd().ToString(); 
            }
            this.richTextBoxLOG.AppendText(String.Format("Read ({0}ms)\n", System.Environment.TickCount - nstart));

            nstart = System.Environment.TickCount;
            lines = filecontents.Replace("\r\n", "\n").Split("\n".ToCharArray());
            this.richTextBoxLOG.AppendText(String.Format("SplitLines ({0}ms)\n", System.Environment.TickCount - nstart));
        }
        catch (IOException ex)
        {
            this.richTextBoxLOG.AppendText(ex.Message+ "\n"); 

        }
        int slut = System.Environment.TickCount;
        this.richTextBoxLOG.AppendText(String.Format("Done ({0}ms)\n", slut - start)); 
        return (lines);

例として、次の出力を取得します。

xxxx.zipを読み取っています...ZipFile(0ms)メモリストリーム(0ms)抽出(234ms)読み取り(78ms)SplitLines(187ms)完了(514ms)

合計514ミリ秒。このコードを使用してPython2.6で同じ操作を実行すると、次のようになります。

def ReadZip(File):
z = zipfile.ZipFile(File, "r")
name =z.namelist()[0]
return(z.read(name).split('\r\n'))

わずか89ミリ秒で実行されます。パフォーマンスを改善する方法についてのアイデアは大歓迎です。

4

2 に答える 2

1

提案をありがとう。いくつかの方法でコードを変更することになります。

  • collection.generic を使用して行を返す
  • streamreader.readline の使用

ロギングと例外処理を削除しても、パフォーマンスはあまり変わりませんでした。私はsharplibsの解凍ライブラリを見ましたが、実装が少し複雑に見え、他の投稿で読むことができたものから、解凍に少し利益があったかもしれません. 現在、約 300ms で実行されています。

        public List<string> LoadZipFile2(string FileName)
    {
        List<string> lines = new List<string>();
        int start = System.Environment.TickCount;
        string debugtext;
        debugtext = "Reading " + FileName + "... ";
        this.richTextBoxLOG.AppendText(debugtext);

        try
        {
            //int nstart = System.Environment.TickCount;
            ZipFile zip = ZipFile.Read(FileName);
           // this.richTextBoxLOG.AppendText(String.Format("ZipFile ({0}ms)\n", System.Environment.TickCount - nstart));

            //nstart = System.Environment.TickCount;
            MemoryStream ms = new MemoryStream();
            //this.richTextBoxLOG.AppendText(String.Format("Memorystream ({0}ms)\n", System.Environment.TickCount - nstart));

            //nstart = System.Environment.TickCount;
            zip[0].Extract(ms);
            zip.Dispose();
            //this.richTextBoxLOG.AppendText(String.Format("Extract ({0}ms)\n", System.Environment.TickCount - nstart));

            //nstart = System.Environment.TickCount;
            using (var reader = new StreamReader(ms))
            {
                reader.BaseStream.Seek(0, SeekOrigin.Begin);
                while (reader.Peek() >= 0)
                {
                    lines.Add(reader.ReadLine());
                }
            }
            ;
            //this.richTextBoxLOG.AppendText(String.Format("Read ({0}ms)\n", System.Environment.TickCount - nstart));
        }
        catch (IOException ex)
        {
            this.richTextBoxLOG.AppendText(ex.Message + "\n");
        }
        int slut = System.Environment.TickCount;
        this.richTextBoxLOG.AppendText(String.Format("Done ({0}ms)\n", slut - start));
        return (lines);
于 2012-08-10T06:48:07.087 に答える
1

あなたのコードは同種のものではないため、比較は不公平です。いくつかの重要なポイント:

  • ロギング コードを削除しようとしましたか? 呼び出しは、余分な時間のAppendText一部を担当します。
  • split を呼び出す前にファイル全体の置換を行うと、プロセスのその部分が大幅に遅くなります。\r\n代わりに分割してください。
  • 文字列を返すだけでなく、各行を char 配列に変換します。これにより、動作も遅くなります。
  • 異なる Zip ライブラリを比較して、より高速な解凍方法があるかどうかを確認することをお勧めします。
  • StreamReader.ReadLineストリーム全体を読み取ってから手動で分割するよりも、繰り返し呼び出す方が速い場合があります。

要するに、いくつかの代替方法をプロファイリングする必要があり、真に同等の比較が必要な場合は、中間ロギングに RichTextBox を使用せずにコードの時間を計る必要があります。

于 2012-08-03T11:37:26.193 に答える