Visión de conjunto
- + Costuras de números
- costuras fmt
- Unir costuras
- costuras de amortiguación
- costuras de constructor
En el caso de menos datos, estos métodos no son muy diferentes, pero se recomienda su uso cuando hay muchas cadenas para unir builder
. La conexión de signo + es adecuada para la concatenación de cadenas cortas y constantes, ya que el compilador optimizará
+ Costuras de números
s := s1+s2+s3
costuras fmt
s := fmt.Sprintf("%v%v",s1,s2)
Unir costuras
Reciba una serie de cadenas y conviértalas en una cadena concatenada
sList := []string{s1,s2}
s := strings.Join(SList,"")
costuras de amortiguación
No solo puede concatenar cadenas de caracteres, sino también concatenar bytes, etc.
var b = bytes.Buffer
b.WriteString(s1)
b.WriteString(S2)
s := String()
costuras de constructor
var b strings.Builder
b.WriteString(s1)
b.WriteString(s2)
s := b.String()
Optimizar el constructor
Código de prueba
proyecto \ stringBuilder \ sb.go
package stringBuilder
import "strings"
func StringBuilder(p []string) string {
var b strings.Builder
l:=len(p)
for i:=0;i<l;i++{
b.WriteString(p[i])
}
return b.String()
}
proyecto \ stringBuilder \ sb_test.go
package stringBuilder
import "testing"
const TESTSTRING = "test,"
/*
初始化函数
生成一个具有N个字符串的数组
*/
func initStrings(N int) []string{
s:=make([]string,N)
for i:=0;i<N;i++{
s[i]=TESTSTRING
}
return s;
}
/*
测试
10个字符串
*/
func BenchmarkStringBuilder10(b *testing.B) {
p:= initStrings(10)
b.ResetTimer()
for i:=0;i<b.N;i++{
StringBuilder(p)
}
}
/*
测试
100个字符串
*/
func BenchmarkStringBuilder100(b *testing.B) {
p:= initStrings(100)
b.ResetTimer()
for i:=0;i<b.N;i++{
StringBuilder(p)
}
}
/*
测试
1000个字符串
*/
func BenchmarkStringBuilder1000(b *testing.B) {
p:= initStrings(1000)
b.ResetTimer()
for i:=0;i<b.N;i++{
StringBuilder(p)
}
}
Resultado de la prueba
goos: windows
goarch: amd64
pkg: TestProject/stringBuilder
BenchmarkStringBuilder10-4 5163981 228 ns/op 120 B/op 4 allocs/op
BenchmarkStringBuilder100-4 1000000 1150 ns/op 1016 B/op 7 allocs/op
BenchmarkStringBuilder1000-4 107428 11735 ns/op 21240 B/op 13 allocs/op
PASS
builder
Donde es lento
Como se puede ver en los resultados de la evaluación comparativa, se ralentiza principalmente en asignaciones de memoria múltiples.Si las asignaciones de memoria múltiples causan GC, ¡será más lento!
builder
Código fuente
// WriteString appends the contents of s to b's buffer.
// It returns the length of s and a nil error.
func (b *Builder) WriteString(s string) (int, error) {
b.copyCheck()
b.buf = append(b.buf, s...)
return len(s), nil
}
En pocas palabras, se rellena con append
funciones []byte b
: cuando b
se expande la matriz de bytes, causará la asignación de memoria, lo que hace que la operación sea más lenta.
Solución
Reduzca la cantidad de asignaciones de memoria, que es b字节数组
asignar el tamaño de antemanocap
Modifica el código
func StringBuilder(p []string,cap int) string {
var b strings.Builder
l:=len(p)
b.Grow(cap)
for i:=0;i<l;i++{
b.WriteString(p[i])
}
return b.String()
}
//测试代码以10个字符串为例
//修改为如下
func BenchmarkStringBuilder10(b *testing.B) {
p:= initStrings(10)
b.ResetTimer()
cap := 10*len(TESTSTRING)
for i:=0;i<b.N;i++{
StringBuilder(p,cap)
}
}
Resultados de la prueba después de la optimización
BenchmarkStringBuilder10-4 10027047 114 ns/op 64 B/op 1 allocs/op
BenchmarkStringBuilder100-4 1312066 810 ns/op 512 B/op 1 allocs/op
BenchmarkStringBuilder1000-4 141570 8080 ns/op 5376 B/op 1 allocs/op
PASS
Puede ser optimizado 20%
~50%