Performance comparison of string concatenation in Go language

  sonic0002        2024-05-13 00:33:20       2,293        0          English  简体中文  繁体中文  ภาษาไทย  Tiếng Việt 

Trong ngôn ngữ Go, nối chuỗi là một thao tác không thể tránh khỏi trong quá trình phát triển, và việc nối chuỗi hiệu quả là rất quan trọng để cải thiện hiệu suất ứng dụng. Bài viết này sẽ đi sâu vào một số cách nối chuỗi phổ biến, cung cấp so sánh hiệu năng và đưa ra các đề xuất tối ưu hóa nhằm giúp các nhà phát triển viết mã hiệu quả hơn.

Các cách nối chuỗi phổ biến

Trong ngôn ngữ Go, các cách nối chuỗi phổ biến bao gồm:

Sử dụng toán tử + để nối

Nó đơn giản và dễ hiểu, nhưng mỗi lần nối tạo ra một chuỗi mới, dẫn đến chi phí phân bổ bộ nhớ đáng kể.

func plusConcat(n int, str string) string {
	s := ""
	for i := 0; i < n; i++ {
		s += str
	}
	return s
}

Sử dụng fmt.Sprintf để nối có định dạng

Nó hỗ trợ các tính năng định dạng phong phú, nhưng hiệu năng của nó không tốt bằng các phương pháp khác.

func sprintfConcat(n int, str string) string {
	s := ""
	for i := 0; i < n; i++ {
		s = fmt.Sprintf("%s%s", s, str)
	}
	return s
}

Sử dụng strings.Builder

Được giới thiệu trong Go 1.10, kiểu này được thiết kế đặc biệt để nối chuỗi hiệu quả.

func builderConcat(n int, str string) string {
	var builder strings.Builder
	for i := 0; i < n; i++ {
		builder.WriteString(str)
	}
	return builder.String()
}

Sử dụng bộ đệm bytes.Buffer

Nó được hỗ trợ bởi một lát []byte, nhưng việc chuyển đổi thành chuỗi gây ra phân bổ bộ nhớ bổ sung.

func bufferConcat(n int, str string) string {
	buf := new(bytes.Buffer)
	for i := 0; i < n; i++ {
		buf.WriteString(str)
	}
	return buf.String()
}

Sử dụng nối lát []byte

Quản lý bộ nhớ thủ công, hoạt động tốt nhưng dễ bị lỗi.

func preByteConcat(n int, str string) string {
	buf := make([]byte, 0, n*len(str))
	for i := 0; i < n; i++ {
		buf = append(buf, str...)
	}
	return string(buf)
}

So sánh hiệu năng

Để so sánh hiệu năng của các phương pháp nối khác nhau, chúng ta nối các chuỗi có độ dài 10 cho 10.000 lần và kiểm tra thời gian và sử dụng bộ nhớ. Dưới đây là kết quả kiểm tra cho các phương pháp nối khác nhau:

 

thời gian/op (ms)

bộ nhớ/op(MB)

phân bổ/op

Nối +

56

530

10026

fmt.Sprintf

112

835

37435

strings.Builder

0.13

0.5

23

bytes.Buffer

0.14

0.4

13

[]byte được phân bổ trước

0.07

0.2

2

Nguyên tắc đằng sau hiệu năng

Tại sao strings.Builder hoạt động tốt hơn nhiều so với các phương pháp khác? Lý do nằm ở cơ chế phân bổ bộ nhớ.

Đối với nối +, mỗi lần nối tạo ra một chuỗi mới, dẫn đến việc liên tục phân bổ lại bộ nhớ.

strings.Builder sử dụng một lát []byte cơ bản và sử dụng chiến lược phân bổ bộ nhớ theo cấp số mũ, tránh việc phân bổ bộ nhớ thường xuyên.

Khi chuyển đổi thành chuỗi, nó trực tiếp trả về lát []byte cơ bản, tránh phân bổ bộ nhớ bổ sung.

Đề xuất tối ưu hóa

Cân nhắc khả năng sử dụng và hiệu năng, nên sử dụng strings.Builder để nối chuỗi. Nếu cần hiệu năng cực cao, hãy xem xét sử dụng bộ nhớ được phân bổ trước với nối lát []byte.

Kết luận

Bài viết này đã so sánh hiệu năng của các phương pháp nối chuỗi khác nhau, phân tích các nguyên tắc cơ bản và đưa ra các đề xuất tối ưu hóa. Trong phát triển thực tế, hãy chọn phương pháp nối phù hợp dựa trên yêu cầu hiệu năng để tránh chi phí hiệu năng không cần thiết. Chúng tôi hy vọng bài viết này sẽ giúp ích trong các trường hợp liên quan đến nối chuỗi. Các ý kiến khác nhau được chào đón trong phần bình luận.

COMPARISON  PERFORMANCE  STRING CONCATENATION 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

Mathematician loses to barman