Самое простое решение с циклом будет выглядеть так:
func memsetLoop(a []int, v int) {
for i := range a {
a[i] = v
}
}
В стандартной библиотеке нет поддержки memset
, но мы можем использовать встроенную высокооптимизированную copy()
. .
С повторяющимся copy()
Мы можем установить первый элемент вручную и начать копирование уже установленной части в неустановленную с помощью copy()
; где уже заданная часть с каждым разом становится все больше и больше (удваивается), поэтому количество итераций равно log(n)
:
func memsetRepeat(a []int, v int) {
if len(a) == 0 {
return
}
a[0] = v
for bp := 1; bp < len(a); bp *= 2 {
copy(a[bp:], a[:bp])
}
}
Это решение было вдохновлено реализацией bytes.Repeat()
. Если вы просто хотите создать новый []byte
, заполненный теми же значениями, вы можете использовать функцию bytes.Repeat()
. Вы не можете использовать это для существующего фрагмента или фрагментов, отличных от []byte
, для этого вы можете использовать представленный memsetRepeat()
.
В случае небольших фрагментов memsetRepeat()
может быть медленнее, чем memsetLoop()
(но в случае небольших фрагментов это не имеет большого значения, он будет работать в одно мгновение).
Из-за использования быстрого copy()
, memsetRepeat()
будет намного быстрее, если количество элементов увеличится.
Сравнение этих двух решений:
var a = make([]int, 1000) // Size will vary
func BenchmarkLoop(b *testing.B) {
for i := 0; i < b.N; i++ {
memsetLoop(a, 10)
}
}
func BenchmarkRepeat(b *testing.B) {
for i := 0; i < b.N; i++ {
memsetRepeat(a, 11)
}
}
Сравнительные результаты
100 элементов: примерно в 1,15 раза быстрее
BenchmarkLoop 20000000 81.6 ns/op
BenchmarkRepeat 20000000 71.0 ns/op
1000 элементов: примерно в 2,5 раза быстрее
BenchmarkLoop 2000000 706 ns/op
BenchmarkRepeat 5000000 279 ns/op
10 000 элементов: примерно в 2 раза быстрее
BenchmarkLoop 200000 7029 ns/op
BenchmarkRepeat 500000 3544 ns/op
100 000 элементов: примерно в 1,5 раза быстрее
BenchmarkLoop 20000 70671 ns/op
BenchmarkRepeat 30000 45213 ns/op
Наибольший прирост производительности составляет около 3800-4000 элементов, что в примерно в 3,2 раза быстрее.
person
icza
schedule
03.06.2015
runtime.duffzero
с другим значением, кроме0
в АКС. См. также mkduff.go. - person thwd   schedule 03.06.2015memset
также не инициализирует все элементы в1
. - person milleniumbug   schedule 03.06.2015memset
vs цикла? - person Akavall   schedule 03.06.2015