नोट 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
और Append
64 के बूटस्ट्रैप आकार का उपयोग करें, बाइट्स के समान। बफ़र
Append
अधिक मेमोरी और एलोकेशन का उपयोग करें, मुझे लगता है कि यह बढ़ते एल्गोरिथ्म से संबंधित है जो इसका उपयोग करता है। यह बाइट्स के रूप में तेजी से मेमोरी नहीं बढ़ा रहा है। बफ़र
सुझाव:
- साधारण कार्य के लिए जैसे कि ओपी क्या चाहता है, मैं उपयोग करूंगा
Append
या AppendPreAllocate
। यह काफी तेज और उपयोग में आसान है।
- यदि एक ही समय में बफर को पढ़ने और लिखने की आवश्यकता है, तो
bytes.Buffer
निश्चित रूप से उपयोग करें । इसके लिए ही इसे बनाया गया है।