首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >清除截断指针的方法是更快还是更慢?

问清除截断指针的方法是更快还是更慢?
EN

Stack Overflow用户
提问于 2020-05-18 19:59:05
回答 1查看 84关注 0票数 1

在我最近读到的一个truncate实现中,作者使用以下方法来清除被截断的项:

代码语言:javascript
复制
var nilItems    = make(items, 16)

func (s *items) truncate(index int) {
    var toClear items
    *s, toClear = (*s)[:index], (*s)[index:]
    for len(toClear) > 0 {
        toClear = toClear[copy(toClear, nilItems):]
    }
}

当我需要清除不需要的项目时,我会遍历切片并将项目逐个设置为nil。

我设置了一个简单的benchmark,看起来for循环方式更快。

我想知道批量清除copy有什么好处。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-18 21:04:00

正如@MartinGallagher提到的,你的循环被编译器识别并优化了,而copy()版本做了“太多的东西”,并且没有优化。

如果您更改示例以填充非nil指针值,您将看到循环版本落后。另外,不要在基准循环内部分配(make()),在外部分配,并使用b.ResetTimer()排除该时间。

你也有一个非常小的切片,如果你增加它的大小,差异会更明显:

代码语言:javascript
复制
var x = new(int)

func BenchmarkSetNilOneByOne(b *testing.B) {
    nums := make([]*int, 12800)
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        for i := range nums {
            nums[i] = x
        }
    }
}

func BenchmarkSetNilInBulk(b *testing.B) {
    nils := make([]*int, 128)
    for i := range nils {
        nils[i] = x
    }

    orig := make([]*int, 12800)
    var nums []*int
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        nums = orig
        for len(nums) > 0 {
            nums = nums[copy(nums, nils):]
        }
    }
}

基准测试结果:

代码语言:javascript
复制
BenchmarkSetNilOneByOne-4          96571         10626 ns/op
BenchmarkSetNilInBulk-4           266690          4023 ns/op

还要注意,您的“批量”版本还多次将切片标头分配给nums。有一种更快的方法来填充切片:您不需要额外的"nils“切片,只需开始填充切片,您可以将已经填充的部分复制到未填充的部分。这也不需要更改/重新分配给nums切片报头。请参阅Is there analog of memset in go?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61869098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档