Какой лучше получить последний символ Х строки Golang?
Когда у меня есть строка "hogemogehogemogehohomomoge世界世界世界", какой код лучше получить последнюю руну, избегая выделения памяти?
Есть похожий вопрос о том, чтобы получить последний символ X строки Golang.
Я хочу убедиться, что предпочтительнее, если я просто хочу получить последнюю руну, без каких-либо дополнительных операций.
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
// which is more better for memory allocation?
s := "hogemogehogemogehogemoge世界世界世界a"
getLastRune(s, 3)
getLastRune2(s, 3)
}
func getLastRune(s string, c int) {
// DecodeLastRuneInString
j := len(s)
for i := 0; i < c && j > 0; i++ {
_, size := utf8.DecodeLastRuneInString(s[:j])
j -= size
}
lastByRune := s[j:]
fmt.Println(lastByRune)
}
func getLastRune2(s string, c int) {
// string -> []rune
r := []rune(s)
lastByRune := string(r[len(r)-c:])
fmt.Println(lastByRune)
}
世界
世界
1 ответ
Всякий раз, когда речь идет о производительности и распределении ресурсов, вы должны запускать тесты.
Сначала давайте изменим ваши функции, чтобы они не печатали, а возвращали результат:
func getLastRune(s string, c int) string {
j := len(s)
for i := 0; i < c && j > 0; i++ {
_, size := utf8.DecodeLastRuneInString(s[:j])
j -= size
}
return s[j:]
}
func getLastRune2(s string, c int) string {
r := []rune(s)
if c > len(r) {
c = len(r)
}
return string(r[len(r)-c:])
}
И эталонные функции:
var s = "hogemogehogemogehogemoge世界世界世界a"
func BenchmarkGetLastRune(b *testing.B) {
for i := 0; i < b.N; i++ {
getLastRune(s, 3)
}
}
func BenchmarkGetLastRune2(b *testing.B) {
for i := 0; i < b.N; i++ {
getLastRune2(s, 3)
}
}
Запуск их:
go test -bench . -benchmem
Результаты:
BenchmarkGetLastRune-4 30000000 36.9 ns/op 0 B/op 0 allocs/op
BenchmarkGetLastRune2-4 10000000 165 ns/op 0 B/op 0 allocs/op
getLastRune()
более чем в 4 раза быстрее Ни один из них не делает никаких распределений, но это происходит из-за оптимизации компилятора (преобразование string
в []rune
и обратно вообще требует выделения).
Если мы запустим тесты с отключенными оптимизациями:
go test -gcflags '-N -l' -bench . -benchmem
Результаты:
BenchmarkGetLastRune-4 30000000 46.2 ns/op 0 B/op 0 allocs/op
BenchmarkGetLastRune2-4 10000000 197 ns/op 16 B/op 1 allocs/op
Оптимизация компилятора или нет, getLastRune()
явный победитель.