开头
一切为了优化而优化都是耍流氓,肯定是在正确的基础上进行优化。
go 切片的优化
Go 语言切片是对数组的抽象。 Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。 内存分配和释放是非常耗时的操作,因此频繁地对切片进行重新分配和释放会影响程序的性能和效率。当程序中的数据量增加时,内存分配和释放的开销也会增加,这会导致程序变得更加缓慢。
因此,在使用切片时,需要注意内存使用的优化,尽可能地避免频繁地进行内存分配和释放操作。优化内存使用可以减少程序的运行时间和内存占用,提高程序的性能和效率。
切片优化内存的技巧
- 预分配切片的容量 在创建切片时,如果能够预先知道其容量,最好设置好预期的容量。这样可以避免内存重新分配的开销。
- 重用底层数组 尽可能地重用底层数组可以减少内存分配和释放的开销。可以使用切片的切片操作和 copy 函数来复制数据,避免创建新的切片。
- 使用 append 函数时预分配容量 如果在使用 append 函数时预先分配足够的容量,可以避免内存重新分配的开销。尽可能地避免在循环中多次使用 append 函数,这将导致多次内存重新分配。
代码实践
package main
import (
"fmt"
)
func main() {
var s1 []int
var s2 []int
for i := 0; i < 10000000; i++ {
s1 = append(s1, i)
s2 = append(s2, i*2)
}
fmt.Printf("s1: %d, s2: %d\n", len(s1), len(s2))
s3 := s1[:0]
s4 := s2[:0]
// var s3 []int
// var s4 []int
for i := 0; i < 10000000; i++ {
s3 = append(s3, i)
s4 = append(s4, i*2)
}
fmt.Printf("s1: %d, s2: %d\n", len(s3), len(s4))
}
开始s3,s4用var创造和用底层数组直接赋值,后者是要快一些。
3的代码实践
package main
import (
"fmt"
"math/rand"
"time"
)
const (
n = 1000000
)
func main() {
// 预分配切片的容量
//data := make([]int, 0, n)
var data []int
// 向切片中添加元素并处理
rand.Seed(time.Now().UnixNano())
for i := 0; i < n; i++ {
data = append(data, rand.Intn(1000))
//fmt.Println(rand.Intn(1000))
}
for i := range data {
//data[i] = process(data[i])
fmt.Println(data[i])
if i == 15 {
break
}
}
fmt.Println("All elements are processed!")
}
这两个的差别不大,make确定了长度,下面直接定义。可能这做错了。
总结
反正切片优化就是少定义,少开空间降低内存。还是要先写出正确的代码。大佬全都写出来了 [借鉴大佬的文章](不背锅运维:Go语言切片内存优化技巧和实战案例_golang 内存优化_不背锅运维的博客-CSDN博客)