惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Blog of Author Tim Ferriss
S
Schneier on Security
H
Help Net Security
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog
云风的 BLOG
云风的 BLOG
H
Hacker News: Front Page
C
Check Point Blog
P
Privacy International News Feed
IT之家
IT之家
爱范儿
爱范儿
AWS News Blog
AWS News Blog
The Hacker News
The Hacker News
Stack Overflow Blog
Stack Overflow Blog
Project Zero
Project Zero
Microsoft Azure Blog
Microsoft Azure Blog
量子位
The Cloudflare Blog
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
I
Intezer
Martin Fowler
Martin Fowler
Scott Helme
Scott Helme
酷 壳 – CoolShell
酷 壳 – CoolShell
A
Arctic Wolf
T
Threat Research - Cisco Blogs
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
The Exploit Database - CXSecurity.com
B
Blog
Simon Willison's Weblog
Simon Willison's Weblog
U
Unit 42
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
博客园_首页
J
Java Code Geeks
K
Kaspersky official blog
Webroot Blog
Webroot Blog
C
CERT Recently Published Vulnerability Notes
H
Heimdal Security Blog
G
Google Developers Blog
T
Tor Project blog
W
WeLiveSecurity
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Blog — PlanetScale
Blog — PlanetScale
小众软件
小众软件
有赞技术团队
有赞技术团队

蛮荆

如何获取更多的免费服务器 Kubernetes 调度器队列 - 设计与实现 Kubernetes 调度器 - 核心流程 Kubernetes Networking Model & CNI Kubernetes 控制器管理总结 Kubernetes CronJob 设计与实现 Kubernetes Job 设计与实现 Kubernetes HPA 设计与实现 Kubernetes Deployment 滚动更新实现原理 Kubernetes GC 设计与实现 Kubernetes Pod 驱逐 - 设计与实现 Kubernetes Daemonset 设计与实现 Kubernetes ReplicaSet 设计与实现 Kubernetes EndPoint 设计与实现 Kubernetes Informer 设计与实现 降本增效之应用优化 (三) 日志存储与检索 Kubernetes Pod 设计与实现 - 创建流程 Kubernetes 探针设计与实现 Unix 编程艺术名句摘录 Kubernetes - CRI 概述 Kubernetes Pod 设计与实现 - Pause 容器 Kubernetes - kube-proxy 代理模式工程优化 Kubernetes 应用最佳实践 - 优雅关闭长连接 Kubernetes Service 类型和会话亲和性 Kubernetes 为什么需要 Ingress Kubernetes 架构 - 控制平面和数据平面 降本增效之应用优化 (二) 大报表 Go 语言如何获取 CPU 利用率 降本增效之应用优化 (一) Redis 业务规则引擎演变过程简述 微服务中的熔断算法 漏桶算法和令牌桶算法 jsonparser 为什么比标准库的 encoding/json 快 10 倍 ? zap 高性能设计与实现 HTTP Router 算法演进 fastcache 高性能设计与实现 Web 常见的三个安全问题 ants Code Reading Go 线程安全 map 方案选型 布隆过滤器 死锁、活锁、饥饿、自旋锁 sync.Pool Code Reading Go 内存管理概述 Go netpoll Code Reading goroutine 泄漏与检测 time/Timer Code Reading GMP Scheduler Code Reading Go channel 的 15 条规则和底层实现 为什么 Linux “一切皆文件” context.Context Code Reading runtime/HACKING.md Goland 最佳实践 互联网开发与金庸武学 为什么 Redis 6.0 引入多线程模型? Kubernetes 应用最佳实践 - 金丝雀发布 容器中如何正确配置 GOMAXPROCS ? singleflight Code Reading sync.Map Code Reading sync.Cond Code Reading sync.WaitGroup Code Reading sync.RWMutex Code Reading sync.Mutex Code Reading sync.Once Code Reading Go 无锁编程 sync/atomic Code Reading goroutine 交替打印奇偶数 GODEBUG Go 并发模式 Go 汇编 UUID 通用技术选型 Kubernetes 应用最佳实践 - 水平自动伸缩 Go 高性能 Tips fasthttp 为什么比标准库 net/http 快 10 倍 ? 技术文章配图指南 ChatGPT 初体验 Docker 网络原理概览 iptables 的五表五链 Kubernetes 应用最佳实践 - 亲和性和污点容忍度 Go 的反射与三大定律 Docker 官方提供的最佳实践 Go 语言内置的设计模式 HTTP1 到 HTTP3 的工程优化 Kubernetes 应用最佳实践 - Sidecar 模式 Kubernetes 应用最佳实践 - init 容器和钩子函数 为什么 recover 必须在 defer 中调用? 为什么 defer 的执行顺序和注册顺序不同? Go map 设计与实现 Go 切片扩容底层实现 Go 语言中的零拷贝 Go Delve 云原生和边缘计算简介 Kubernetes Pod 服务质量等级 Kubernetes 应用最佳实践 - 探针 Kubernetes 应用最佳实践 - 资源请求和限制 CDN 原理 Kubernetes 应用最佳实践 - 开篇 缓存策略和模式 Go 内存模型 Kubernetes 核心概念 软件版本语义化
Golang 编译速度为什么这么快?
2023-10-28 · via 蛮荆

2023-10-28 Golang

概述

开始接触 GO 语言的时候,笔者已经拥有 C/C++, Java 三种静态语言和 PHP, Javascript 两种动态语言的基础。正因为如此,在入门 Go 语言的过程中, 第一次编译一个几百行的 demo 文件时,着实被其编译速度惊到了,当时心中感慨: “Go 语言号称静态语言的执行速度,动态语言的编译速度,果然名不虚传”。 事实上,Google 发明 Go 语言的核心诉求就是解决其内部的大型项目代码每次构建时都需要花费很长时间的问题,抛开技术的产生历史背景, 本文着重介绍一下 Go 语言编译速度背后的主要优化方案。

极简关键字

Go 语言只有 25 个关键字,这有助于缩短编译时间。

符号表

符号表是编译器中的一种数据结构,用于存储程序中的标志符 (变量、函数、结构体/对象) 等,主要作用是提供了一个管理程序中的各种标志符的快捷方式, 以便在程序编译的不同阶段进行引用、解析、优化等工作。

Go 语言中并没有直接 (显式) 的符号表,编译器会在编译过程中创建一些内部数据结构来管理标志符和类型信息,虽然这些内部数据结构直接暴露给开发者使用的符号表, 但是可以看做是编译器的 “内部符号表”。此外,Go 语言提供了反射 (Reflection) 机制,可以在运行时获取类型、结构体字段、调用方法/堆栈 等, 也可以获取和修改对象的字段,开发者可以通过这种间接的方式获取类似符号表的信息。

依赖分析

这是 Go 语言编译速度性能提升的主要原因

消除循环依赖

循环依赖示例

Go 语言出现循环依赖会在编译时报错,在开发者解决了循环依赖问题之后,编译过程只需要递归到依赖关系树的底部即可,本质上就是一个 DFS (深度优先搜索) 过程。 此外在没有循环依赖的前提下,每个包可以独立并行编译。

依赖简化

Go 语言代码文件中只需要包含直接在代码中使用到的包名,例如当我们需要使用 Cookie 对象时, 只需要引入 cookiejar 包即可,不需要引入 http 包。

package main

import "net/http/cookiejar"

func main() {
	var c cookiejar.Jar
}

与此同时,Go 语言中引入未使用的包也会产生编译错误:

imported and not used:  ...

这个编译前置约束可以保证不相关的包对编译时间造成影响。

最后,Go 语言规定源文件中所有使用到的包必须在文件开始处 (package 语句之后) 全部列出,因此编译器无须读完整个文件内容就可以确定依赖关系。 已经编译完成的 Go 包的目标文件不仅记录了包文件的导出信息,还记录了其本身依赖的包导出信息,编译时每次导入一个目标文件即可,不需要查看其他信息。

不支持重载/重写

Go 语言不支持方法重写和方法重载,也就是说,所有的方法都可以视为静态类型的,就像 Java 里面的 static 方法。

class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!"); 
    }
}

不支持模板

Go 语言同样不支持模板方法,这可以避免模板实例化带来的性能开销。

无须虚拟机

Go 语言和 Java 一样,也是自带 GC 的语言,但是不同的地方在于,Java 是在虚拟机中编译的,因此 Java 代码在通过编译器之前必须先编译为字节码, 但是 Go 不依赖虚拟机编译代码,而是直接从源代码编译为二进制文件。

Reference