我需要阅读大约 600 个 pcap 文件,每个文件大约 100MB。我使用 gopacket 加载 pcap 文件,并检查它。
Case1:使用 1 个例程检查。
案例 2:使用 40 个例程进行检查。
而且我发现case1和case2消耗的时间差不多。不同的是case1的cpu使用率只有200%,case2可以达到3000%。我的问题是为什么多个例程不能提高性能? 代码中有一些注释,希望对您有所帮助。
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
"sync"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
func main() {
var wg sync.WaitGroup
var dir = flag.String("dir", "../pcap", "input dir")
var threadNum = flag.Int("threads", 40, "input thread number")
flag.Parse()
fmt.Printf("dir=%s, threadNum=%d\n", *dir, *threadNum)
pcapFileList, err := ioutil.ReadDir(*dir)
if err != nil {
panic(err)
}
log.Printf("start. file number=%d.", len(pcapFileList))
fileNumPerRoutine := len(pcapFileList) / *threadNum
lastFileNum := len(pcapFileList) % *threadNum
// split files to different routine
// each routine only process files which belong to itself
if fileNumPerRoutine > 0 {
for i := 0; i < *threadNum; i++ {
start := fileNumPerRoutine * i
end := fileNumPerRoutine * (i + 1)
if lastFileNum > 0 && i == (*threadNum-1) {
end = len(pcapFileList)
}
// fmt.Printf("start=%d, end=%d\n", start, end)
wg.Add(1)
go checkPcapRoutine(i, &wg, dir, pcapFileList[start:end])
}
}
wg.Wait()
log.Printf("end.")
}
func checkPcapRoutine(id int, wg *sync.WaitGroup, dir *string, pcapFileList []os.FileInfo) {
defer wg.Done()
for _, p := range pcapFileList {
if !strings.HasSuffix(p.Name(), "pcap") {
continue
}
pcapFile := *dir + "/" + p.Name()
log.Printf("checkPcapRoutine(%d): process %s.", id, pcapFile)
handle, err := pcap.OpenOffline(pcapFile)
if err != nil {
log.Printf("error=%s.", err)
return
}
defer handle.Close()
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
// Per my test, if I don't parse packets, it is very fast, even use only 1 routine, so IO should not be the bottleneck.
// What puzzles me is that every routine has their own packets, each routine is independent, but it still seems to be processed serially.
// This is the first time I use gopacket, maybe used wrong parameter?
for packet := range packetSource.Packets() {
gtpLayer := packet.Layer(layers.LayerTypeGTPv1U)
lays := packet.Layers()
outerIPLayer := lays[1]
outerIP := outerIPLayer.(*layers.IPv4)
if gtpLayer == nil && (outerIP.Flags&layers.IPv4MoreFragments != 0) && outerIP.Length < 56 {
log.Panicf("file:%s, idx=%d may leakage.", pcapFile, j+1)
break
}
}
}
}