Go 官方标准编译器中所做的优化

本文是对#102 Go 官方标准编译器中实现的优化集锦汇总[1] 内容的记录与总结.


alt

优化1-4: 字符串和字节切片之间的转化


alt

1.紧跟range关键字的 从字符串到字节切片的转换;


package main

import (
 "fmt"
 "strings"
 "testing"
)

var cs10086 = strings.Repeat("shuang!"10086)

func main() {
 fmt.Println(testing.AllocsPerRun(1, f)) //0
 fmt.Println(testing.AllocsPerRun(1, g)) //1

}

func f() {
 for range []byte(cs10086) {

 }
}

func g() {
 bs := []byte(cs10086)
 for range bs {

 }
}


f没有开辟内存,g开辟了一次内存.

alt

2.映射元素读取索引语法中被用做键值的 从字节切片到字符串的转换;


package main

import (
 "bytes"
 "fmt"
 "testing"
)

var name = bytes.Repeat([]byte{'x'}, 188)

var m = make(map[string]string10)
var s = ""

func main() {

 fmt.Println(testing.AllocsPerRun(1, f2)) //0
 fmt.Println(testing.AllocsPerRun(1, g2)) //1
 fmt.Println(testing.AllocsPerRun(1, h2)) //1
}

func f2() {
 s = m[string(name)] // 有效
}

func g2() {
 key := string(name)
 s = m[key] // 无效
}

func h2() {
 m[string(name)] = "Golang" // 无效
}

alt

3.字符串比较表达式中被用做比较值的 从字节切片到字符串的转换


package main

import (
 "fmt"
 "testing"
)

var x = []byte{1023'x'}
var y = []byte{1023'y'}

var b bool

func main() {
 fmt.Println(testing.AllocsPerRun(1, f3)) //0
 fmt.Println(testing.AllocsPerRun(1, g3)) //2

}

func f3() {
 b = string(x) != string(y)
}

func g3() {
 sx, sy := string(x), string(y)
 b = sx == sy
}

alt

4.含 非空字符串常量 的字符串衔接表达式中的 从字节切片到字符串的转换


package main

import (
 "fmt"
 "testing"
)

var p = []byte{1023'p'}

var q = []byte{1023'q'}

var str string

func main() {

 fmt.Println(testing.AllocsPerRun(1, f4)) //1
 fmt.Println(testing.AllocsPerRun(1, g4)) //3
}

func f4() {
 str = ("-" + string(p) + string(q))[1:]
}

func g4() {
 str = string(p) + string(q)
}

alt



5.[]rune(aString)转换的时间和空间复杂度都是O(n),但len([]rune(aString))中的此转换 不需要开辟内存


Go 1.12引入

package main

import (
 "fmt"
 "strings"
 "testing"
)

var shuang = strings.Repeat("shuang!"10086)

func main() {

 fmt.Println(testing.AllocsPerRun(1, f5)) //0
 fmt.Println(testing.AllocsPerRun(1, g5)) //1
}

func f5() {
 _ = len([]rune(shuang))
}

func g5() {
 _ = len([]byte(shuang)) //未对len([]byte(aString))做优化
}

alt



6.字符串衔接表达式只需开辟一次内存,无论需要衔接多少个字符串


package main

import (
 "fmt"
 "testing"
)

var h, i, j, k = "Hello""World""Let's""Go"

var str6 string

func main() {
 fmt.Println(testing.AllocsPerRun(1, f6)) //1
 fmt.Println(testing.AllocsPerRun(1, g6)) //3

}

func f6() {
 str6 = h + i + j + k
}

func g6() {
 str6 = h + i
 str6 += j
 str6 += k
}
alt



7.for i := range anArrayOrSlice{anArrayOrSlice[i]} = zeroElement} 形式 将被优化为一个内部的memclr操作


package main

const N = 1024 * 100

var arr [N]int

func clearArray() {
 for i := range arr {
  arr[i] = 0
 }
}

func clearSlice() {
 sli := arr[:]
 for i := range sli {
  sli[i] = 0
 }
}

func clearArrayPtr() {
 for i := range &arr {
  arr[i] = 0
 }
}
alt

benchmark:

package main

import (
 "testing"
)

func BenchmarkTest1(b *testing.B) {
 for i := 0; i < b.N; i++ {
  clearArray()
 }
}

func BenchmarkTest2(b *testing.B) {
 for i := 0; i < b.N; i++ {
  clearSlice()
 }
}

func BenchmarkTest3(b *testing.B) { //无效
 for i := 0; i < b.N; i++ {
  clearArrayPtr()
 }
}

执行结果:

goos: darwin
goarch: amd64
pkg: xxxx
cpu: Intel(R) Core(TM) i7-8557U CPU @ 1.70GHz
BenchmarkTest1-8           73000             15309 ns/op
BenchmarkTest2-8           76464             15167 ns/op
BenchmarkTest3-8           40194             30096 ns/op
PASS
ok      xxxx    4.213s



8.for k = range m {delete(m,k)}形式 将被优化为一个内部的map清空操作


alt



9.尺寸不大于4个原生字(即int),并且字段数不超过4个的结构体值被视为是小尺寸值


package main

type S1 struct {
 a int
}

type S2 struct {
 a, b int
}

type S3 struct {
 a, b, c int
}

type S4 struct {
 a, b, c, d int
}

type S5 struct {
 a, b, c, d, e int
}

type S6 struct {
 a, b, c, d, e, f int
}

var ss1, ss2, ss3, ss4, ss5, ss6 = make([]S1, 1000), make([]S2, 1000), make([]S3, 1000), make([]S4, 1000), make([]S5, 1000), make([]S6, 1000)

var x1, x2, x3, x4, x5, x6 int


benchmark:

package main

import "testing"

func Benchmark_Range1(b *testing.B) {
 for i := 0; i < b.N; i++ {
  for _, v := range ss1 {
   x1 = v.a
  }
 }
}

func Benchmark_Range2(b *testing.B) {
 for i := 0; i < b.N; i++ {
  for _, v := range ss2 {
   x2 = v.a
  }
 }
}

func Benchmark_Range3(b *testing.B) {
 for i := 0; i < b.N; i++ {
  for _, v := range ss3 {
   x3 = v.a
  }
 }
}

func Benchmark_Range4(b *testing.B) {
 for i := 0; i < b.N; i++ {
  for _, v := range ss4 {
   x4 = v.a
  }
 }
}

func Benchmark_Range5(b *testing.B) {
 for i := 0; i < b.N; i++ {
  for _, v := range ss5 {
   x5 = v.a
  }
 }
}

func Benchmark_Range6(b *testing.B) {
 for i := 0; i < b.N; i++ {
  for _, v := range ss6 {
   x6 = v.a
  }
 }
}

执行结果:

goos: darwin
goarch: amd64
pkg: xxxx
cpu: Intel(R) Core(TM) i7-8557U CPU @ 1.70GHz
Benchmark_Range1-8       4759434               248.4 ns/op
Benchmark_Range2-8       3910621               306.0 ns/op
Benchmark_Range3-8       3735921               328.9 ns/op
Benchmark_Range4-8       3677784               325.9 ns/op
Benchmark_Range5-8        814666              1517 ns/op
Benchmark_Range6-8        728656              1568 ns/op
PASS
ok      xxxx     8.868s
alt

因为很多一等公民,其底层结构体的元素,都没有超过4个




10.接口值包裹 指针值 比 包裹 其他类型的值 要快


package main

var p, p2 = new([100]int), new([100]int)

var ip interface{}

package main

import "testing"



func Benchmark_PointerAssign(b *testing.B) {
 for i := 0; i < b.N; i++ {
  p = p2
 }
}

func Benchmark_BoxPointer(b *testing.B) {
 for i := 0; i < b.N; i++ {
  ip = p
 }
}

func Benchmark_PointerAssert(b *testing.B) {
 for i := 0; i < b.N; i++ {
  p = ip.(*[100]int)
 }
}


goos: darwin
goarch: amd64
pkg: xxxx
cpu: Intel(R) Core(TM) i7-8557U CPU @ 1.70GHz
Benchmark_PointerAssign-8       1000000000               0.5251 ns/op          0 B/op          0 allocs/op
Benchmark_BoxPointer-8          1000000000               0.5833 ns/op          0 B/op          0 allocs/op
Benchmark_PointerAssert-8       1000000000               0.6418 ns/op          0 B/op          0 allocs/op
PASS
ok      xxxx   2.372s

alt
alt



11.接口值包裹 指针值 比 包裹 其他类型的值 要快


Go 1.15新增优化

package main

var x,y = 255,256

var ix,iy interface{}

package main

import "testing"

func Benchmark_x(b *testing.B) {

 for i := 0; i < b.N; i++ {
  ix = x
 }
}

func Benchmark_y(b *testing.B) {

 for i := 0; i < b.N; i++ {
  iy = y
 }
}


goos: darwin
goarch: amd64
pkg: xxxx
cpu: Intel(R) Core(TM) i7-8557U CPU @ 1.70GHz
Benchmark_x-8           565624285                2.033 ns/op           0 B/op          0 allocs/op
Benchmark_y-8           92127024                12.71 ns/op            8 B/op          1 allocs/op
PASS
ok      xxxx     2.653s
alt



12.Bounds Check Elimination


alt
alt
alt
alt
alt
alt

参考资料

[1]

#102 Go 官方标准编译器中实现的优化集锦汇总: https://www.bilibili.com/video/BV1YZ4y1K7w2

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/117820.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图像翻拍检测——反射分量分离的特征融合

随着计算机技术的迅速发展&#xff0c;需要建立人与信息一一对应的安保认证技术&#xff0c;通过建立完整的映射网络体系&#xff0c;从而确保每个人的人身、财产、隐私等的安全.与指纹、基因等人体生物特征识别系统相比&#xff0c;人脸识别系统更加友好&#xff0c;不需要人的…

unity面试题(性能优化篇)

CPU 预处理、缓存数据 注释空的unity函数 运算cpu->gpu 减少昂贵计算(开方) 限制帧数 加载(预加载、分帧加载、异步加载、对象池) 慎用可空类型比较 避免频繁计算(分帧、隔帧) 算法优化 变体收集预热 使用clear操作代替容器的new操作 unity spine使用二进制格式…

Data Rescue Professional for Mac:专业的数据恢复工具

在数字化时代&#xff0c;我们的生活和工作离不开电脑和存储设备。但是&#xff0c;意外情况时常发生&#xff0c;例如误删除文件、格式化硬盘、病毒攻击等&#xff0c;这些都可能导致重要的数据丢失。面对数据丢失&#xff0c;我们迫切需要一款可靠的数据恢复工具。今天&#…

CentOS 8 安装 Code Igniter 4

在安装好LNMP运行环境基础上&#xff0c;将codeigniter4文件夹移动到/var/nginx/html根目录下&#xff0c;浏览器地址栏输入IP/codeigniter/pulbic 一直提示&#xff1a; Cache unable to write to "/var/nginx/html/codeigniter/writable/cache/". 找了好久&…

文献阅读:Semantic Communications for Speech Signals

目录 论文简介动机&#xff1a;为什么作者想要解决这个问题&#xff1f;贡献&#xff1a;作者在这篇论文中完成了什么工作(创新点)&#xff1f;规划&#xff1a;他们如何完成工作&#xff1f;自己的看法(作者如何得到的创新思路) 论文简介 作者 Zhenzi Weng Zhijin Qin Geoffre…

【MySQL】用户管理

之前我们一直都使用root身份来对mysql进行操作&#xff0c;但这样存在安全隐患。这时&#xff0c;就需要使用MySQL的用户管理 目录 一、用户 1.1 用户信息 1.2 添加用户 1.3 删除用户 1.4 修改用户密码 二、用户权限 2.1 赋予授权 2.2 回收权限 一、用户 1.1 用户信息…

Kubernetes技术--使用kubeadm快速部署一个K8s集群

这里我们配置一个单master集群。(一个Master节点,多个Node节点) 1.硬件环境准备 一台或多台机器,操作系统 CentOS7.x-86_x64。这里我们使用安装了CentOS7的三台虚拟机 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多 2.主机名称和IP地址规划 3. 初始化准备工作…

Scala的函数式编程与高阶函数,匿名函数,偏函数,函数的闭包、柯里化,抽象控制,懒加载等

Scala的函数式编程 函数式编程 解决问题时&#xff0c;将问题分解成一个一个的步骤&#xff0c;将每个步骤进行封装&#xff08;函数&#xff09;&#xff0c;通过调用这些封装好的步骤&#xff0c;解决问题。 例如&#xff1a;请求->用户名、密码->连接 JDBC->读取…

【LeetCode】1654:到家的最少跳跃次数的解题思路 关于力扣无法return的BUG的讨论

文章目录 一、题目二、题解与代码三、神奇的BUG3.1 无法执行的 return 和 break 语句3.2 通过另一个 break 解决 一、题目 有一只跳蚤的家在数轴上的位置 x 处。请你帮助它从位置 0 出发&#xff0c;到达它的家。 跳蚤跳跃的规则如下&#xff1a; 它可以 往前 跳恰好 a 个位…

【C++深入浅出】类和对象上篇(类的基础、类的模型以及this指针)

目录 一. 前言 二. 面向对象与面向过程 2.1 面向过程 2.2 面向对象 三. 类的基础知识 3.1 类的引入 3.2 类的定义 3.3 成员变量的命名规则 3.4 封装 3.5 类的访问限定符 3.6 类的作用域 3.7 类的实例化 四. 类的对象模型 4.1 类对象的大小 4.2 类对象的存储方式 …

在 WSL2 中使用 NVIDIA Docker 进行全栈开发和深度学习 TensorFlow pytorch GPU 加速

在 WSL2 中使用 NVIDIA Docker 进行全栈开发和深度学习 TensorFlow pytorch GPU 加速 0. 背景 0.1 起源 生产环境都是在 k8d pod 中运行&#xff0c;直接在容器中开发不好嘛&#xff1f;每次换电脑&#xff0c;都要配配配&#xff0c;呸呸呸新电脑只安装日常用的软件不好嘛&…

【从0学习Solidity】合约入门 Hello Web3

【学习Solidity的基础】入门智能合约开发 Hello Web3 &#x1f4f1;不写代码没饭吃上架主页 在强者的眼中&#xff0c;没有最好&#xff0c;只有更好。我们是全栈开发领域的优质创作者&#xff0c;同时也是阿里云专家博主。 ✨ 关注我们的主页&#xff0c;探索全栈开发的无限…

【斗罗Ⅱ】最强武魂揭秘,98级玄老、95级言少哲神兽级武魂曝光

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析【绝世唐门】 在斗罗大陆动画绝世唐门中&#xff0c;98级玄老已经登场&#xff0c;他是一个很随意的老人&#xff0c;乍眼一看&#xff0c;似乎是一个邋里邋遢、好吃懒做的人&#xff0c;但是实际上他却是史莱克学院重量级…

Linux(CentOS7)下如何配置多个Tomcat容器?

一、在 liunx 系统安装 jdk 1、安装jdk&#xff08;yum install 安装&#xff09; 查看是否系统是否自带jdk并卸载 rpm -qa |grep java rpm -qa |grep jdk rpm -qa |grep gcj 其中&#xff0c;GCJ是GNU的Java编译器,可以把java程序编译成本地代码&#xff0c;编译成功后的可…

JixiPix Artista Impresso Pro for mac(油画滤镜效果软件)

JixiPix Artista Impresso pro Mac是一款专业的图像编辑软件&#xff0c;专为Mac用户设计。它提供了各种高质量的图像编辑工具&#xff0c;可以帮助您创建令人惊叹的图像。该软件具有直观的用户界面&#xff0c;使您可以轻松地浏览和使用各种工具。 它还支持多种文件格式&…

说说IO多路复用

分析&回答 IO多路复用 I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态(对应空管塔里面的Fight progress strip槽)来同时管理多个I/O流。直白点说&#xff1a;多路指的是多个socket连接&#xff0c;复用指的是复用一个…

非科班菜鸡算法学习记录 | 代码随想录算法训练营第53天|| 1143.最长公共子序列 1035.不相交的线 53. 最大子序和 动态规划

1143. 最长公共子序列 知识点&#xff1a;动规 状态&#xff1a;不会 思路&#xff1a; 用dpij表示两个串中到i-1和j-1个字符结束的最长公共子序列长度&#xff08;不用特殊初始化&#xff09; class Solution { public:int longestCommonSubsequence(string text1, string …

Web of Science批量导出

目录 如何用Web of Science检索学术信息问题批量导出 Web of Science检索结果 如何用Web of Science检索学术信息 进入 Web of Science 检索页面&#xff1a; https://www.webofscience.com/wos/woscc/basic-search 根据需求填写过滤条件&#xff0c;点击 search 进入搜索详…

C# char曲线控件

一、char曲线显示随机数数据 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using Syst…

完全平方数

题目链接 完全平方数 题目描述 注意点 返回 和为 n 的完全平方数的最少数量 解答思路 初始想到使用动态规划&#xff0c;后续数字的完全平方数可以由前面数字的完全平方数求得&#xff0c;对于任意数字&#xff0c;可以计算其减去从1…i之间&#xff08;保证做减操作后的值…