3 回答

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超6個(gè)贊
我使用和來(lái)提高性能。當(dāng)您處理小型shell腳本時(shí),我認(rèn)為一次讀取所有文件不會(huì)對(duì)內(nèi)存造成壓力(我使用了)。我還只分配了一次,以便為減少分配提供足夠的存儲(chǔ)空間。strings.Builder
ioutil.ReadAll
ioutil.ReadAll
strings.Builder
快速:更快的實(shí)施
doSlow:實(shí)現(xiàn)速度較慢(您最初執(zhí)行的操作)
現(xiàn)在,讓我們看一下基準(zhǔn)測(cè)試結(jié)果:
goos: darwin
goarch: amd64
pkg: test
cpu: Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz
BenchmarkDoFast-8 342602 3334 ns/op 1280 B/op 3 allocs/op
BenchmarkDoSlow-8 258896 4408 ns/op 4624 B/op 8 allocs/op
PASS
ok test 2.477s
我們可以看到,這不僅更快,而且只會(huì)減少分配。測(cè)量的指標(biāo)越低越好。doFast
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
"strings"
)
func open(filename string) (*os.File, error) {
return os.Open(filename)
}
func main() {
fd, err := open("test.sh")
if err != nil {
panic(err)
}
defer fd.Close()
outputA, err := doFast(fd)
if err != nil {
panic(err)
}
fd.Seek(0, 0)
outputB, err := doSlow(fd)
if err != nil {
panic(err)
}
fmt.Println(outputA)
fmt.Println(outputB)
}
func doFast(fd *os.File) (string, error) {
b, err := ioutil.ReadAll(fd)
if err != nil {
return "", err
}
var res strings.Builder
res.Grow(len(b))
bLines := bytes.Split(b, []byte("\n"))
for i := range bLines {
switch {
case len(bLines[i]) == 0 || bLines[i][0] == '#':
case bLines[i][len(bLines[i])-1] != ';':
res.Write(bLines[i])
res.WriteString("; ")
default:
res.Write(bLines[i])
res.WriteByte(' ')
}
}
return res.String(), nil
}
func doSlow(fd *os.File) (string, error) {
var a strings.Builder
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
lines := scanner.Text()
switch {
case lines == "" || lines[:1] == "#":
continue
case lines[len(lines)-1:] != ";":
a.WriteString(lines + "; ")
default:
a.WriteString(lines + " ")
}
}
return a.String(), nil
}
注意:我沒有使用;是必需的嗎?bufio.NewScanner

TA貢獻(xiàn)1847條經(jīng)驗(yàn) 獲得超11個(gè)贊
使用掃描儀是可行的。字節(jié)()。代碼如下:
func main() {
file, err := os.Open("./script.sh")
if err != nil {
log.Fatalln(err)
}
defer file.Close()
var a strings.Builder
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines := scanner.Bytes()
switch {
case len(lines) == 0 || lines[0] == '#':
continue
case lines[len(lines)-1] != ';':
a.Write(lines)
a.WriteString("; ")
default:
a.Write(lines)
a.WriteByte(' ')
}
}
fmt.Println(a.String())
}
此程序避免了掃描儀中的字符串分配。文本()。如果程序速度受到 I/O 的限制,則程序在實(shí)踐中可能不會(huì)更快。
在操場(chǎng)上奔跑。
如果您的目標(biāo)是將結(jié)果寫入標(biāo)準(zhǔn),則寫入 bufio。編寫器而不是字符串。建筑工人。此更改將替換字符串中的一個(gè)或多個(gè)分配。在布菲奧中具有單個(gè)分配的建筑商。作家。
func main() {
file, err := os.Open("./script.sh")
if err != nil {
log.Fatalln(err)
}
defer file.Close()
a := bufio.NewWriter(os.Stdout)
defer a.Flush() // flush buffered data on return from main.
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines := scanner.Bytes()
switch {
case len(lines) == 0 || lines[0] == '#':
continue
case lines[len(lines)-1] != ';':
a.Write(lines)
a.WriteString("; ")
default:
a.Write(lines)
a.WriteByte(' ')
}
}
}
在操場(chǎng)上奔跑。
額外改進(jìn):用于處理 a 之前和之后的空格lines := bytes.TrimSpace(scanner.Bytes())'#'';'

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超10個(gè)贊
您也可以通過緩沖輸出來(lái)提高性能。
func main() {
output := bufio.NewWriter(os.Stdout)
// instead of Printf, use
fmt.Fprintf(output, "%s\n", a)
}
- 3 回答
- 0 關(guān)注
- 88 瀏覽
添加回答
舉報(bào)