面试题答案
一键面试可能存在的性能瓶颈
- 内存分配频繁:如果在向切片添加元素时,切片容量不足,Go会重新分配内存,将原切片内容复制到新的内存地址,这会导致大量的内存分配和复制操作,严重影响性能。
- 数据遍历开销:海量数据的遍历求和本身也有一定开销,如果切片内存布局不合理,可能会增加CPU缓存未命中的次数,降低数据读取效率。
优化方法 - 容量预分配
通过预先分配足够的容量,可以减少内存重新分配和数据复制的次数,提高性能。
优化前代码示例
package main
import (
"fmt"
)
func sumWithoutPreallocation(data []int) int {
var sum int
for _, num := range data {
sum += num
}
return sum
}
优化后代码示例
package main
import (
"fmt"
)
func sumWithPreallocation(data []int) int {
var sum int
newData := make([]int, 0, len(data))
for _, num := range data {
newData = append(newData, num)
}
for _, num := range newData {
sum += num
}
return sum
}
性能对比分析思路
- 生成测试数据:使用
math/rand
包生成海量整数数据,例如100万个随机整数。 - 计时对比:使用
time
包记录优化前后代码执行求和操作的时间。例如:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
const numElements = 1000000
data := make([]int, numElements)
for i := 0; i < numElements; i++ {
data[i] = rand.Intn(100)
}
start := time.Now()
sumWithoutPreallocation(data)
elapsedWithoutPreallocation := time.Since(start)
start = time.Now()
sumWithPreallocation(data)
elapsedWithPreallocation := time.Since(start)
fmt.Printf("Without preallocation time: %v\n", elapsedWithoutPreallocation)
fmt.Printf("With preallocation time: %v\n", elapsedWithPreallocation)
}
- 多次测试:为了得到更准确的结果,可以多次运行测试,取平均时间。性能优化后,由于减少了内存重新分配和数据复制,理论上执行时间会明显缩短。