Skip to content

Instantly share code, notes, and snippets.

@tevjef
Last active November 27, 2016 04:31
Show Gist options
  • Save tevjef/cf451c3947191299372879fd08c1e644 to your computer and use it in GitHub Desktop.
Save tevjef/cf451c3947191299372879fd08c1e644 to your computer and use it in GitHub Desktop.
Golang regexp vs strings.Map
bash-3.2$ go test -bench=.
PASS
BenchmarkRegexReplace-4 500000 2470 ns/op 19.83 MB/s 113 B/op 1 allocs/op
BenchmarkMapReplace-4 2000000 813 ns/op 60.22 MB/s 0 B/op 0 allocs/op
package main
import (
"regexp"
"strings"
"unicode"
)
var topicRegex, _ = regexp.Compile("[^A-Za-z0-9-_.~% ]+")
func regexReplace(str string) string {
return topicRegex.ReplaceAllLiteralString(str, "")
}
func mapReplace(str string) string {
return strings.Map(func(r rune) rune {
if isValidTopicRune(r) {
return r
}
return -1
}, str)
}
func isValidTopicRune(r rune) bool {
isDash := r == rune('-')
isUnderscore := r == rune('_')
isDot := r == rune('.')
isTilde := r == rune('~')
isPercent := r == rune('%')
return unicode.IsLetter(r) || unicode.IsNumber(r) || unicode.IsSpace(r) || isDash || isUnderscore || isDot || isTilde || isPercent
}
package main
import (
"math/rand"
"testing"
"time"
)
var testString = "Res Proposal In A....H.!@#$%[]^&*()_?><.02.87A\u0000SDA"
var expected = "Res Proposal In A....H.%_.02.87ASDA"
func Test_regexReplace(t *testing.T) {
type args struct {
str string
}
tests := []struct {
name string
args args
want string
}{
{args: args{testString}, want: expected},
}
for _, tt := range tests {
if got := regexReplace(tt.args.str); got != tt.want {
t.Errorf("%q. regexReplace() = %v, want %v", tt.name, got, tt.want)
}
}
}
func Test_mapReplace(t *testing.T) {
type args struct {
str string
}
tests := []struct {
name string
args args
want string
}{
{args: args{testString}, want: expected},
}
for _, tt := range tests {
if got := mapReplace(tt.args.str); got != tt.want {
t.Errorf("%q. mapReplace() = %v, want %v", tt.name, got, tt.want)
}
}
}
func BenchmarkRegexReplace(b *testing.B) {
seed := time.Now().UnixNano()
popr := rand.New(rand.NewSource(seed))
total := 0
pops := make([]string, 10000)
for i := 0; i < 10000; i++ {
pops[i] = randStringModel(popr)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
total += len(regexReplace(pops[i%10000]))
}
b.SetBytes(int64(total / b.N))
}
func BenchmarkMapReplace(b *testing.B) {
popr := rand.New(rand.NewSource(0))
total := 0
pops := make([]string, 10000)
for i := 0; i < 10000; i++ {
pops[i] = randStringModel(popr)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
total += len(mapReplace(pops[i%10000]))
}
b.SetBytes(int64(total / b.N))
}
type randyModel interface {
Float32() float32
Float64() float64
Int63() int64
Int31() int32
Uint32() uint32
Intn(n int) int
}
func randStringModel(r randyModel) string {
v32 := r.Intn(100)
tmps := make([]rune, v32)
for i := 0; i < v32; i++ {
tmps[i] = randUTF8RuneModel(r)
}
return string(tmps)
}
func randUTF8RuneModel(r randyModel) rune {
ru := r.Intn(62)
if ru < 10 {
return rune(ru + 48)
} else if ru < 36 {
return rune(ru + 55)
}
return rune(ru + 61)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment