从切片中删除元素 - 关于优化的说明

问题描述 投票:0回答:1

我一直在寻找一种从 go 中的切片中删除元素的方法,我基本上遇到了两种方法,

1:

s = append(s[:i], s[i+1:]...)

2:

s[i], s = s[len(s)-1], s[:len(s)-1]

版本 2 被认为更快。

我做了一些基准测试,结果我不太明白:

1:

BenchmarkSliceOrder-12          1000000000               0.0001861 ns/op

2:

BenchmarkSliceNoOrder-12        1000000000               0.0001618 ns/op

这表明它没有真正的区别。 这里需要注意的是,要删除的元素的索引是在切片的整个长度上随机选择的 (

i := rand.Intn(limit)
)。我还发现有一些特定的指数确实会产生影响,但最多为 2。

由于我认为版本 1 在索引较小时涉及更多复制,因此我又进行了两次测试:

i = 2, limit 100000

BenchmarkSliceOrder-12          1000000000               0.008157 ns/op
BenchmarkSliceNoOrder-12        1000000000               0.01165 ns/op

i = limit - 2, limit 100000

BenchmarkSliceOrder-12          1000000000               0.01550 ns/op
BenchmarkSliceNoOrder-12        1000000000               0.01599 ns/op

那么 Go 中的切片有什么用呢?我们不应该担心优化还是什么吗?

我的参考代码:

var limit int = 100000

func BenchmarkSliceOrder(b *testing.B) {
    s := make([]string, limit)
    for i := 0; i < limit; i++ {
        s[i] = fmt.Sprintf("string%d", i)
    }
    //i := rand.Intn(limit)
    i := limit / 2
    s = append(s[:i], s[i+1:]...)
}

func BenchmarkSliceNoOrder(b *testing.B) {
    s := make([]string, limit)
    for i := 0; i < limit; i++ {
        s[i] = fmt.Sprintf("string%d", i)
    }
    //i := rand.Intn(limit)
    i := limit / 2
    s[i] = s[len(s)-1]
    s = s[:len(s)-1]
}
go optimization slice
1个回答
0
投票

正如JimB正确指出的那样,你的基准是不正确的。

尝试类似的事情

package main

import (
    "testing"
)

const (
    length = 1_000
    remove = 500
)

func BenchmarkSliceOrder(b *testing.B) {
    var a [length]int

    for range b.N {
        s := a[:]
        s = append(s[:remove], s[remove+1:]...)
        _ = s
    }
}

func BenchmarkSliceNoOrder(b *testing.B) {
    var a [length]int

    for range b.N {
        s := a[:]
        s[remove] = s[len(s)-1]
        s = s[:len(s)-1]
        _ = s
    }
}

请注意,这是一个微观基准测试,其结果取决于许多因素,例如 CPU 缓存、RAM 速度等。

我不会仅仅因为你在机器上看到一些数字就假设一种方法更快,请参见例如“如何在 Go 中编写准确的基准”

    对微基准做出错误的假设
  • 不小心编译器优化
  • 被观察者效应愚弄
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.