Skip to content

Instantly share code, notes, and snippets.

@andrewhodel
Last active April 15, 2025 15:08
Show Gist options
  • Save andrewhodel/18350814a6c7880b153265d4b0bcf1a2 to your computer and use it in GitHub Desktop.
Save andrewhodel/18350814a6c7880b153265d4b0bcf1a2 to your computer and use it in GitHub Desktop.
Golang: delete from slice performance by CPU instruction count

This proves slices.Delete is the fastest method on x86-64 by CPU instruction count.

All methods usually report 0 nanoseconds when running these tests using time, that is why it tests by using CPU instruction count.

delete without order preserved
	 22 CPU instructions (speed)
delete using append with order preserved
	 1508 CPU instructions (speed)
delete using slices.Delete with order preserved
	 1013 CPU instructions (speed)

delete without order preserved
	 [asdf0 asdf1 asdf49 asdf3 asdf4 asdf5 asdf6 asdf7 asdf8 asdf9 asdf10 asdf11 asdf12 asdf13 asdf14 asdf15 asdf16 asdf17 asdf18 asdf19 asdf20 asdf21 asdf22 asdf23 asdf24 asdf25 asdf26 asdf27 asdf28 asdf29 asdf30 asdf31 asdf32 asdf33 asdf34 asdf35 asdf36 asdf37 asdf38 asdf39 asdf40 asdf41 asdf42 asdf43 asdf44 asdf45 asdf46 asdf47 asdf48]
delete using append with order preserved
	 [asdf0 asdf1 asdf3 asdf4 asdf5 asdf6 asdf7 asdf8 asdf9 asdf10 asdf11 asdf12 asdf13 asdf14 asdf15 asdf16 asdf17 asdf18 asdf19 asdf20 asdf21 asdf22 asdf23 asdf24 asdf25 asdf26 asdf27 asdf28 asdf29 asdf30 asdf31 asdf32 asdf33 asdf34 asdf35 asdf36 asdf37 asdf38 asdf39 asdf40 asdf41 asdf42 asdf43 asdf44 asdf45 asdf46 asdf47 asdf48 asdf49]
delete using slices.Delete with order preserved
	 [asdf0 asdf1 asdf3 asdf4 asdf5 asdf6 asdf7 asdf8 asdf9 asdf10 asdf11 asdf12 asdf13 asdf14 asdf15 asdf16 asdf17 asdf18 asdf19 asdf20 asdf21 asdf22 asdf23 asdf24 asdf25 asdf26 asdf27 asdf28 asdf29 asdf30 asdf31 asdf32 asdf33 asdf34 asdf35 asdf36 asdf37 asdf38 asdf39 asdf40 asdf41 asdf42 asdf43 asdf44 asdf45 asdf46 asdf47 asdf48 asdf49]
package main

import (
	"fmt"
	"slices"
	"strconv"

	// requires x86-64 architecture to use CPU instruction count as time
	// as time.Now() nanosecond resolution is not precise enough
	"github.com/dterei/gotsc"
)

func main() {

	tsc := gotsc.TSCOverhead()

	a := make([]string, 50)
	a1 := make([]string, 50)
	a2 := make([]string, 50)

	for n := range a {
		a[n] = "asdf" + strconv.Itoa(n)
		a1[n] = "asdf" + strconv.Itoa(n)
		a2[n] = "asdf" + strconv.Itoa(n)
	}

	// element to remove
	i := 2

	// delete fast but order not preserved
	var s0 = gotsc.BenchStart()

	// Remove the element at index i from a.
	a[i] = a[len(a)-1] // Copy last element to index i.
	a[len(a)-1] = ""   // Erase last element (write zero value).
	a = a[:len(a)-1]   // Truncate slice.

	fmt.Println("delete without order preserved\n\t", gotsc.BenchEnd()-s0-tsc, "CPU instructions (speed)")

	// delete with order preserved using append
	var s1 = gotsc.BenchStart()

	// Remove the element at index i from a1.
	copy(a1[i:], a1[i+1:]) // Shift a[i+1:] left one index.
	a1[len(a1)-1] = ""     // Erase last element (write zero value).
	a1 = a1[:len(a1)-1]    // Truncate slice.

	fmt.Println("delete using append with order preserved\n\t", gotsc.BenchEnd()-s1-tsc, "CPU instructions (speed)")

	// delete with order preserved using slices.Delete
	var s2 = gotsc.BenchStart()

	// Remove the element at index i from a2.
	a2 = slices.Delete(a2, i, i+1)

	// show results
	fmt.Println("delete using slices.Delete with order preserved\n\t", gotsc.BenchEnd()-s2-tsc, "CPU instructions (speed)")

	fmt.Println("")
	fmt.Println("delete without order preserved\n\t", a)
	fmt.Println("delete using append with order preserved\n\t", a1)
	fmt.Println("delete using slices.Delete with order preserved\n\t", a2)

}

https://go.dev/play/p/ULJ62uYjoiM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment