首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用pprof优化CSV加载器?

如何使用pprof优化CSV加载器?
EN

Stack Overflow用户
提问于 2018-10-09 18:27:37
回答 1查看 89关注 0票数 1

我正在尝试优化CSV加载过程,基本上就是在一个大的CSV文件(我的实验是+4 4GB 31033993条记录)中执行正则表达式搜索。我设法构建了一个多处理逻辑来读取CSV,但是当我使用pprof分析CPU配置文件时,我认为我的正则表达式搜索并没有得到优化。你能帮我改进这段代码,让它能更快地读取CSV吗?

到目前为止,我的代码如下:

代码语言:javascript
复制
package main

import (
    "bufio"
    "flag"
    "fmt"
    "log"
    "os"
    "regexp"
    "runtime"
    "runtime/pprof"
    "strings"
    "sync"
)

func processFile(path string) [][]string {
    file, err := os.Open(path)
    if err != nil {
        log.Println("Error:", err)
    }
    var pattern = regexp.MustCompile(`^.*foo.*$`)
    numCPU := runtime.NumCPU()
    jobs := make(chan string, numCPU+1)

    fmt.Printf("Strategy: Parallel, %d Workers ...\n", numCPU)

    results := make(chan []string)
    wg := new(sync.WaitGroup)
    for w := 1; w <= numCPU; w++ {
        wg.Add(1)
        go parseRecord(jobs, results, wg, pattern)
    }
    go func() {
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
            jobs <- scanner.Text()
        }
        close(jobs)
    }()

    go func() {
        wg.Wait()
        close(results)
    }()

    lines := [][]string{}
    for line := range results {
        lines = append(lines, line)
    }

    return lines
}

func parseRecord(jobs <-chan string, results chan<- []string, wg *sync.WaitGroup, pattern *regexp.Regexp) {
    defer wg.Done()
    for j := range jobs {
        if pattern.MatchString(j) {
            x := strings.Split(string(j), "\n")
            results <- x
        }

    }
}

func split(r rune) bool {
    return r == ','
}

func main() {
    f, err := os.Create("perf.data")
    if err != nil {
        log.Fatal(err)
    }
    pprof.StartCPUProfile(f)
    defer pprof.StopCPUProfile()

    pathFlag := flag.String("file", "", `The CSV file to operate on.`)
    flag.Parse()
    lines := processFile(*pathFlag)
    fmt.Println("loaded", len(lines), "records")
}

当我在没有任何正则表达式约束的情况下处理文件时,我得到了一个合理的计算时间(我只是将解析后的字符串加载到2D数组中,而没有任何pattern.MatchString())

Strategy: Parallel, 8 Workers ... loaded 31033993 records 2018/10/09 11:46:38 readLines took 30.611246035s

相反,当我使用正则表达式约束运行上面的代码时,我得到了以下结果:

Strategy: Parallel, 8 Workers ... loaded 143090 records 2018/10/09 12:04:32 readLines took 1m24.029830907s

EN

回答 1

Stack Overflow用户

发布于 2018-10-09 20:54:35

在MatchString引擎中,regexp会查找字符串上的任何匹配项,这样就可以去掉锚点和两端的通配符,这通常很慢

在go 1.10上显示这一点的示例

代码语言:javascript
复制
package reggie

import (
        "regexp"
        "testing"
)

var pattern = regexp.MustCompile(`^.*foo.*$`)
var pattern2 = regexp.MustCompile(`foo`)

func BenchmarkRegexp(b *testing.B) {
        for i := 0; i < b.N; i++ {
                pattern.MatchString("youfathairyfoobar")
        }
}

func BenchmarkRegexp2(b *testing.B) {
        for i := 0; i < b.N; i++ {
                pattern2.MatchString("youfathairyfoobar")
        }
}
$ go test -bench=.
goos: darwin
goarch: amd64
BenchmarkRegexp-4        3000000           471 ns/op
BenchmarkRegexp2-4      20000000           101 ns/op
PASS
ok      _/Users/jsandrew/wip/src/reg    4.031s
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52718808

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档