我写了一段代码来说明Go中的标准命令grep
,但速度远远落后于 ,有人可以给我任何进展吗?这里是代码: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)
}
围棋的time
:
>>> time gogrep /var/log/task.log DEBUG
Total 21089
real 0m0.156s
user 0m0.156s
sys 0m0.015s
的time
在grep
:
>>> time grep DEBUG /var/log/task.log | wc -l
21089
real 0m0.069s
user 0m0.046s
sys 0m0.064s
参考上面的'time',Go在'sys'中获胜,但在'user'部分丢失,这意味着我的代码吃了这个时间? – askingyj 2014-11-03 08:56:18
看来,每行一个去例行程序(请参阅'grepLine')可能是您可以删除的开销。在每次执行例程时投掷多行代码意味着创建执行例程的时间更少,并且执行文本搜索的时间更多。如果您还没有推荐Rob Pikes http://talks.golang.org/2012/concurrency.slide#1 – miltonb 2014-11-03 09:32:10
您正在多次阅读每一行:在bufio中扫描\ n,然后将这些字节复制到一个字符串中,然后扫描DEBUG。只有后者在您的代码中并行执行。我希望grep能够一次完成所有的事情。 – 2014-11-03 09:40:07