Ich schrieb ein Stück Code, um den Standardbefehl grep
in Go zu veranschaulichen, aber die Geschwindigkeit ist weit dahinter, konnte mir jemand irgendwelche Fortschritte geben? hier ist der Code:Könnte das in Go effizienter sein?
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)
}
Die time
in Go:
>>> time gogrep /var/log/task.log DEBUG
Total 21089
real 0m0.156s
user 0m0.156s
sys 0m0.015s
Die time
in grep
:
>>> time grep DEBUG /var/log/task.log | wc -l
21089
real 0m0.069s
user 0m0.046s
sys 0m0.064s
beziehen sich auf die "Zeit" oben, Go gewinnt in 'sys', aber verlieren in den' user' Teil, Dosis, die meine Code essen die Zeit bedeuten? – askingyj
Es scheint, dass eine Go-Routine pro Zeile (siehe "grepLine") ein Overhead sein kann, den Sie entfernen können. Mehrere Zeilen bei jeder Routine zu werfen, würde weniger Zeit für die Erstellung von Routinen und mehr Zeit für Textsuchen bedeuten. Wenn Sie nicht bereits Ich empfehle Rob Pikes http://talks.golang.org/2012/concurrency.slide#1 – miltonb
Sie lesen jede Zeile mehrmals: Scannen für \ n in Bufio, dann kopieren Sie die Bytes in eine Zeichenfolge , dann nach DEBUG scannen. Nur letzteres wird in Ihrem Code parallel ausgeführt. Ich würde erwarten, Grep macht alles in einem einzigen Durchgang. –