Câu hỏi này là về tốc độ truy cập các thành phần của mảng và lát, không phải về hiệu quả truyền chúng tới các hàm làm đối số.Mảng vs Slice: tốc độ truy cập
Tôi mong chờ mảng là nhanh hơn so với lát trong nhiều trường hợp vì một lát là một cấu trúc dữ liệu mô tả một phần tiếp giáp của một mảng và do đó có thể có thêm một bước tham gia khi truy cập vào các yếu tố của một lát (gián tiếp các phần tử của mảng cơ bản của nó).
Vì vậy, tôi đã viết một bài kiểm tra nhỏ để chuẩn một loạt các hoạt động đơn giản. Có 4 chức năng chuẩn, 2 thử nghiệm đầu tiên một toàn cầu lát và một mảng toàn cầu, 2 thử nghiệm khác một địa phương lát và một mảng địa phương:
var gs = make([]byte, 1000) // Global slice
var ga [1000]byte // Global array
func BenchmarkSliceGlobal(b *testing.B) {
for i := 0; i < b.N; i++ {
for j, v := range gs {
gs[j]++; gs[j] = gs[j] + v + 10; gs[j] += v
}
}
}
func BenchmarkArrayGlobal(b *testing.B) {
for i := 0; i < b.N; i++ {
for j, v := range ga {
ga[j]++; ga[j] = ga[j] + v + 10; ga[j] += v
}
}
}
func BenchmarkSliceLocal(b *testing.B) {
var s = make([]byte, 1000)
for i := 0; i < b.N; i++ {
for j, v := range s {
s[j]++; s[j] = s[j] + v + 10; s[j] += v
}
}
}
func BenchmarkArrayLocal(b *testing.B) {
var a [1000]byte
for i := 0; i < b.N; i++ {
for j, v := range a {
a[j]++; a[j] = a[j] + v + 10; a[j] += v
}
}
}
Tôi chạy thử nghiệm nhiều lần, đây là sản lượng tiêu biểu (go test -bench .*
):
BenchmarkSliceGlobal 300000 4210 ns/op
BenchmarkArrayGlobal 300000 4123 ns/op
BenchmarkSliceLocal 500000 3090 ns/op
BenchmarkArrayLocal 500000 3768 ns/op
Phân tích kết quả:
Truy cập lát toàn cầu là hơi chậm hơn so với truy cập vào mảng toàn cầu mà là như tôi mong đợi:
4210
vs 4123
ns/op
Nhưng truy cập vào lát địa phương là đáng kể nhanh hơn so với truy cập vào các mảng địa phương:
3090
vs 3768
ns/op
Câu hỏi của tôi là: Lý do cho điều này là gì?
Ghi chú
tôi đã cố gắng thay đổi những điều sau đây nhưng không ai thay đổi kết quả:
- kích thước của mảng/lát (thử 100, 1000, 10000)
- thứ tự của các hàm chuẩn
- loại phần tử của mảng/lát (đã thử
byte
vàint
)
Có một số yếu tố ảnh hưởng đến các tiêu chí vi mô như vậy: Kiểm tra giới hạn, phân bổ (đống, ngăn xếp), tạo mã, tối ưu hóa lổ nhìn trộm, v.v. Hãy xem kết quả lắp ráp được tạo ra trong các điều kiện khác nhau như kiểm tra bị vô hiệu hóa hoặc tắt tối ưu hóa. – Volker
Điều thú vị là, nếu bạn thêm một [con trỏ vào mảng] (http://play.golang.org/p/nyynQgndDl) vào điểm chuẩn, bạn sẽ thấy rằng chúng hoạt động giống như các lát cắt. –