Golang中如何优化这个简单的斐波那契函数?
Golang中如何优化这个简单的斐波那契函数? 我编写了这个简单的函数,它迭代1000次,每次迭代计算1250次斐波那契数列,并将每个数字追加到切片中。我的目标是创建一个模拟CPU工作的函数。谢谢!
func fibonacci() []int {
var result []int
var start = 1000
for {
var num = 1250
var n1, n2, temp int = 0, 1, 0
for {
temp = n2
n2 = n1 + n2
n1 = temp
result = append(result, n2)
if num <= 1 {
break
}
num--
}
if start <= 1 {
break
}
start--
}
return result
}
更多关于Golang中如何优化这个简单的斐波那契函数?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
如何改进?是太快了还是太慢了?
@NobbZ 感谢您的详细解释,这完全说得通。关于Go语言还有很多需要学习的地方 🙂
@NobbZ 在优化之前,我的测试结果是每秒340个请求,现在达到了每秒1,245个请求。我很好奇为什么这个优化能带来如此显著的提升?
我正在学习Go语言,想知道这段代码能否优化得更快?有没有更好的编写方式能让性能更出色?
func main() {
fmt.Println("hello world")
}
既然你已经知道需要1250个元素,可以预先分配切片。
result := make([]int, 0, 1250)
或者甚至
result := make([]int, 1250)
…
for {
…
result[1250 - num] = n2
…
}
编辑
我刚意识到,你正在用相同的数字重复追加1000次…所以你需要相应地调整容量/大小和索引计算。
内存分配代价高昂,复制大块内存更是如此。
由于切片本质上是带有"长度"和"容量"的胖指针,其工作原理如下:
从零长度的切片开始。首次追加元素时,会分配容量为10的空间(具体数值可能有所不同,但大致相当),长度变为1,元素被插入其中。 长度持续增加直到插入操作将超出容量,此时会重新分配双倍容量(20)的内存块,复制原有内容,并将新元素添加到末尾。 随后容量依次倍增为40、80、160、320、640、1280、2560、5120、10240、20480、40960、81920、163840、327680、655360、1310720。
这意味着需要经历18次扩容,总共复制约1310710个元素的数据。按每个int类型占4字节计算,相当于5242840字节或约5.1MiB。
通过预分配可以避免所有这些复制操作。
以下是针对您提供的斐波那契函数的优化建议。原函数通过嵌套循环模拟CPU工作,但存在一些性能瓶颈,如重复的切片追加和变量初始化。我将展示优化后的代码,并解释关键改进点。
优化后的代码
func fibonacciOptimized() []int {
const outerIterations = 1000
const innerIterations = 1250
totalElements := outerIterations * innerIterations
result := make([]int, 0, totalElements)
for i := 0; i < outerIterations; i++ {
n1, n2 := 0, 1
for j := 0; j < innerIterations; j++ {
n1, n2 = n2, n1+n2
result = append(result, n2)
}
}
return result
}
优化点解释
-
预分配切片容量:使用
make([]int, 0, totalElements)预分配切片容量,避免append操作时的多次内存重新分配。原函数在每次append时可能触发底层数组扩容,增加开销。 -
简化循环结构:将无限循环
for {}改为固定次数的for循环,使用常量outerIterations和innerIterations提高可读性。原代码使用start和num变量递减,容易出错。 -
优化变量赋值:使用并行赋值
n1, n2 = n2, n1+n2替换临时变量temp,减少变量操作和内存访问。 -
移除冗余初始化:将变量
n1和n2的初始化移至外层循环内,避免在每次内层循环重复初始化(原代码中n1, n2, temp在内层循环外初始化,但实际应在每次外层循环重置)。
性能对比
- 原函数:在每次
append时可能频繁扩容切片,且循环控制复杂。 - 优化后:预分配内存减少分配次数,循环结构清晰,变量操作更高效。
运行优化后的函数会生成相同的结果(包含 1,250,000 个斐波那契数),但执行速度更快,尤其在大迭代次数下。您可以通过基准测试验证改进,例如使用 testing.B 在Go中测试性能。
如果目标是最大化CPU负载,可以考虑进一步优化,如使用循环展开或并行计算(例如goroutine),但当前优化已显著提升单线程性能。


