नोट 2018 में जोड़ा गया
1.10 गो से एक strings.Builderप्रकार है, अधिक विस्तार के लिए कृपया इस उत्तर पर एक नज़र डालें ।
201 से पहले के उत्तर
@ Cd1 और अन्य उत्तरों का बेंचमार्क कोड गलत है। b.Nबेंचमार्क फ़ंक्शन में सेट नहीं होना चाहिए। यह गो परीक्षण उपकरण द्वारा गतिशील रूप से निर्धारित करने के लिए निर्धारित किया जाता है कि परीक्षण का निष्पादन समय स्थिर है या नहीं।
एक बेंचमार्क फ़ंक्शन को एक ही परीक्षण b.Nबार चलाना चाहिए और लूप के अंदर का परीक्षण प्रत्येक पुनरावृत्ति के लिए समान होना चाहिए। इसलिए मैं इसे एक आंतरिक लूप जोड़कर ठीक करता हूं। मैं कुछ अन्य समाधानों के लिए बेंचमार्क भी जोड़ता हूं:
package main
import (
"bytes"
"strings"
"testing"
)
const (
sss = "xfoasneobfasieongasbg"
cnt = 10000
)
var (
bbb = []byte(sss)
expected = strings.Repeat(sss, cnt)
)
func BenchmarkCopyPreAllocate(b *testing.B) {
var result string
for n := 0; n < b.N; n++ {
bs := make([]byte, cnt*len(sss))
bl := 0
for i := 0; i < cnt; i++ {
bl += copy(bs[bl:], sss)
}
result = string(bs)
}
b.StopTimer()
if result != expected {
b.Errorf("unexpected result; got=%s, want=%s", string(result), expected)
}
}
func BenchmarkAppendPreAllocate(b *testing.B) {
var result string
for n := 0; n < b.N; n++ {
data := make([]byte, 0, cnt*len(sss))
for i := 0; i < cnt; i++ {
data = append(data, sss...)
}
result = string(data)
}
b.StopTimer()
if result != expected {
b.Errorf("unexpected result; got=%s, want=%s", string(result), expected)
}
}
func BenchmarkBufferPreAllocate(b *testing.B) {
var result string
for n := 0; n < b.N; n++ {
buf := bytes.NewBuffer(make([]byte, 0, cnt*len(sss)))
for i := 0; i < cnt; i++ {
buf.WriteString(sss)
}
result = buf.String()
}
b.StopTimer()
if result != expected {
b.Errorf("unexpected result; got=%s, want=%s", string(result), expected)
}
}
func BenchmarkCopy(b *testing.B) {
var result string
for n := 0; n < b.N; n++ {
data := make([]byte, 0, 64) // same size as bootstrap array of bytes.Buffer
for i := 0; i < cnt; i++ {
off := len(data)
if off+len(sss) > cap(data) {
temp := make([]byte, 2*cap(data)+len(sss))
copy(temp, data)
data = temp
}
data = data[0 : off+len(sss)]
copy(data[off:], sss)
}
result = string(data)
}
b.StopTimer()
if result != expected {
b.Errorf("unexpected result; got=%s, want=%s", string(result), expected)
}
}
func BenchmarkAppend(b *testing.B) {
var result string
for n := 0; n < b.N; n++ {
data := make([]byte, 0, 64)
for i := 0; i < cnt; i++ {
data = append(data, sss...)
}
result = string(data)
}
b.StopTimer()
if result != expected {
b.Errorf("unexpected result; got=%s, want=%s", string(result), expected)
}
}
func BenchmarkBufferWrite(b *testing.B) {
var result string
for n := 0; n < b.N; n++ {
var buf bytes.Buffer
for i := 0; i < cnt; i++ {
buf.Write(bbb)
}
result = buf.String()
}
b.StopTimer()
if result != expected {
b.Errorf("unexpected result; got=%s, want=%s", string(result), expected)
}
}
func BenchmarkBufferWriteString(b *testing.B) {
var result string
for n := 0; n < b.N; n++ {
var buf bytes.Buffer
for i := 0; i < cnt; i++ {
buf.WriteString(sss)
}
result = buf.String()
}
b.StopTimer()
if result != expected {
b.Errorf("unexpected result; got=%s, want=%s", string(result), expected)
}
}
func BenchmarkConcat(b *testing.B) {
var result string
for n := 0; n < b.N; n++ {
var str string
for i := 0; i < cnt; i++ {
str += sss
}
result = str
}
b.StopTimer()
if result != expected {
b.Errorf("unexpected result; got=%s, want=%s", string(result), expected)
}
}
पर्यावरण OS X 10.11.6, 2.2 GHz इंटेल कोर i7 है
परीक्षण के परिणाम:
BenchmarkCopyPreAllocate-8 20000 84208 ns/op 425984 B/op 2 allocs/op
BenchmarkAppendPreAllocate-8 10000 102859 ns/op 425984 B/op 2 allocs/op
BenchmarkBufferPreAllocate-8 10000 166407 ns/op 426096 B/op 3 allocs/op
BenchmarkCopy-8 10000 160923 ns/op 933152 B/op 13 allocs/op
BenchmarkAppend-8 10000 175508 ns/op 1332096 B/op 24 allocs/op
BenchmarkBufferWrite-8 10000 239886 ns/op 933266 B/op 14 allocs/op
BenchmarkBufferWriteString-8 10000 236432 ns/op 933266 B/op 14 allocs/op
BenchmarkConcat-8 10 105603419 ns/op 1086685168 B/op 10000 allocs/op
निष्कर्ष:
CopyPreAllocate सबसे तेज़ तरीका है; AppendPreAllocateनंबर 1 के काफी करीब है, लेकिन कोड लिखना आसान है।
Concatगति और स्मृति उपयोग दोनों के लिए वास्तव में खराब प्रदर्शन है। इसका उपयोग न करें।
Buffer#Writeऔर Buffer#WriteStringमूल रूप से गति में समान हैं, जो @ दानी-ब्र ने टिप्पणी में कहा है। विचार stringकरना वास्तव []byteमें गो में है, यह समझ में आता है।
- बाइट्स। बफ़र मूल रूप से एक ही समाधान का उपयोग
Copyअतिरिक्त पुस्तक रखने और अन्य सामान के साथ करते हैं।
Copyऔर Append64 के बूटस्ट्रैप आकार का उपयोग करें, बाइट्स के समान। बफ़र
Appendअधिक मेमोरी और एलोकेशन का उपयोग करें, मुझे लगता है कि यह बढ़ते एल्गोरिथ्म से संबंधित है जो इसका उपयोग करता है। यह बाइट्स के रूप में तेजी से मेमोरी नहीं बढ़ा रहा है। बफ़र
सुझाव:
- साधारण कार्य के लिए जैसे कि ओपी क्या चाहता है, मैं उपयोग करूंगा
Appendया AppendPreAllocate। यह काफी तेज और उपयोग में आसान है।
- यदि एक ही समय में बफर को पढ़ने और लिखने की आवश्यकता है, तो
bytes.Bufferनिश्चित रूप से उपयोग करें । इसके लिए ही इसे बनाया गया है।