After some profiling investigations, it looks the following code has not
been optimized yet:
s2 := make([]int, len(s) + len(vs))
copy(s2, s[:k])
copy(s2[k:], vs)
copy(s2[k+len(vs):], s[k:])
Much unnecessary time is consumed on memclrNoHeapPointers.
The one-line implementation does move more memory, but this disadvantage is
compensated by its advantage of spending less time on memclrNoHeapPointers
when N is large.
On Thursday, May 13, 2021 at 4:52:32 AM UTC-4 [email protected] wrote:
>
> package main
>
> import "testing"
>
> const N = 1615119
> // It is strange that if N is large enough,
> // the one line implementations are fast as the others.
> // And if N is odd number, the InsertOneline_Disassemble
> // implementation is about 10% faster than the others.
>
> func init() {
> println("==================== N =", N)
> }
>
> func InsertOneline(s []int, k int, vs ...int) []int {
> return append(s[:k], append(vs, s[k:]...)...)
> }
>
> func InsertOneline_Disassemble(s []int, k int, vs ...int) []int {
> z := append(vs, s[k:]...)
> return append(s[:k], z...)
> }
>
> func InsertVerbose(s []int, k int, vs ...int) []int {
> if n := len(s) + len(vs); n <= cap(s) {
> s2 := s[:n]
> copy(s2[k+len(vs):], s[k:])
> copy(s2[k:], vs)
> return s2
> }
> s2 := make([]int, len(s) + len(vs))
> copy(s2, s[:k])
> copy(s2[k:], vs)
> copy(s2[k+len(vs):], s[k:])
> return s2
> }
>
>
> func InsertVerbose_b(s []int, k int, vs ...int) []int {
> if n := len(s) + len(vs); n <= cap(s) {
> s2 := s[:n]
> copy(s2[k+len(vs):], s[k:])
> copy(s2[k:], vs)
> return s2
> }
> s2 := make([]int, 0, len(s) + len(vs))
> s2 = append(s2, s[:k]...)
> s2 = append(s2, vs...)
> s2 = append(s2, s[k:]...)
> return s2
> }
>
> func InsertVerbose_c(s []int, k int, vs ...int) []int {
> if n := len(s) + len(vs); n <= cap(s) {
> s2 := s[:n]
> copy(s2[k+len(vs):], s[k:])
> copy(s2[k:], vs)
> return s2
> }
> s2 := append([]int(nil), make([]int, len(s) + len(vs))...)[:0]
> s2 = append(s2, s[:k]...)
> s2 = append(s2, vs...)
> s2 = append(s2, s[k:]...)
> return s2
> }
>
> var s1 []int
> func Benchmark_InsertOneline(b *testing.B) {
> var x = make([]int, N)
> var y = make([]int, N/2)
> var k = N/5
> b.ResetTimer()
> for i := 0; i < b.N; i++ {
> s1 = InsertOneline(x, k, y...)
> }
> }
>
> var s1b []int
> func Benchmark_InsertOneline_Disassemble(b *testing.B) {
> var x = make([]int, N)
> var y = make([]int, N/2)
> var k = N/2
> b.ResetTimer()
> for i := 0; i < b.N; i++ {
> s1b = InsertOneline_Disassemble(x, k, y...)
> }
> }
>
> var s2 []int
> func Benchmark_InsertVerbose(b *testing.B) {
> var x = make([]int, N)
> var y = make([]int, N/2)
> var k = N/2
> b.ResetTimer()
> for i := 0; i < b.N; i++ {
> s2 = InsertVerbose(x, k, y...)
> }
> }
>
> var s3 []int
> func Benchmark_InsertVerbose_b(b *testing.B) {
> var x = make([]int, N)
> var y = make([]int, N/2)
> var k = N/2
> b.ResetTimer()
> for i := 0; i < b.N; i++ {
> s3 = InsertVerbose_b(x, k, y...)
> }
> }
>
> var s4 []int
> func Benchmark_InsertVerbose_c(b *testing.B) {
> var x = make([]int, N)
> var y = make([]int, N/2)
> var k = N/2
> b.ResetTimer()
> for i := 0; i < b.N; i++ {
> s4 = InsertVerbose_c(x, k, y...)
> }
> }
>
>
> The result:
>
> $ go test -bench=. -benchtime=3s
> ==================== N = 1615119
> goos: linux
> goarch: amd64
> pkg: a.y/bench/sliceinsert
> cpu: Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz
> Benchmark_InsertOneline-4 693 4741509 ns/op
> Benchmark_InsertOneline_Disassemble-4 871 4194142 ns/op
> Benchmark_InsertVerbose-4 764 4627334 ns/op
> Benchmark_InsertVerbose_b-4 769 4958537 ns/op
> Benchmark_InsertVerbose_c-4 661 4855514 ns/op
>
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/0aadf46a-e432-417c-8839-cfdfe24d8375n%40googlegroups.com.