首页 > 其他分享 >golang技术降本增效的手段

golang技术降本增效的手段

时间:2023-07-28 11:47:16浏览次数:47  
标签:手段 err Person golang 降本增效 bufio 缓冲区 personPool Pool

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

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

比如池化、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利用缓冲区,减少频繁的系统调用

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

标签:手段,err,Person,golang,降本增效,bufio,缓冲区,personPool,Pool
From: https://www.cnblogs.com/JulianHuang/p/17587159.html

相关文章

  • Golang安装
    目录Go安装下载安装GoGo安装下载安装Go地址:https://studygolang.com/dl1、根据系统来选择下载包。2、我是Window,所以直接下载windows的安装包来安装。3、在控制台窗口输入“goversion”可查看Go版本,检测是否安装成功。4、配置环境变量。Go需要一个安装目录,还需......
  • Golang之工作区workspace
    快速开始创建工作区写一个最简单的基础项目实际演练一下 Goworkspace。首先,创建 workspace 工作区。$:mkdirworkspace$:cdworkspace$:goworkinit 完成以上步骤后,工作区目录就会出现一个新的文件 go.work .内容是这样的:go1.18因为工作区暂时是空的,所......
  • Golang中结构体映射mapstructure库深入详解
    mapstructure用于将通用的map[string]interface{}解码到对应的 Go 结构体中,或者执行相反的操作。很多时候,解析来自多种源头的数据流时,我们一般事先并不知道他们对应的具体类型。只有读取到一些字段之后才能做出判断 +目录在数据传递时,需要先编解码;常用的方式是JSON编解码......
  • Golang 规则引擎原理及实战
    本文主要介绍规则引擎在golang中的使用,将首先介绍golang中主要的规则引擎框架,然后利用golang原生的parser搭建一个简单的规则引擎实现基本的bool表达式解析工作。背景随着业务代码的不断迭代,诞生出了越来越多的if-else,并且if-else中的逻辑越来越复杂,导致代码逻辑复......
  • 想在golang里用好泛型还挺难的
    golang的泛型已经出来了一年多了,从提案被接受开始我就在关注泛型了,如今不管是在生产环境还是开源项目里我都写了不少泛型代码,是时候全面得回顾下golang泛型的使用体验了。先说说结论,好用是好用,但问题也很多,有些问题比较影响使用体验,到了不吐不快的地步了。这篇文章不会教你泛型......
  • golang channel 未关闭导致的内存泄漏
    现象某一个周末我们的服务oom了,一个比较重要的job没有跑完,需要重跑,以为是偶然,重跑成功,因为是周末没有去定位原因又一个工作日,它又oom了,重跑成功,持续观察,job在oom之前竟然占用了30g左右(这里我们的任务一个数据量都在内存中计算,所以这里数据量大一点)应用使用30g肯定是不正常......
  • 使用golang灵活处理动态文案
    代码packagescripts_stroageimport("fmt""github.com/duke-git/lancet/v2/slice""github.com/gogf/gf/util/gconv""github.com/gookit/goutil/dump""regexp""strings"&q......
  • 通过降本增效,提升测试价值
    近几年关于降本增效的话题越来越热,无论是各技术大会还是企业内部,关于降本增效的讨论和实践越来越多。比如研发效能、质量度量、精细化运营等,其本质都是在尽可能降低成本投入的前提下,提升生产效率,以求获得更高的投入产出比,企业获得更大的利润。那降本增效该如何在企业内落地呢?要......
  • golang 实现 RPC(远程过程调⽤实例)
    golang实现RPC 前提概要,先了解几个概念,websocket简介什么是websocketWebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的Websocket是一个持久化的协议webs......
  • Golang 中 Gin 框架开发学习记录 ——(二)
    4、响应页面  首先创建template文件夹将需要的hmtl文件放在里面,然后编写hmtl<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>我的GOweb页面</title><linkrel="stylesheet"href=&......