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开发的阳光网吧管理系统,纯手工敲打,系统管理员和用户角色,功能如下: 管理员:修改个人信息、修改密码;机房类型管理;机房管理;机位…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...
