Go 官方标准编译器中所做的优化
本文是对#102 Go 官方标准编译器中实现的优化集锦汇总[1] 内容的记录与总结.
优化1-4: 字符串和字节切片之间的转化
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开辟了一次内存.
2.映射元素读取索引语法中被用做键值的 从字节切片到字符串的转换;
package main
import (
"bytes"
"fmt"
"testing"
)
var name = bytes.Repeat([]byte{'x'}, 188)
var m = make(map[string]string, 10)
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" // 无效
}
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
}
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)
}
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))做优化
}
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
}
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
}
}
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清空操作
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
因为很多一等公民,其底层结构体的元素,都没有超过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
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
12.Bounds Check Elimination
参考资料
#102 Go 官方标准编译器中实现的优化集锦汇总: https://www.bilibili.com/video/BV1YZ4y1K7w2
本文由 mdnice 多平台发布
相关文章:
Go 官方标准编译器中所做的优化
本文是对#102 Go 官方标准编译器中实现的优化集锦汇总[1] 内容的记录与总结. 优化1-4: 字符串和字节切片之间的转化 1.紧跟range关键字的 从字符串到字节切片的转换; package mainimport ( "fmt" "strings" "testing")var cs10086 s…...
C语言程序设计——小学生计算机辅助教学系统
题目:小学生计算机辅助教学系统 编写一个程序,帮助小学生学习乘法。然后判断学生输入的答案对错与否,按下列任务要求以循序渐进的方式分别编写对应的程序并调试。 任务1 程序首先随机产生两个1—10之间的正整数,在屏幕上打印出问题…...
SQL自动递增的列恢复至从0开始
在许多数据库管理系统中,当你删除表格中的所有数据时,自动递增的列(也称为自增列、标识列或序列)的计数器通常不会重置为 0。这是出于性能和数据完整性方面的考虑,以避免因删除数据而导致的自增列值冲突。即使你删除了…...
介绍一下CDN
CDN(内容分发网络,Content Delivery Network)是一个由多个服务器组成的分布式网络,它的目的是将内容高效地传送到用户。下面是CDN的工作原理及其主要特点: 内容分发:当用户首次请求某一特定内容时ÿ…...
2023年最新 Github Pages 使用手册
参考:GitHub Pages 快速入门 1、什么是 Github Pages GitHub Pages 是一项静态站点托管服务,它直接从 GitHub 上的仓库获取 HTML、CSS 和 JavaScript 文件,(可选)通过构建过程运行文件,然后发布网站。 可…...
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 年以来不断发展,它支持所有经典的 NLP 任务,从标记化、词干提取、词性标记,包括语义索引和依赖关系解析。它还具有一组丰富的附加功能,例如内置语料库,NLP任务的不同模型以及与S…...
Java IDEA Web 项目 1、创建
环境: IEDA 版本:2023.2 JDK:1.8 Tomcat:apache-tomcat-9.0.58 maven:尚未研究 自行完成 IDEA、JDK、Tomcat等安装配置。 创建项目: IDEA -> New Project 选择 Jakarta EE Template:选择…...
leetcode316. 去除重复字母(单调栈 - java)
去除重复字母 题目描述单调栈代码演示进阶优化 上期经典 题目描述 难度 - 中等 leetcode316. 去除重复字母 给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对…...
零散笔记:《Spring实战》Thymeleaf
1、Thymeleaf模板就是增加一些额外元素属性的HTML,这些属性能够指导模板如何渲染request数据。 <p th:test "${message}">placeholder message</p> th我推测是中文的”替换“。 2、th:each,迭代元素集合。 <div th:each &qu…...
WordArt Designer:基于用户驱动与大语言模型的艺术字生成
AIGC推荐 FaceChain人物写真开源项目,支持风格与穿着自定义,登顶github趋势榜首! 前言 本文介绍了一个基于用户驱动,依赖于大型语言模型(LLMs)的艺术字生成框架,WordArt Designer。 该系统包含四个关键模块:LLM引擎、…...
【C进阶】深度剖析数据在内存中的存储
目录 一、数据类型的介绍 1.类型的意义: 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…...
巨人互动|游戏出海游戏出海的趋势如何
随着全球游戏市场的不断扩大和消费者需求的多元化,游戏出海作为游戏行业的重要战略之一,正面临着新的发展趋势。本文小编将讲讲游戏出海的趋势,探讨一下未来游戏出海的发展方向与前景。 巨人互动|游戏出海&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中以?区分以&拼接Body则是将请求参数放在请求体中 后端接受数据: 二、body中不同格式 2.1 multipart/form-data key - value 格式输入,主要特点是可以上…...
基于python+pyqt的opencv汽车分割系统
目录 一、实现和完整UI视频效果展示 主界面: 识别结果界面: 查看分割处理过程图片界面: 二、原理介绍: 加权灰度化 编辑 二值化 滤波降噪处理 锐化处理 边缘特征提取 图像分割 完整演示视频: 完整代码链…...
游戏设计的主要部分
游戏设计的主要部分 介绍 游戏设计是创建有趣、挑战性和令人满足的游戏体验的过程。它涵盖了许多方面,从概念开发到实际实施,以及最终的游戏测试和优化。游戏设计师需要考虑玩家的情感、技能挑战、故事情节、游戏世界等多个要素,以确保游戏…...
架构师成长之路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阳光网吧管理系统
项目介绍: 本系统使用jspservletmysql开发的阳光网吧管理系统,纯手工敲打,系统管理员和用户角色,功能如下: 管理员:修改个人信息、修改密码;机房类型管理;机房管理;机位…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
