Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 清除截断指针的更快或更慢的方法?_Pointers_Go_Slice_Benchmarking_Memset - Fatal编程技术网

Pointers 清除截断指针的更快或更慢的方法?

Pointers 清除截断指针的更快或更慢的方法?,pointers,go,slice,benchmarking,memset,Pointers,Go,Slice,Benchmarking,Memset,在我最近阅读的truncate实现中,作者使用以下方法清除被截断的项: 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, nilI

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

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

我设置了一个简单的循环方式,似乎
for
循环方式更快


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

正如@MartinGallagher所提到的,编译器会识别并优化您的循环,而
copy()
版本做了“太多的事情”,没有优化

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

您还有一个非常小的切片,如果您增加其大小,则差异将更加明显:

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):]
        }
    }
}

还要注意的是,您的“批量”版本还多次将切片头分配给
nums
。有一种更快的方法来填充切片:您不需要额外的“nils”切片,只需开始填充切片,就可以将已填充的部分复制到未填充的部分。这也不需要更改/重新分配到
nums
切片头。请参见

我认为基准测试的结果正好相反。基于拷贝的清除比按循环清除快。
nil
by循环可以利用
运行时。在某些平台上,例如
amd64
,这是
memclr
的专业化,很难被打败。注意,对于值类型,它使用
运行时.memclrNoHeapPointers
(例如
[]int
)。因此,如果我们想将
设置为nil
s,没有什么比编译器优化的
for
循环更好的了,对吗?@satoru目前看来是这样的。您仍然可以尝试答案中提供的解决方案。谢谢。我已经尝试了
字节中使用的算法。重复一下
,速度大约是你答案中的两倍。我已经确认,当赋值为
a[I]=nil
(如果它是值
nil
的变量,则不起作用)时,使用优化的
for
循环会更快。
BenchmarkSetNilOneByOne-4          96571         10626 ns/op
BenchmarkSetNilInBulk-4           266690          4023 ns/op