当前位置: 首页 > news >正文

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 多平台发布

相关文章:

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

本文是对#102 Go 官方标准编译器中实现的优化集锦汇总[1] 内容的记录与总结. 优化1-4: 字符串和字节切片之间的转化 1.紧跟range关键字的 从字符串到字节切片的转换&#xff1b; package mainimport ( "fmt" "strings" "testing")var cs10086 s…...

C语言程序设计——小学生计算机辅助教学系统

题目&#xff1a;小学生计算机辅助教学系统 编写一个程序&#xff0c;帮助小学生学习乘法。然后判断学生输入的答案对错与否&#xff0c;按下列任务要求以循序渐进的方式分别编写对应的程序并调试。 任务1 程序首先随机产生两个1—10之间的正整数&#xff0c;在屏幕上打印出问题…...

SQL自动递增的列恢复至从0开始

在许多数据库管理系统中&#xff0c;当你删除表格中的所有数据时&#xff0c;自动递增的列&#xff08;也称为自增列、标识列或序列&#xff09;的计数器通常不会重置为 0。这是出于性能和数据完整性方面的考虑&#xff0c;以避免因删除数据而导致的自增列值冲突。即使你删除了…...

介绍一下CDN

CDN&#xff08;内容分发网络&#xff0c;Content Delivery Network&#xff09;是一个由多个服务器组成的分布式网络&#xff0c;它的目的是将内容高效地传送到用户。下面是CDN的工作原理及其主要特点&#xff1a; 内容分发&#xff1a;当用户首次请求某一特定内容时&#xff…...

2023年最新 Github Pages 使用手册

参考&#xff1a;GitHub Pages 快速入门 1、什么是 Github Pages GitHub Pages 是一项静态站点托管服务&#xff0c;它直接从 GitHub 上的仓库获取 HTML、CSS 和 JavaScript 文件&#xff0c;&#xff08;可选&#xff09;通过构建过程运行文件&#xff0c;然后发布网站。 可…...

docker 安装 Nginx

1、下载 docker pull nginx:latest 2、本地创建管理目录 mkdir -p /var/docker/nginx/conf mkdir -p /var/docker/nginx/log mkdir -p /var/docker/nginx/html 3、将容器中的相应文件复制到管理目录中 /usr/docker/nginx docker run --name nginx -p 80:80 -d nginxdocke…...

【NLP的python库(01/4) 】: NLTK

一、说明 NLTK是一个复杂的库。自 2009 年以来不断发展&#xff0c;它支持所有经典的 NLP 任务&#xff0c;从标记化、词干提取、词性标记&#xff0c;包括语义索引和依赖关系解析。它还具有一组丰富的附加功能&#xff0c;例如内置语料库&#xff0c;NLP任务的不同模型以及与S…...

Java IDEA Web 项目 1、创建

环境&#xff1a; IEDA 版本&#xff1a;2023.2 JDK&#xff1a;1.8 Tomcat&#xff1a;apache-tomcat-9.0.58 maven&#xff1a;尚未研究 自行完成 IDEA、JDK、Tomcat等安装配置。 创建项目&#xff1a; IDEA -> New Project 选择 Jakarta EE Template&#xff1a;选择…...

leetcode316. 去除重复字母(单调栈 - java)

去除重复字母 题目描述单调栈代码演示进阶优化 上期经典 题目描述 难度 - 中等 leetcode316. 去除重复字母 给你一个字符串 s &#xff0c;请你去除字符串中重复的字母&#xff0c;使得每个字母只出现一次。需保证 返回结果的字典序最小&#xff08;要求不能打乱其他字符的相对…...

零散笔记:《Spring实战》Thymeleaf

1、Thymeleaf模板就是增加一些额外元素属性的HTML&#xff0c;这些属性能够指导模板如何渲染request数据。 <p th:test "${message}">placeholder message</p> th我推测是中文的”替换“。 2、th:each&#xff0c;迭代元素集合。 <div th:each &qu…...

WordArt Designer:基于用户驱动与大语言模型的艺术字生成

AIGC推荐 FaceChain人物写真开源项目&#xff0c;支持风格与穿着自定义&#xff0c;登顶github趋势榜首&#xff01; 前言 本文介绍了一个基于用户驱动&#xff0c;依赖于大型语言模型(LLMs)的艺术字生成框架&#xff0c;WordArt Designer。 该系统包含四个关键模块:LLM引擎、…...

【C进阶】深度剖析数据在内存中的存储

目录 一、数据类型的介绍 1.类型的意义&#xff1a; 2.类型的基本分类 二、整形在内存中的存储 1.原码 反码 补码 2.大小端介绍 3.练习 三、浮点型在内存中的存储 1.一个例子 2.浮点数存储规则 一、数据类型的介绍 前面我们已经学习了基本的内置类型以及他们所占存储…...

TortoiseGit安装

一、安装Git环境 Git-2.42.0-64-bit.exe (访问密码: 1666)https://url48.ctfile.com/f/33868548-924037167-76e273?p1666 二、安装TortoiseGit TortoiseGit-2.14.0.1-64bit.msi (访问密码: 1666)https://url48.ctfile.com/f/33868548-924037173-d395c7?p1666 三、安装T…...

巨人互动|游戏出海游戏出海的趋势如何

随着全球游戏市场的不断扩大和消费者需求的多元化&#xff0c;游戏出海作为游戏行业的重要战略之一&#xff0c;正面临着新的发展趋势。本文小编将讲讲游戏出海的趋势&#xff0c;探讨一下未来游戏出海的发展方向与前景。 巨人互动|游戏出海&2023国内游戏厂商加快“出海”发…...

k8s 安装 istio(二)

3.3 部署服务网格调用链检测工具 Jaeger 部署 Jaeger 服务 kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/addons/jaeger.yaml 创建 jaeger-vs.yaml 文件 apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata…...

Postman中参数区别及使用说明

一、Params与Body 二者区别在于请求参数在http协议中位置不一样。Params 它会将参数放入url中以&#xff1f;区分以&拼接Body则是将请求参数放在请求体中 后端接受数据: 二、body中不同格式 2.1 multipart/form-data key - value 格式输入&#xff0c;主要特点是可以上…...

基于python+pyqt的opencv汽车分割系统

目录 一、实现和完整UI视频效果展示 主界面&#xff1a; 识别结果界面&#xff1a; 查看分割处理过程图片界面&#xff1a; 二、原理介绍&#xff1a; 加权灰度化 ​编辑 二值化 滤波降噪处理 锐化处理 边缘特征提取 图像分割 完整演示视频&#xff1a; 完整代码链…...

游戏设计的主要部分

游戏设计的主要部分 介绍 游戏设计是创建有趣、挑战性和令人满足的游戏体验的过程。它涵盖了许多方面&#xff0c;从概念开发到实际实施&#xff0c;以及最终的游戏测试和优化。游戏设计师需要考虑玩家的情感、技能挑战、故事情节、游戏世界等多个要素&#xff0c;以确保游戏…...

架构师成长之路Redis第二篇|Redis配置文件参数讲解

Redis.conf文件 官网Redis文档链接:Redis官网 官网Redis config配置文件参数讲解:https://redis.io/docs/management/config/ Redis.conf参考模板例子 : https://redis.io/docs/management/config-file/ Redis 可以使用内置的默认配置在没有配置文件的情况下启动,但是仅…...

jsp+servlet+mysql阳光网吧管理系统

项目介绍&#xff1a; 本系统使用jspservletmysql开发的阳光网吧管理系统&#xff0c;纯手工敲打&#xff0c;系统管理员和用户角色&#xff0c;功能如下&#xff1a; 管理员&#xff1a;修改个人信息、修改密码&#xff1b;机房类型管理&#xff1b;机房管理&#xff1b;机位…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...