1 回答
TA贡献1831条经验 获得超10个赞
更换
split_line := strings.Fields(line)
和
split_line := strings.SplitN(line, " ", 11)
在1M行随机生成的文件中,模仿您上面提供的格式,速度提高了约4倍:
strings.Fields版本:在4.232525975s中完成
strings.SplitN版本:在1.111450755s中完成
效率的提高部分来自于避免在分割持续时间后解析和分割输入线,但大部分来自于SplitN中更简单的分割逻辑。即使拆分所有字符串,也不会比在持续时间之后停止花费很长时间。使用:
split_line := strings.SplitN(line, " ", -1)
1.554971313s完成
SplitN和字段不相同。字段假定标记由1个或多个空格字符限制,其中SplitN将标记视为由分隔符字符串限制的任何字符。如果输入的标记之间有多个空格,则split_line将为每对空格包含空标记。
排序和计算中位数不会增加太多时间。为了方便起见,我将代码更改为使用float64而不是float32。这是完整的程序:
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
"time"
)
// SortKeys returns a sorted list of key values from a map[int][]float64.
func sortKeys(items map[int][]float64) []int {
keys := make([]int, len(items))
i := 0
for k, _ := range items {
keys[i] = k
i++
}
sort.Ints(keys)
return keys
}
// Median calculates the median value of an unsorted slice of float64.
func median(d []float64) (m float64) {
sort.Float64s(d)
length := len(d)
if length%2 == 1 {
m = d[length/2]
} else {
m = (d[length/2] + d[length/2-1]) / 2
}
return m
}
func main() {
data := make(map[int][]float64)
infile, err := os.Open("sample.log")
defer infile.Close()
if err != nil {
panic(err)
}
reader := bufio.NewReaderSize(infile, 256*1024)
s := time.Now()
for {
line, err := reader.ReadString('\n')
if len(line) == 0 {
break
}
if err != nil {
panic(err)
}
split_line := strings.SplitN(line, " ", 11)
num_packets, err := strconv.ParseFloat(split_line[7], 32)
if err != nil {
panic(err)
}
duration, err := strconv.ParseFloat(split_line[9], 32)
if err != nil {
panic(err)
}
pkts := int(num_packets)
data[pkts] = append(data[pkts], duration)
}
for _, k := range sortKeys(data) {
fmt.Printf("pkts: %d, median: %f\n", k, median(data[k]))
}
fmt.Println("\nCompleted in ", time.Since(s))
}
并输出:
pkts: 0, median: 0.498146
pkts: 1, median: 0.511023
pkts: 2, median: 0.501408
...
pkts: 99, median: 0.501517
pkts: 100, median: 0.491499
Completed in 1.497052072s
- 1 回答
- 0 关注
- 258 浏览
添加回答
举报