Ho scritto un pezzo di codice per illustrare il comando standard grep
in Go, ma la velocità è gran lunga alle spalle, qualcuno potrebbe darmi eventuali anticipi? ecco il codice:Potrebbe essere più efficiente in Go?
package main
import (
"bufio"
"fmt"
"log"
"os"
"strings"
"sync"
)
func parse_args() (file, pat string) {
if len(os.Args) < 3 {
log.Fatal("usage: gorep2 <file_name> <pattern>")
}
file = os.Args[1]
pat = os.Args[2]
return
}
func readFile(file string, to chan<- string) {
f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
defer f.Close()
freader := bufio.NewReader(f)
for {
line, er := freader.ReadBytes('\n')
if er == nil {
to <- string(line)
} else {
break
}
}
close(to)
}
func grepLine(pat string, from <-chan string, result chan<- bool) {
var wg sync.WaitGroup
for line := range from {
wg.Add(1)
go func(l string) {
defer wg.Done()
if strings.Contains(l, pat) {
result <- true
}
}(string(line))
}
wg.Wait()
close(result)
}
func main() {
file, pat := parse_args()
text_chan := make(chan string, 10)
result_chan := make(chan bool, 10)
go readFile(file, text_chan)
go grepLine(pat, text_chan, result_chan)
var total uint = 0
for r := range result_chan {
if r == true {
total += 1
}
}
fmt.Printf("Total %d\n", total)
}
Il time
in Go:
>>> time gogrep /var/log/task.log DEBUG
Total 21089
real 0m0.156s
user 0m0.156s
sys 0m0.015s
Il time
in grep
:
>>> time grep DEBUG /var/log/task.log | wc -l
21089
real 0m0.069s
user 0m0.046s
sys 0m0.064s
si riferisce al 'tempo' precedente, Go vince in' sys', ma perde nella parte 'utente', dose che significa che il mio codice mangia il tempo? – askingyj
Sembra che una routine di go per riga (si veda 'grepLine') potrebbe essere un overhead che è possibile rimuovere. Lanciare più linee a ogni routine di routine significherebbe meno tempo a creare routine di go e più tempo a fare ricerche di testo. Se non lo hai già io consiglio Rob Pikes http://talks.golang.org/2012/concurrency.slide#1 – miltonb
Stai leggendo ogni riga più volte: scansione per \ n in bufio, quindi copia i byte in una stringa , quindi eseguire la scansione di DEBUG. Solo quest'ultimo viene eseguito in parallelo nel tuo codice. Mi aspetto che Grep faccia tutto in un solo passaggio. –