An efficient way to compare strings in Go

| Reading Time : 3 minutes | #backenddevelopment #Go


Introduction

One of the most overlooked operations is comparing two strings and this might not cause system overhead but definitely, it is a good practice to write an efficient code where possible. These small dividends definitely pay at the end when the application is under real stress in production.

Note: I am amateur in Go if you are an experienced professional in Go and find anything wrong here don’t be annoyed. If you could point the mistake I will correct those accordingly.

One of the often used string comparisons is

strings.ToLower(stringA) == strings.ToLower(stringB)

but this way of comparing takes a lot of time per operation and the reason is, In Go, a string is an immutable sequence of runes. rune in Go is an integer value represents code point

The more detailed and sensible explanation is given by Rob Pike in blog: https://blog.golang.org/strings Its a very nice bedtime read which gives a recap of basics of strings in programming languages.

Here ToLower a standard function in strings package which when used traverse through the entire string converts it to a lower case and returns a new string cause strings in Go is immutable which means strings.ToLower allocates new memory spaces for these two strings.

sample code:

func CompareStringsInCrudeWay(stringA, stringB string) (bool, error) {
	if strings.ToLower(stringA) == strings.ToLower(stringB) {
		return true, nil
	} else {
		return false, nil
	}
}

Benchmark:

Input:

  stringA = "rakesh123456789mothukuri123456789"

  stringB = "ramesh123456789mothukuri123456789"

BenchmarkCompare-8       8304722               151 ns/op               0 B/op          0 allocs/op

If we notice in earlier benchmark figures this operation takes 151 nanoseconds per operation. But is this too much we need to talk about? No, but if there is a simple change to way strings are compared and we could get this down to 30 nanoseconds why not?

Optimization

To optimize we could find a way instead traverse through runes of each string, compare each character in the string, if rune doesn’t match we would convert rune to lowercase and compare again and if they still don’t match we break the loop and break the loop and return strings are not same. This process will save operation time spent comparing string.

Pseudocode

func Compare(stringA, stringB string) bool {
	for i := 0; i < len(stringA); i++ {
		if stringA[i] == stringB[i] {
			continue
		}
		if unicode.ToLower(stringA[i]) != unicode.ToLower(stringB[i]) {
			return false
		}
	}
	return true
}

But this has more logic here to remember and implement every time we compare string only if there is an easy way to do. Go strings package has a method which performs in this fashion which is strings.EqualFold

sample code using EqualFold

func CompareStringsInEfficientWay(stringA, stringB string) (bool, error) {
   if strings.EqualFold(stringA, stringB) {
      return true, nil
   } else {
      return false, nil
   }
}

Benchmark:

Input:
  stringA = "rakesh123456789mothukuri123456789"
  stringB = "ramesh123456789mothukuri123456789"
BenchmarkCompare-8      76842292                17.1 ns/op             0 B/op          0 allocs/op

Now, it took 17 nanoseconds per operation, These small wins over a period of time will definitely payback, not only they pay back it also helps promote an efficient way of writing code.

This is the end of the blog if you think there is a more efficient way of comparing string in Go please drop me a message I will attribute you and amend the content.


Articles from blogs I follow around the net

powerctl: A small case study in Hare for systems programming

powerctl is a little weekend project I put together to provide a simple tool for managing power states on Linux. I had previously put my laptop into suspend with a basic “echo mem | doas tee /sys/power/state”, but this leaves a lot to be desired. I have to u…

via Drew DeVault's blog August 28, 2022

United States v. Microsoft Corp exhibits

Links to exhibits from the Microsoft anti-trust case, with a bit of info on each link. Projection of PC marketshare Share of new browser users Share of the browser market, grouped by major ISP, 3 month moving average Share of the browser market, grouped by ma…

via danluu.com August 24, 2022

Status update, August 2022

Hi all! This month I’ve been pondering offline-first apps. The online aspect of modern apps is an important feature for many use-cases: it enables collaboration between multiple people and seamless transition between devices (e.g. I often switch between my pe…

via emersion August 14, 2022

Generated by openring

© Copyright 2021-2022. Rakesh Mothukuri