Byte Replace

October 19, 2023
golang benchmark patch

You are probably very familiar with the strings function to replace a substring:

func Replace(s, old, new string, n int) string

Every now and then I’d like to do the same with a byte slice without having to cast it to a string first. Here are a couple of approaches with a benchmark:

package replace

import "bytes"

// ByteReplace is the brute force sliding window approach
func ByteReplace(b, old, new []byte) []byte {
	var found = true
	for i := 0; i < len(b)-len(new)+1; i++ {
		for j := 0; j < len(old); j++ {
			if b[i+j] != old[j] {
				found = false
				break
			}
		}
		if found {
			copy(b[i:], new)
			break
		}
		found = true
	}
	return b
}

// IndexReplace uses the optimized offset finding
func IndexReplace(b, old, new []byte) []byte {
	i := bytes.Index(b, old)
	if i == -1 {
		return b
	}
	copy(b[i:], new)
	return b
}

// StdReplace is more secure and handles a lot of corner cases
func StdReplace(b, old, new []byte) []byte {
	return bytes.Replace(b, old, new, 1)
}

If we compare these using a simple benchmark, we can see how the increase in complexity and corner-case handling is adding to the computation time:

BenchmarkTime per OperationBytes per OperationMemory Allocations per Operation
BenchmarkByteReplace7.154 ns/op0 B/op0 allocs/op
BenchmarkIndexReplace12.59 ns/op0 B/op0 allocs/op
BenchmarkStdReplace52.56 ns/op16 B/op1 allocs/op

As with all things in life, measure and pick the best tool for the job.

Headless BPF

December 30, 2023

I’ve been using the Berkeley Packet Filter from Golang’s wrapper around the PCAP library whenever I needed to filter network packets programmatically:

golang pcap bpf

That String Array

October 11, 2019

If you are using gqlgen to generate your GraphQL endpoint and sqlx or some other kind of ORM for your database, you can benefit from using one type or struct in both directions. You create one type User struct for GraphQL and it maps to your db schema. Now if this user contains more complex types, things become interesting…

golang gqlgen graphql sql cockroachdb