文字の置き換えをする際に使う「strings.Replace」と「strings.NewReplacer」について速度比較してみました。
実装(hoge→foo、moge→bar)
strings.Replace
// 「hogemoge」のスライス1万個
var s = strings.Split(strings.TrimRight(strings.Repeat("hogemoge,", 10000), ","), ",")
func BenchmarkReplace(b *testing.B) {
for _, v := range s {
fmt.Println(strings.Replace(strings.Replace(v, "hoge", "foo", -1), "moge", "bar", -1))
}
}
strings.NewReplacer
// 「hogemoge」のスライス1万個
var s = strings.Split(strings.TrimRight(strings.Repeat("hogemoge,", 10000), ","), ",")
func BenchmarkNewReplacer(b *testing.B) {
replacer := strings.NewReplacer(
"hoge", "foo",
"moge", "bar",
)
for _, v := range s {
fmt.Println(replacer.Replace(v))
}
}
計測(hoge→foo、moge→bar)
環境
- go version:1.20.1
- プロセッサ:AMD Ryzen 5 PRO 3500U w/ Radeon Vega Mobile Gfx 2.10 GHz
- RAM:8.00GB
- OS:Windows 10 Home(22H2)
strings.Replace
1回目:0.446s
2回目:0.449s
3回目:0.436s
strings.NewReplacer
1回目:0.448s
2回目:0.450s
3回目:0.442s
あれ?strings.NewReplacerの方が速いと思ったけどあまり変わらない。
3つ変換するパターンもやってみる。
実装(hoge→foo、moge→bar、huga→baz)
strings.Replace
// 「hogemogehuga」のスライス1万個
var s = strings.Split(strings.TrimRight(strings.Repeat("hogemogehuga,", 10000), ","), ",")
func BenchmarkReplace(b *testing.B) {
for _, v := range s {
fmt.Println(strings.Replace(strings.Replace(strings.Replace(v, "hoge", "foo", -1), "moge", "bar", -1), "huga", "baz", -1))
}
}
strings.NewReplacer
// 「hogemogehuga」のスライス1万個
var s = strings.Split(strings.TrimRight(strings.Repeat("hogemogehuga,", 10000), ","), ",")
func BenchmarkNewReplacer(b *testing.B) {
replacer := strings.NewReplacer(
"hoge", "foo",
"moge", "bar",
"huga", "baz",
)
for _, v := range s {
fmt.Println(replacer.Replace(v))
}
}
計測(hoge→foo、moge→bar、huga→baz)
strings.Replace
1回目:0.460s
2回目:0.463s
3回目:0.478s
strings.NewReplacer
1回目:0.452s
2回目:0.454s
3回目:0.447s
若干strings.NewReplacerが優勢に。
さらに各スライスの文字列が大量のケースでもやってみる。
実装(hoge→foo、moge→bar、huga→baz)※文字列大量
strings.Replace
// 「A × 10000 + hogemoge」のスライス1万個
var s = strings.Split(strings.TrimRight(strings.Repeat(strings.Repeat("A", 10000)+"hogemogehuga,", 10000), ","), ",")
func BenchmarkReplace(b *testing.B) {
for _, v := range s {
fmt.Println(strings.Replace(strings.Replace(strings.Replace(v, "hoge", "foo", -1), "moge", "bar", -1), "huga", "baz", -1))
}
}
strings.NewReplacer
// 「A × 10000 + hogemoge」のスライス1万個
var s = strings.Split(strings.TrimRight(strings.Repeat(strings.Repeat("A", 10000)+"hogemogehuga,", 10000), ","), ",")
func BenchmarkNewReplacer(b *testing.B) {
replacer := strings.NewReplacer(
"hoge", "foo",
"moge", "bar",
"huga", "baz",
)
for _, v := range s {
fmt.Println(replacer.Replace(v))
}
}
計測(hoge→foo、moge→bar、huga→baz)※文字列大量
strings.Replace
1回目:27.802s
2回目:26.717s
3回目:30.299s
strings.NewReplacer
1回目:14.379s
2回目:15.929s
3回目:10.609s
結論
長文に対して複数のワードで置換をしたい場合はstrings.NewReplacerが速いっぽい。
長文でなくても2ワード以上置換する場合は見やすいのでstrings.NewReplacerを使っておけば良さそう。