golang技术降本增效的手段

golang,技术,降本增效,手段 · 浏览次数 : 1497

小编点评

**优化技术总结** **1. 优化同步池** * 使用 `sync.Pool` 缓存临时对象。 * 通过设置默认值,简化对象创建。 * 使用 `Put` 方法重用对象,减少 GC 频率。 **2. 优化序列化** * 使用 `bytes.Buffer` 创建可变大小的字节缓存。 * 将 `[]byte` 转换为 `string`,方便字符串操作。 **3. 优化读取和写入** * 使用缓冲区读取数据,减少系统调用。 * 利用 `bufio` 库针对原始 `io.Writer` 创建带缓冲区的 `io.Writer`。 **4. 优化日志记录** * 使用开源的 `bufio` 库优化日志写入。 * 利用 `go` 中的 `sync.WaitGroup` 确保写入完成后关闭资源。 **5. 其他优化** * 使用 `golangC#eg` 中的 `PoolObjectPool` 来管理对象池。 * 使用 `BenchmarkWithoutPool` 和 `BenchmarkWithPool` 函数评估优化效果。 * 通过调整 `sync.Pool` 的参数,优化性能。 **最佳实践** * 使用 `sync.Pool` 缓存并重用对象。 * 使用 `bytes.Buffer` 优化字符串操作。 * 利用缓冲区和异步操作减少系统调用。 * 使用 `bufio` 库优化日志记录。 * 优化 `golangC#eg` 中的对象池。

正文

最近一年各大中小厂都在搞"优化",说到优化,目的还是"降本增效",降低成本,增加效益(效率)。

技术层面,也有一些降本增效的常规操作。

比如池化、io缓冲区技术

golang C# eg.
池化技术 snnc.Pool ObjectPool 前端切图仔,归入前端资源池 , 随用随取
字节数组缓冲区 bytes.Buffer List ...
io缓冲区 bufio BufferStream 适度超前,赛道埋伏

池化技术 sync.Pool

sync.Pool位于标准库,该文件提供了对临时对象的重复使用能力, 避免了频繁的gc, 对并发协程是安全的。

该文件只有三个控制点:

  • New: 默认的临时对象
  • Get: 从池中哪一个临时对象
  • Put: 放回池中,以重用

下面使用基准测试进行b.N*1000次运算时的内存消耗。

package main

import (
	"sync"
	"testing"
)

type Person struct {
	Age int
}

var (
	personPool = sync.Pool{
		New: func() interface{} {  // 设置默认值
			return &Person{}
		},
	}
)

func ExampleObjPool() {
	var p *Person
	for i := 0; i < 1000; i++ {
		for j := 0; j < 1000; j++ {
			p = personPool.Get().(*Person)
			p.Age = i + 1
			personPool.Put(p)
		}
	}
	p = personPool.Get().(*Person)
	fmt.Println(p.Age)
	// output:1000
}

func BenchmarkWithoutPool(b *testing.B) {
	var p *Person
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000; j++ {
			p = new(Person)    // 每次均产生临时对象
			p.Age = 23
		}
	}
}

func BenchmarkWithPool(b *testing.B) {
	var p *Person
	b.ReportAllocs()
	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		for j := 0; j < 1000; j++ {
			p = personPool.Get().(*Person)  // 从池中复用对象
			p.Age = 23
			personPool.Put(p)     // 放回以重用
		}
	}
}

测试结果如下,sync.Pool[重用临时对象]的性能可见一斑。

bytes.Buffer

golang很多方法内充斥了[]byte, 就连最常规的序列化/反序列化,返回值/参数都是[]byte, 但是slice是一个冷冰冰的数据结构,没有得心趁手的操作行为,还有很多陷阱。

  func Marshal(v any) ([]byte, error)
  func Unmarshal(data []byte, v any) 

A bytes.Buffer is a variable-sized buffer of bytes with Read and Write methods.

坦白讲bytes.Buffer并非底层优化机制, 实际提供了一个友好操作slice的方式。

下面的"abcd"字符串,先读取首字符、后面追加字符"e":

  var b bytes.Buffer
	b.Write([]byte("abcd")) // 写入之后,自动扩容
	rdbuf := make([]byte, 1)
	_, err := b.Read(rdbuf) // 读取一个字节的数据,移动读off指针
	if err != nil {
		panic(err)
	}
	fmt.Println(b.String()) // 上面读取了一个字符,读off已经移动,现从读off位置转换为string
	b.WriteByte('e')        // 在尾部写字符
	fmt.Println(b.String())
	fmt.Printf("%d, %d \n", b.Len(), b.Cap()) // Len方法返回还能读取的字符数量,Cap返回底层buf的容量
  
//output:
bcd 
bcde
4, 64

bufio

Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer object, creating another object (Reader or Writer) that also implements the interface but provides buffering and some help for textual I/O.

首先我们需要知道当应用程序执行IO操作(从文件、网络和数据库读取或写入数据),它将触发底层的系统调用,从性能角度来看,这很繁重。

缓冲IO是一种技术,用于在传递之前暂时积累IO操作的结果。这种技术可以通过减少系统调用的数量来提高程序的速度。例如,如果您想要逐字节地从磁盘读取数据,与每次直接从磁盘读取每个字节不同,使用缓冲区IO技术,我们可以一次将一个数据块读入缓冲区,然后消费者可以以任何您想要的方式从缓冲区读取数据。通过减少繁重的系统调用,性能将得到提高。

磁盘:1.寻址:ms(毫秒) 2.磁盘带宽:MB/s
内存:1.寻址:ns(纳秒) 2. 内存带宽:GB/s
磁盘比内存在寻址上慢了10W倍,传输带宽上慢了20倍。

开源的带缓冲区的logrus日志写入hook,就利用了bufio技术。

 // 利用bufio针对原始io.Writer封装成带缓冲区的io.Writer  
 `s.writer = bufio.NewWriterSize(s.Writer, size) 
  ......
  if len(bs) > s.writer.Available() && s.writer.Buffered() > 0 {
		if err := s.writer.Flush(); err != nil {
			return err
		}
	}
	_, err = s.writer.Write(bs)` 

优化总结

  • sync.Pool 复用临时对象,减少gc次数
  • bufio利用缓冲区,减少频繁的系统调用

研发人员历来都是公司的成本大头,技术优化虽然不能增效,但是能降本,减少核数和内存条,希望大家都能通过技术优化让自己不被优化。

本文会持续更新更多 后端优化思想,如果看客有什么不同意见,欢迎斧正。

与golang技术降本增效的手段相似的内容:

golang技术降本增效的手段

最近一年各大中小厂都在搞"优化",说到优化,目的还是"降本增效",降低成本,增加效益(效率)。 技术层面,也有一些降本增效的常规操作。 比如池化、io缓冲区技术 | | golang | C# | eg. | | | | | | | 池化技术 | snnc.Pool | ObjectPool | 前

巧如范金,精比琢玉,一分钟高效打造精美详实的Go语言技术简历(Golang1.18)

研发少闲月,九月人倍忙。又到了一年一度的“金九银十”秋招季,又到了写简历的时节,如果你还在用传统的Word文档寻找模板,然后默默耕耘,显然就有些落后于时代了,本次我们尝试使用云平台flowcv高效打造一份巧如范金、精比琢玉的高品质Golang技术简历。 首先来到云平台:flowcv.com 点击 t

区块链,中心去,何曾着眼看君王?用Go语言实现区块链技术,通过Golang秒懂区块链

区块链技术并不是什么高级概念,它并不比量子力学、泡利不相容原则、哥德巴赫猜想更难以理解,但却也不是什么类似“时间就是金钱”这种妇孺皆知的浅显道理。区块链其实是一套统筹组织记录的方法论,或者说的更准确一些,一种“去中心化”的组织架构系统。 去中心化 众所周知,任何一个公司、组织、或者是机构,都遵循同一

20个Golang片段让我不再健忘

本文使用代码片段的形式来解释在 go 语言开发中经常遇到的小功能点,由于本人主要使用 java 开发,因此会与其作比较,希望对大家有所帮助。

千姿百态,瞬息万变,Win11系统NeoVim打造全能/全栈编辑器(前端/Css/Js/Vue/Golang/Ruby/ChatGpt)

我曾经多次向人推荐Vim,其热情程度有些类似现在卖保险的,有的时候,人们会因为一些弥足珍贵的美好暗暗渴望一个巨大的负面,比如因为想重温手动挡的快乐而渴望买下一辆二十万公里的老爷车,比如因为所谓完美的音质而舍不得一个老旧的有线耳机,比如因为一个铜炉火锅而期待北京那漫长而寒冷的冬天。

新版以太坊Ethereum库ethersV5.0配合后端Golang1.18实时链接区块链钱包(Metamask/Okc)以及验签操作

区块链去中心化思想无处不在,比如最近使用个体抗原自检替代大规模的中心化核酸检测,就是去中心化思想的落地实践,避免了大规模聚集导致的交叉感染,提高了检测效率,本次我们使用Ethereum最新的ethersV5.0以上版本链接去中心化区块链钱包,并且通过后端Golang1.18服务进行验签。 在之前的一

周而复始,往复循环,递归、尾递归算法与无限极层级结构的探究和使用(Golang1.18)

所有人都听过这样一个歌谣:从前有座山,山里有座庙,庙里有个和尚在讲故事:从前有座山。。。。,虽然这个歌谣并没有一个递归边界条件跳出循环,但无疑地,这是递归算法最朴素的落地实现,本次我们使用Golang1.18回溯递归与迭代算法的落地场景应用。 递归思想与实现 递归思想并非是鲜为人知的高级概念,只不过

动手造轮子自己实现人工智能神经网络(ANN),解决鸢尾花分类问题Golang1.18实现

人工智能神经网络( Artificial Neural Network,又称为ANN)是一种由人工神经元组成的网络结构,神经网络结构是所有机器学习的基本结构,换句话说,无论是深度学习还是强化学习都是基于神经网络结构进行构建。关于人工神经元,请参见:人工智能机器学习底层原理剖析,人造神经元,您一定能看

防微杜渐,未雨绸缪,百度网盘(百度云盘)接口API自动化备份上传以及开源发布,基于Golang1.18

奉行长期主义的开发者都有一个共识:对于服务器来说,数据备份非常重要,因为服务器上的数据通常是无价的,如果丢失了这些数据,可能会导致严重的后果,伴随云时代的发展,备份技术也让千行百业看到了其“云基因”的成长与进化,即基于云存储的云备份。 本次我们使用Golang1.18完成百度网盘(百度云盘)接口AP

Golang 切片作为函数参数传递的陷阱与解答

作者:林冠宏 / 指尖下的幽灵。转载者,请: 务必标明出处。 GitHub : https://github.com/af913337456/ 出版的书籍: 《1.0-区块链DApp开发实战》 《2.0-区块链DApp开发:基于公链》 例子 切片作为函数参数传递的是值 用来误导切片作为函数参数传递的