2016-03-25 10 views
3

Yeni-grad SWE öğrenim Go (ve sevgiyim).GoLang: bz2'yi goroutin üzerinde sıkıştırın, diğer goroutini tüketin

Vikipedi dökümü dosyaları için bir ayrıştırıcı yapıyorum - temel olarak büyük bir bzip2 sıkıştırılmış XML dosyası (sıkıştırılmamış ~ 50 GB).

Hem akıtma dekompresyonunu hem de ayrıştırma işlemini yapmak istiyorum. dekomprasyonu ve ayrıştırma hem pahalı operasyonlar olduğundan, ben istiyorum, Ancak

decoder := xml.NewDecoder(inputFile)

:

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

Sonra XML ayrıştırıcı okuyucuyu geçmesi: dekompresyon için, evet Ek çekirdekten faydalanmak için ayrı Go rutinleri üzerinde çalışırlar. Bunu Go’da yapmayı nasıl yaparım?

Düşünebildiğim tek şey, dosyayı bir [] baytında sarmalamak ve io.Reader arabirimini uygulamaktır, ancak bunu yapmanın yerleşik bir yolu (ve daha temiz) olabileceğini varsayar.

Hiç kimse böyle bir şey yaptı mı?

Teşekkürler! Manuel

cevap

2

Sen boruya sıkıştırılmış veriyi itmek için io.Copy kullanmak, sonra io.Pipe kullanın ve başka goroutine okuyabilirsiniz:

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

Bu ihtiyacım tam olarak ne, teşekkürler! Ne yazık ki, stardard lib bzip2 açıcının performansının büyük olmadığı görünüyor, bu yüzden hala sınırlayıcı bir faktör. Bu kompresöre geçiş yapabilirim: https://godoc.org/github.com/dsnet/compress/bzip2 Bununla birlikte, pbzip2 gibi bir şeyden yaklaşık% 33 daha yavaştır. –

+0

Sonunda ne kadar hız kazantınız, @ManuelMenzella? Bu kodun görünüşünü beğendim - işe yarayacak gibi görünüyor, fakat benim testlerimde tek iplikçik herşeyi yapmaktan sadece çok daha hızlı (1 saniyede 72 saniyede 72 saniye). Ne yapıyorum diye bir fikrim var, @ kullanıcı1431317? – EM0

+0

Belki de bzip2 dekompresyonunun verileri ne kadar hızlı besleyebildiğini ve xml kod çözmenin bu kadar cpu gücüne sahip olmadığından dolayı hala sınırlıdır. Boru bir veya iki ucu io.Reader/io.Writer olduğunda io.Copy için optimizasyonları olmasına rağmen, muhtemelen, bazı yük ekler. Çok sayıda küçük geçici arabellek tahsis etmesi ve bunun çok fazla çöplüğe neden olması mümkündür. Belki bir tamponlu okuyucu veya yazar yardımcı olabilir. Uygulamanızı profillemelisiniz (hem cpu hem de mem profili - mem profili çok fazla gereksiz ayırma bulmanıza yardımcı olabilir). – user1431317