emersion / go-msgauth

🔏 A Go library and tools for DKIM, DMARC and Authentication-Results
MIT License
162 stars 51 forks source link

compare with EqualFold instead of ToLower #48

Closed pierrre closed 3 years ago

pierrre commented 3 years ago

I did a profiling of my application, and noticed that msgauth/dkim is comparing strings with ToLower. https://github.com/emersion/go-msgauth/blob/e98a2eeae5c0d11715d4d4d8170447cb94b15cc0/dkim/header.go#L152-L158 https://github.com/emersion/go-msgauth/blob/e98a2eeae5c0d11715d4d4d8170447cb94b15cc0/dkim/verify.go#L244 Each time this function is called, it allocates a new string, which creates more work for the garbage collector. I think there is an "allocation free" alternative: EqualFold.

WDYT ? I can submit a benchmark if needed.

emersion commented 3 years ago

Sure, EqualFold LGTM

pierrre commented 3 years ago

For reference, here is a very simple micro-benchmark:

package main

import (
    "strings"
    "testing"
)

func BenchmarkToLower(b *testing.B) {
    for i := 0; i < b.N; i++ {
        if strings.ToLower("ABCDEFGHIJ") != "abcdefghij" {
            b.Fatal("not equal")
        }
    }
}

func BenchmarkEqualFold(b *testing.B) {
    for i := 0; i < b.N; i++ {
        if !strings.EqualFold("ABCDEFGHIJ", "abcdefghij") {
            b.Fatal("not equal")
        }
    }
}

The result

BenchmarkToLower
BenchmarkToLower-12         26062184            42.60 ns/op       16 B/op          1 allocs/op
BenchmarkEqualFold
BenchmarkEqualFold-12       41775878            27.07 ns/op        0 B/op          0 allocs/op

I tried to integrate the benchmark to msgauth, but I don't know a simple way to write it.