Golang如何编写更省力的代码
Golang如何编写更省力的代码 继续讨论 Go 与绿色技术 - 你如何使用 Go 来保护环境?:
每次算法代码审查都会问“能否用更少的电力来完成”
我刚读到上面这段话,想知道这具体如何实现,我该如何测量代码的耗电量?有没有什么例子,展示一段高耗电的代码,然后如何重写它以消耗更少的能量?
hyousef:
我很好奇这是如何实现的,如何测量我的代码的耗电量?有没有一个高耗电的代码示例,然后进行重写…
非常简单:每个CPU操作都会消耗能量。尽量减少CPU操作。同时,每一点内存的使用也会消耗能量,尽量减少内存使用。
更多关于Golang如何编写更省力的代码的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
节能与硬件的设计和制造方式直接相关。
先生,您说得对。但请看看您陈述的实用性:您有一台已经制造好的机器,并在其上运行您的代码。对于您的代码需求而言,那台机器是静态的,它不会改变。
只要您的代码不是为特定机器设计、没有针对其特定规格进行优化以利用其特性,那么拥有更高效的代码就是有益的,即使在您升级机器时也是如此。
每个CPU操作都会消耗能量。尝试最小化CPU操作。同时,每一比特内存都会消耗能量,尝试最小化内存使用。
在我看来,在代码层面,这不会有太大帮助。节能与硬件的设计和制造方式直接相关。
在消费者层面,你可以考虑将你的应用程序部署在基于ARM或RISC-V的端点上(例如:Vision5 - https://www.youtube.com/watch?v=ykKnc86UtXg)。然而,这本身也有其需要应对的挑战。
总而言之,通用的绿色规则适用:仅部署你所消耗的;尽可能遵循3R原则。
hollowaykeanho:
充其量,我们只能优化算法,使其用更少的周期获得更好的性能,但效果是微乎其微的。
你为什么声称效果微乎其微?你是怎么知道的,你有什么证据?
hollowaykeanho:
在下次硬件更新时,考虑使用更环保的硬件,比如基于ARM或RISC-V的服务器和终端。
我强烈反对。你能使用的最环保的硬件就是你现有的硬件,这比制造一台新硬件要环保得多。同理,一辆二手车也比一辆新的电动汽车环保得多,仅仅是因为电动汽车需要先被制造出来。
3R 尽可能做到
在我看来,使用 Go 语言来减少、重用和回收代码有点困难。至少我在理解如何做到这一点上有些困难。例如,与其他驱动程序相比,sqlx(Postgresql)可以大大减少代码量,但它不被认为是生成静态类型代码的方式,因此不算是“地道的”Go 用法。
但有一种方法可以实现更好的代码(至少在 Web 开发中),那就是反复测量并修复问题。我自己经常使用 https://pagespeed.web.dev 来寻找提高速度的方法,从而减少整体影响。这不仅仅是电力消耗的问题。但 Web 开发还有其他一些挑战,因为它很复杂(例如托管、缓存、减少流量等)。
我在某处读到,只有大约 10% 的 Go 开发者使用 Go 进行 Web 开发。有人能证实这一点吗?
telo_tade:
只要你的代码不是为特定机器设计的,没有针对其特定规格进行优化,那么拥有更高效的代码总是有益的,即使在你升级机器之后。
代码仅仅是指令。我们最多只能优化算法,使其用更少的周期获得更好的性能,但效果是微乎其微的。用通俗的话来说:
- 我们需要进行食物配给(保持绿色环保)。
- 我可以用英语、普通话等语言工作(代码)。
- 我吃的食物是普通人的两倍(需要两倍的能量)。
- 最多,你可以用你的语言告诉我食物短缺,或者指着我的肚子让我开始减少消耗(告诉我用一倍的能量完成相同的输出)。
问题不在于说话或指肚子没有帮助;而是它产生的效果非常小(因为我仍然需要大约两倍的能量才能维持生存,否则我会饿死)。在这种情况下,我宁愿从其他角度来解决问题,比如:
- 雇佣另一个吃得比我少(少于两倍食物)但工作比我做得更好的人(硬件替换)。
- 研究自给自足的室内农业来源(使用可再生能源供电)。
- 优化我的工作安排,让一个只吃一倍食物的人处理日常任务,只在重大任务时叫我(调度优化,能效+性能协处理器)。
争论的焦点主要是从正确的角度来解决问题。
附注:不要灰心。我们(指活跃的维护者)无论如何都会为了可维护性而不断重构和优化我们的代码(例如性能优化等),所以你仍然会得到更好的代码。
telo_tade:
但看看你陈述的实用性:你已经有一台已经构建好的机器,你在上面运行你的代码。对于你的代码需求来说,那台机器是静态的,它不会改变。
这就是“只部署你消耗的资源”原则发挥作用的地方。如果你的机器还没有达到其投资回报时间线(通常是6年),请继续使用它。在那之后,你可以考虑使用虚拟机或容器(Docker等)进行优化,将你的计算服务整合到尽可能少的活跃硬件上。如果你能实现类似谷歌容器引擎的自动驾驶功能,那就更好了。
在下一次硬件更新时,考虑更环保的硬件,比如基于ARM或RISC-V的服务器和终端。
同时,别忘了回收旧硬件。
Sibert:
我在某处读到,只有大约10%的Go开发者将Go用于Web开发。有人能证实这一点吗?
据我所知并非如此。
来源:Go Developer Survey 2022 Q2 Results - The Go Programming Language,基于5752个数据源。
在Go中编写更节能的代码主要涉及优化算法效率、减少内存分配和利用并发。以下是一些具体示例:
1. 测量工具
可以使用runtime/pprof和runtime包来测量CPU和内存使用:
import (
"fmt"
"runtime"
"time"
)
func measurePowerUsage() {
var m1, m2 runtime.MemStats
start := time.Now()
runtime.ReadMemStats(&m1)
// 你的代码在这里
runtime.ReadMemStats(&m2)
elapsed := time.Since(start)
memUsed := m2.TotalAlloc - m1.TotalAlloc
fmt.Printf("执行时间: %v, 内存分配: %v bytes\n", elapsed, memUsed)
}
2. 高耗电 vs 节能代码示例
示例1:字符串拼接优化
高耗电版本:
func buildStringHighPower(data []string) string {
var result string
for _, s := range data {
result += s // 每次都会分配新内存
}
return result
}
节能版本:
func buildStringLowPower(data []string) string {
var builder strings.Builder
builder.Grow(len(data) * 10) // 预分配内存
for _, s := range data {
builder.WriteString(s)
}
return builder.String()
}
示例2:算法复杂度优化
高耗电版本(O(n²)):
func findDuplicatesHighPower(arr []int) []int {
duplicates := []int{}
for i := 0; i < len(arr); i++ {
for j := i + 1; j < len(arr); j++ {
if arr[i] == arr[j] {
duplicates = append(duplicates, arr[i])
}
}
}
return duplicates
}
节能版本(O(n)):
func findDuplicatesLowPower(arr []int) []int {
seen := make(map[int]bool)
duplicates := make([]int, 0, len(arr)/2)
for _, num := range arr {
if seen[num] {
duplicates = append(duplicates, num)
} else {
seen[num] = true
}
}
return duplicates
}
示例3:并发处理优化
高耗电版本(顺序处理):
func processItemsHighPower(items []Item) []Result {
results := make([]Result, len(items))
for i, item := range items {
results[i] = processItem(item) // 顺序处理
}
return results
}
节能版本(并发处理):
func processItemsLowPower(items []Item) []Result {
results := make([]Result, len(items))
var wg sync.WaitGroup
sem := make(chan struct{}, runtime.NumCPU()) // 限制并发数
for i, item := range items {
wg.Add(1)
sem <- struct{}{}
go func(idx int, it Item) {
defer wg.Done()
results[idx] = processItem(it)
<-sem
}(i, item)
}
wg.Wait()
return results
}
示例4:内存复用
高耗电版本:
func processBatchHighPower(batches [][]byte) {
for _, batch := range batches {
result := make([]byte, len(batch)) // 每次分配新内存
// 处理逻辑
_ = result
}
}
节能版本:
func processBatchLowPower(batches [][]byte) {
var buffer []byte
for _, batch := range batches {
if cap(buffer) < len(batch) {
buffer = make([]byte, len(batch))
} else {
buffer = buffer[:len(batch)]
}
// 复用buffer处理
_ = buffer
}
}
3. 使用pprof进行性能分析
import (
"os"
"runtime/pprof"
)
func profileCode() {
f, _ := os.Create("cpu.prof")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
// 你的代码在这里
}
4. 实际节能技巧
- 使用
sync.Pool重用对象 - 避免不必要的内存分配
- 使用适当的数据结构
- 批量处理减少系统调用
- 合理设置GOMAXPROCS
这些优化通过减少CPU计算时间和内存分配,直接降低了电力消耗。在实际环境中,可以通过监控系统的功率计或云服务商的能耗报告来验证效果。

