Golang 提高性能的几个特性
1、值的高效处理和存储,允许创建紧凑的数据结构,避免不必要的填充字节。紧凑的数据结构能更好地利用缓存。更好的缓存利用率可带来更好的性能。
2、函数的调用有开销,减少函数调用开销的解决方案是内联。简单的函数可以被 Go 编译器内联。
3、强制垃圾回收使 Go 成为一种更简单,更安全的语言。这意味着在堆上分配的内存是有代价的。每次 GC 运行时都会花费 CPU 时间,直到释放内存为止。逃逸分析的重要性,增加变量在栈分配,减少在堆分配。
4、进程切换的开销很大,所以出现了线程,共享相同的内存空间。由于线程共享地址空间,因此它们比进程更轻,因此创建速度更快,切换速度更快。Goroutine 升华了线程。
Goroutine 可能会给禅让给其他协程时刻是:
-
阻塞式通道发送和接收。
-
Go 声明,虽然不能保证会立即调度新的 goroutine。
-
文件和网络操作式的阻塞式系统调用。
-
在被垃圾回收循环停止后。
每一个 Go 进程的操作系统线程相对较少,Go 运行时负责将可运行的 Goroutine 分配给空闲的操作系统线程。
5、进程地址空间有堆、栈来保存变量,堆自下而上,栈自上而下,防止相互穿透,有保护页,称为不可写内存区域。每个线程都会分配自己的栈,随着程序中线程数的增加,可用地址空间的数量会减少。Go 编译器不使用保护页,而是在每个函数调用时插入一个检查,以检查是否有足够的栈来运行该函数。如果没有,运行时可以分配更多的栈空间。为了解决热分裂问题,Go 1.3 采用了一种新的栈管理方法。如果 goroutine 的栈太小,则不会添加和删除其他栈段,而是分配新的更大的栈。旧栈的内容被复制到新栈,然后 goroutine 使用新的更大的栈继续运行。
总结:这五个特性一样强大,它们不是孤立存在的。例如,运行时将 goroutine 复用到线程上的方式在没有可扩展栈的情况下几乎没有效率。内联通过将较小的函数组合成较大的函数来降低栈大小检查的成本。逃逸分析通过自动将从实例从堆移动到栈来减少垃圾回收器的压力。逃逸分析还提供了更好的缓存局部性Cache Locality。如果没有可增长的栈,逃逸分析可能会对栈施加太大的压力。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现