2016-03-25 9 views
3

私は新しい学年のSWEラーニング・ゴー(と愛する)です。GoLang:ゴルーチンでbz2を解凍し、他のゴルーチンで消化する

私はウィキペディアのダンプファイル用のパーサーを構築しています。基本的には巨大なbzip2圧縮XMLファイル(〜50GB非圧縮)です。

私はストリーミングの解凍と解析の両方を行いたいですが、それは十分に簡単です。解凍のために、私が行います。その後、

inputFilePath := flag.Arg(0) inputReader := bzip2.NewReader(inputFile)

そしてXMLパーサーにリーダーを渡す:

decoder := xml.NewDecoder(inputFile)

しかし、伸長及び解析の両方が高価な操作なので、私が持っているしたいと思います追加のコアを使用するために、別々のGoルーチンで実行されます。私はGoでこれをどうやってやりますか?

私が考えることができるのは、ファイルをchan []バイトでラップし、io.Readerインターフェイスを実装することだけです。しかし、私はそこに構築された方法(およびクリーナー)があると推測します。

このようなことをしたことがありますか?

ありがとうございます! マヌエル

答えて

2

あなたはパイプに解凍されたデータをプッシュするio.Copyを使用し、その後、io.Pipeを使用し、他のゴルーチンでそれを読むことができます:

package main 

import (
    "bytes" 
    "encoding/json" 
    "fmt" 
    "io" 
    "sync" 
) 

func main() { 

    rawJson := []byte(`{ 
      "Foo": { 
       "Bar": "Baz" 
      } 
     }`) 

    bzip2Reader := bytes.NewReader(rawJson) // this stands in for the bzip2.NewReader 

    var wg sync.WaitGroup 
    wg.Add(2) 

    r, w := io.Pipe() 

    go func() { 
     // write everything into the pipe. Decompression happens in this goroutine. 
     io.Copy(w, bzip2Reader) 
     w.Close() 
     wg.Done() 
    }() 

    decoder := json.NewDecoder(r) 

    go func() { 
     for { 
      t, err := decoder.Token() 
      if err != nil { 
       break 
      } 
      fmt.Println(t) 
     } 
     wg.Done() 
    }() 

    wg.Wait() 
} 

http://play.golang.org/p/fXLnfnaWYA

+1

これは私が必要なものを正確にです、ありがとう!残念ながら、stardard lib bzip2デコンプレッサの性能はあまり良くないと思われるので、依然として制限要因です。 私はこの圧縮機に切り替えるかもしれません:https://godoc.org/github.com/dsnet/compress/bzip2 しかし、それはまだpbzip2のようなものより約33%遅いです。 –

+0

最後にスピードアップしたのはどれくらいですか、@ManuelMenzella?私はこのコードの外観が好きです - それはうまくいくようですが、私のテストでは、シングルスレッド(67秒と72秒の1Mレコード)を行うよりもほんの僅かしかありません。どのようなアイデアが私は間違っている可能性がある、@ user1431317? – EM0

+0

おそらく、bzip2圧縮解除がデータをどれくらい速く送ることができるかによって制限されているかもしれません。また、xmlデコードではCPUの消費量がそれほど多くはありません。 io.Copyでは片方または両方がio.Reader/io.Writerの場合に最適化されていますが、パイプにはおそらくオーバーヘッドが追加されます。それは、小さな一時的なバッファをたくさん割り当てている可能性があり、それはあまりにも多くのゴミを引き起こしている。バッファリングされた読者や作家が役に立つかもしれない。あなたはアプリをプロファイルする必要があります(cpuとmemの両方のプロファイル - memプロファイルは不必要な割り当てをたくさん見つけるのに役立ちます)。 – user1431317

関連する問題