为了账号安全,请及时绑定邮箱和手机立即绑定

内置追加与字节。缓冲区写入

内置追加与字节。缓冲区写入

Go
慕标5832272 2022-03-07 22:35:32
在我需要将未知数量的数据添加到一个字节的情况下,比如说在一个循环中,我可以使用内置函数append()或创建一个新函数Buffer并使用该Write()函数。哪种方法最快?
查看完整描述

2 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

这取决于用例。

在这两种情况下都比(样本:1、2、3、4)bytes.Buffer更快。append


使用buf.Write(make([]byte, 16))需要4.6482659s,

使用buf = append(buf, make([]byte, 16)...)需要6.6623811s。


对于样本 5、6:

使用buf = append(buf, byte(i))take 445.0255ms,

Using buf.WriteByte(byte(i))take1.4410824s


并bytes.Buffer使用内置函数copy,速度很快:


// 写入将 p 的内容附加到缓冲区,根据

需要增长缓冲区。返回值n是p的长度;错误总是零。如果

// 缓冲区变得太大,Write 会出现 ErrTooLarge 恐慌。


func (b *Buffer) Write(p []byte) (n int, err error) {

  b.lastRead = opInvalid

  m := b.grow(len(p))

  return copy(b.buf[m:], p), nil

}

bytes.Buffer耗时 4.8892797s,append耗时 7.7514434s


查看这些基准:


1-使用append:


package main


import (

    "fmt"

    "time"

)


func main() {

    buf := []byte{}

    data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}

    t := time.Now()

    for i := 0; i < 100000000; i++ {

        buf = append(buf, data...)

    }

    fmt.Println(time.Since(t))

    fmt.Println(len(buf))

}

输出:


7.7514434s

1600000000

2-使用bytes.Buffer


package main


import (

    "bytes"

    "fmt"

    "time"

)


func main() {

    buf := &bytes.Buffer{}

    data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}

    t := time.Now()

    for i := 0; i < 100000000; i++ {

        buf.Write(data)

    }

    fmt.Println(time.Since(t))

    fmt.Println(buf.Len())

}

输出:


4.8892797s

1600000000

3-bytes.Buffer使用make([]byte, 16):


package main


import (

    "bytes"

    "fmt"

    "time"

)


func main() {

    buf := &bytes.Buffer{}

    t := time.Now()

    for i := 0; i < 100000000; i++ {

        buf.Write(make([]byte, 16))

    }

    fmt.Println(time.Since(t)) // 4.6482659s

    fmt.Println(buf.Len())     //1600000000

}

4-append使用make([]byte, 16):


package main


import (

    "fmt"

    "time"

)


func main() {

    buf := []byte{}

    t := time.Now()

    for i := 0; i < 100000000; i++ {

        buf = append(buf, make([]byte, 16)...)

    }

    fmt.Println(time.Since(t)) // 6.6623811s

    fmt.Println(len(buf))      // 1600000000

}

5- 使用buf = append(buf, byte(i))需要445.0255ms:


package main


import (

    "fmt"

    "time"

)


func main() {

    buf := []byte{}

    t := time.Now()

    for i := 0; i < 100000000; i++ {

        buf = append(buf, byte(i))

    }

    fmt.Println(time.Since(t)) // 445.0255ms

    fmt.Println(len(buf))      // 100000000

}

6- 使用buf.WriteByte(byte(i))需要1.4410824s:


package main


import (

    "bytes"

    "fmt"

    "time"

)


func main() {

    buf := &bytes.Buffer{}


    t := time.Now()

    for i := 0; i < 100000000; i++ {

        buf.WriteByte(byte(i))

    }

    fmt.Println(time.Since(t)) // 1.4410824s

    fmt.Println(buf.Len())     // 100000000

}


查看完整回答
反对 回复 2022-03-07
?
慕姐4208626

TA贡献1852条经验 获得超7个赞

使用内置函数append更快,如以下基准所示:


package x


import (

    "bytes"

    "math/rand"

    "testing"

    "time"

)


var startSeed = time.Now().UnixNano()


func randomSlice() []byte {

    return make([]byte, 0, rand.Intn(1<<10))

}


func BenchmarkAppend(b *testing.B) {

    rand.Seed(startSeed)

    b.ResetTimer()

    var all []byte


    for i := 0; i < b.N; i++ {

        all = append(all, randomSlice()...)

    }

}


func BenchmarkBufferWrite(b *testing.B) {

    rand.Seed(startSeed)

    b.ResetTimer()

    var buff bytes.Buffer

    for i := 0; i < b.N; i++ {

        buff.Write(randomSlice())

    }

    all := buff.Bytes()

    _ = all

}

结果:


BenchmarkAppend-4           10000000           206 ns/op         540 B/op          0 allocs/op

BenchmarkBufferWrite-4      10000000           214 ns/op         540 B/op          0 allocs/op



查看完整回答
反对 回复 2022-03-07
  • 2 回答
  • 0 关注
  • 124 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信