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

推荐订阅源

Vercel News
Vercel News
O
OpenAI News
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
罗磊的独立博客
S
SegmentFault 最新的问题
The Register - Security
The Register - Security
Hugging Face - Blog
Hugging Face - Blog
D
DataBreaches.Net
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
雷峰网
雷峰网
V
Visual Studio Blog
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
N
Netflix TechBlog - Medium
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog
博客园 - 【当耐特】
G
Google Developers Blog
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
Martin Fowler
Martin Fowler
F
Fortinet All Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Cloudflare Blog
AI
AI
Google Online Security Blog
Google Online Security Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - Franky
Blog — PlanetScale
Blog — PlanetScale
Webroot Blog
Webroot Blog
PCI Perspectives
PCI Perspectives
爱范儿
爱范儿
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org

文章列表 on polarisxu

通过一个例子让你彻底掌握 Go 工作区模式 这道题正确率竟然只有 22% Go 开源项目推荐:一个简单的 Go 练手项目 go test 如何禁用缓存? Go1.18 快讯:constraints 包被移除标准库 跟着 Go 作者学泛型 「2022 版」轻松搞定 Go 开发环境 鹅厂小哥用行动反对加班:程序员加班能被终结吗? Go 为什么选择 Gopher 作为吉祥物? 本地如何配置多个 GitHub/Gitee 账号? 为 Java 开发者准备的 Go 教程 02:Java 有而 Go 无 GitHub 发现了 studygolang 项目依赖的漏洞 Typora 宣布收费后,这款开源 Markdown 编辑器火了 为 Java 开发者准备的 Go 教程 01:漫游了 我的 2021 年终总结 泛型版 singleflight:Go 中如何防止缓存击穿? 2021 年你写了多少代码?这个 Go 工具帮你统计 Go1.18 新特性:TryLock Go 泛型入门教程 程序员瑞士军刀:各种结构的转换工具 终于有 Go 版的 Elasticsearch 了 Go泛型系列:maps 包讲解 Go 1.18 中的 any 是什么? Go1.18 快讯:新的 IP 包 Go编程模式:详解函数式选项模式 Go泛型系列:slices 包讲解 Nginx 竟然也有 playground — Go 语言构建的 Go泛型系列:Go1.18 类型约束那些事 Go1.18 快讯:Module 工作区模式 Go1.18 快讯:新增的 Cut 函数太方便了 Go1.18 快讯:废弃了这个 API Go1.18 快讯:新增字符串 Clone API Go:如何获得项目根目录? Go 如何获取和设置环境变量 重磅变动:更快找到微信公众号里的Go文章 Go 这样设置版本号:我们的项目也可以 假期结束,推荐 2 本 manning 出的 Go 图书 Go Fiber 框架系列教程 04:测试应用 Go Fiber 框架系列教程 03:中间件 Go泛型系列:提前掌握Go泛型的基本使用 推荐一个 Go GUI 实战项目 Go Fiber 框架系列教程 02:详解相关 API 的使用 Go Fiber 框架系列教程 01: 和 Express 对比学习 Go Module:私有不合规库怎么解决引用问题 Go1.17 新特性:go get 变了 Go1.17 新特性:testing 包的相关变化 StackOverflow 上关于 Go select 死锁的问题 新书推荐:用 Gin 框架构建分布式应用 Go 官网要变天。。。 Gin 这是要成为 Go 官方框架? 扬眉吐气:刚刚,Go 已经默认支持泛型了 Go 1.17 新特性:Module 有哪些变化? Go 第三方库推荐:类型转换如此简单 担心密码提交到 GitHub?建议使用这个 Go 开源工具 Go 的时间格式化为什么是 2006-01-02 15:04:05? GitHub 为 Go 社区带来安全支持 Go开源项目推荐:500行代码确认请求时间花在哪 一道关于 len 函数的诡异 Go 面试题解析 厉害了我的 Go:推荐系统都有开源实现 Go1.17 新特性:新版构建约束 这个工具真好:看看你的Go项目依赖有无漏洞 网友很强大,发现了Go并发下载的Bug Rust 劝退系列 09:函数 Go项目实战:一步步构建一个并发文件下载器 这本 Go 新书挺期待的:100 个常见错误 Go 启用新的官方问答社区 这是要干嘛?!微软招 Go 编译器全职开发人员 Go1.17 快报之标准库越来越注重易用性 Go1.17 新特性之切片变数组 回顾 Go 官网的演变史 站长8年前的Go代码竟然进入大厂的项目里了 Go图书翻译:一个好消息,一个坏消息 不怕烂尾!决定组织翻译这本 Go 图书 Rust 劝退系列 08:模式匹配 一本花了2.5年写成的Go免费在线图书 被黑惨了:一句话,说明自己会 Go,咋整? Go1.16 中的新函数 signal.NotifyContext 怎么用? Go 1.17 新特性提前学之测试执行随机化 Rust 劝退系列 07:流程控制 官方的 Go 多版本管理:使用和原理 Rust新书:给你一个劝退的理由 周刊题解:常量表达式这个规则应该了解下 盘点那些使用 Go 语言的国外公司 编写了50万行Go代码是一种什么体验 Rust 劝退系列 06:常量 Uber 使用 Go 的规模这么大?!都自己定制的 Go 编译器了 Go Team Leader — rsc 大神新开源了一个库,增强模板功能 再一次看到了 Go 的节制:int128 类型要不要支持? Rust 劝退系列 05:复合数据类型 「卷」有理论依据:海勒姆定律—Go又是怎么卷的 Go 真的也可以进行 GUI 开发:还有这样的图书呢 Rust 劝退系列 04:基本数据类型 我的 Go 语言书单 Rust 劝退系列 03:变量 我又来推荐免费 Go 新书了:一本用 Go 讲架构的书 注释竟然还有特殊用途?一文解惑 //go:linkname 指令 这个功能,公众号、微信群会不会被玩坏? 一道 Go 闭包题,面试官说原来自己答错了:面别人也涨知识 Rust 劝退系列 02:第一个 Rust 程序 Rust 劝退系列 01:打造开发环境
优化Go应用性能就是在浪费时间?
2021-03-17 · via 文章列表 on polarisxu

原文标题:Writing slower Go programs。作者认为应该优化可读性,而不是优化性能。你认可吗?一起看下该文。本文不代表 Go语言中文网 的观点。

什么?写更慢的 Go 程序?难道我们不应该关注如何让 Go 程序更快吗?

实际不是的。为了性能而优化 Go 代码几乎肯定在浪费你的时间,原因有以下几点:

  • 性能并不重要(Performance doesn’t matter);
  • Go 本身就够快;
  • 可读性胜过速度;

以上几个简短的陈述,有些人可能不服,所以需要做一些阐述。需要说明的是,并非全部如此,肯定存在例外情况,这里只说大部分时候。而且,这三点很难在工程师中达成共识。所以,你可以随意发表你的看法,甚至可以说这是有史以来最垃圾的文章,但还是继续读下去吧。

性能并不重要

对于我们大多数人编写的大多数程序来说,它们执行的速度到底有多快并不重要。例如,以下是我最近参与的一些项目:

  • 网站链接检查器(抓取网站,以找到和报告中断的链接)
  • Terraform 提供程序(通过 Terraform 代码管理站点监视检查)
  • 数据分析器(下载和计算监测数据的统计表)
  • 站点迁移工具(在服务器之间移动网站文件和数据库)

所有这些程序运行相对较少(可能一天一到两次),运行时间很短(一到两分钟)。这样的情况,值得花费任何工程上的努力让它们变得更快吗?几乎可以肯定不值得。(如果你已经被说服了,你可以停止阅读,但我觉得我可能需要再多说一点。)

即使在我们关心程序快速运行的极少数情况下,问题也不在于 Go 代码。例如,链接检查器 99% 的时间都花在等待 HTTP 请求上。Terraform 提供者将大部分时间用于对远程 API 进行通信和监听。站点迁移工具的瓶颈是通过网络复制数千兆字节的 tarballs。

因此,如果我们确实需要对这些程序进行性能优化,我们不会在 Go 级别进行这种优化。CPU 比内存访问快得离谱,内存访问比磁盘访问快得多,磁盘访问比网络访问快得多,网络访问比交互式用户快得多。因此,代码的执行速度可能是我们最不需要担心的事情。

当每个 ns/op 都很重要时

“等一下,伙计,我正在编写 3D 游戏,而且我的预算非常紧张。每十亿分之一秒都很重要,而你却说我不用担心性能?你是大笨蛋吧?”

没有。游戏是这个规则的一个合理的例外,因为游戏代码的某些小部分(例如着色器)是速度的关键。不过,请注意,即使在这里我们也引入了一个警告:性能只对游戏代码的一个小子集有影响。除非您从头开始编写 3D 引擎(不要这样做)),否则您自己的代码不太可能成为框架绘制的瓶颈。

你不是谷歌,也不是太空人

但是大多数 Go 程序不是游戏。还有其他例外吗?是的:网络服务器,如 web 服务器和 api 有性能关键部分。在一个大型、复杂的分布式系统中,总体请求延迟非常重要,因此每个子系统的延迟可以下降到纳秒。再说一次,你和我都不太可能编写这样的程序,当我们这样做的时候,我们最好知道我们在做什么。(polarisxu 译注:但 Web 和 API 开发可是 Go 目前主要的战场)

当然,还有很多特殊用途的嵌入式系统需要速度,比如 i/o 驱动程序,实时硬件,比如卫星和工业控制系统,我允许你对所有这些进行例外处理,但是我坚定地认为它们并不代表典型的 Go 程序员的 Go 程序。(polarisxu 译注:我无言以对)

即使性能不是大多数程序的主要考虑因素,但这并不意味着我们不应该考虑它。作为程序员,您所做的选择会影响程序的性能,包括内存和磁盘使用以及原始速度。有可能编写的程序执行得非常糟糕,以至于它们使用起来很慢,令人恼火,或者浪费资源,比如一次性将整个文件读入内存,而不是一行一行地处理它。

然而,一般来说 Go 程序是相当快速和高效的。如果你是从 Ruby、 PHP 或 Python 这样的解释性语言开始转向 Go 的,那么 Go 可以简单地快速运行。这主要是因为它是一门编译语言。任何解释器,无论多么聪明或多么经过优化,都无法与编译成纯机器代码的某些东西的性能相匹配。

轻装上阵

编译后的 Go 程序也很小。解释器又大又复杂,在开始执行程序之前,它们需要做大量的工作来解释程序。您需要将解释器与程序一起分发。

相比之下,Go 二进制文件只包含程序本身的机器代码,加上 Go 运行时,后者提供了 goroutine 和垃圾收集等功能。这使得 Go 程序在内存和磁盘使用方面更轻松,执行更快,并且易于构建、打包和分发。

首选需要优化的是选择合适的语言

因此,我们通常不需要太担心我们的代码在 Go 中的性能,因为我们从一个非常快的基线开始,感谢 Go 的编译本质。当然,有更快的编译语言,但这不是重点。如果性能对您的应用程序非常重要,那么不要浪费时间调整和优化您的 Go 代码: 只要使用不同的语言就可以了。我听说 C++ 很不错。

可读性胜过速度

是这样的。大多数程序花在阅读上的时间比执行上的时间要多得多。而且程序员花费的时间比 CPU 花费的时间要多得多(祝你好运找到一个每小时 5 美分的开发人员)。那么,为了可读性而不是为了原始速度而优化程序是否有意义呢?

当然,我们希望我们的程序可读性和速度快一样好,而这通常是可能的。但是,当我们的工程师告诉我们:“嘿,我可以通过使用数组而不是 map,并使用键的低阶位计算索引,使每通电话的速度提高几纳秒” 时,重要的是要考虑我们放弃了什么来换取这几纳秒。

一切的成本,一无所有的价值

每一次优化都是一次权衡。当我们权衡速度和内存时,我们失去的通常是:

  • 简洁。有更多的代码,所以很难阅读
  • 清晰。这是如何工作的不再明显
  • 简单。更多的功能,更多的抽象,更多的数据结构读取和理解

教会自己可读性价值的一个很好的方法是尝试阅读别人的代码。作为开发人员,我们通常不会做很多这样的事情,我们可能要么自己编写代码,要么深度参与这些代码,所以我们很清楚这一切是为了什么,以及它们是如何组合在一起的。我们甚至可以感觉到随着时间的推移,由于需求和特性更新的变化,它是如何变化的。

黑暗中一座陌生的房子

当您第一次查看代码时,您不会有任何上下文。这就像在黑暗的房间里跌跌撞撞,被电线绊倒,脚趾被意想不到的家具绊到。“那是什么鬼东西?” 在 GitHub 上浏览任何大型的 Go 项目,你就会明白我的意思。(你从哪个文件开始读?一个重要的程序有开头吗?)

现在,如果一个程序不能做很多事情,就很容易让它变得简单。有些程序是复杂的,因为问题域是复杂的(Kubernetes)。我们写的任何东西都有一定的不可避免的复杂性。但这并不意味着要用聪明的、狡猾的、超优化的代码进一步模糊它。相反,它建议我们应该尽一切可能使我们的代码尽可能简单、直接和明显。

写更好的代码,更少的注释

对于一般的 Go 程序员来说,在任何级别都可以进入你的任何函数,并且或多或少地了解这些代码的用途和工作原理。我这么说并不是说你应该在上面写上大量的注释。只有当我们已经做了所有可能的事情来使代码变得简单和明显,并且在某种程度上写注释就是承认失败时,我们才应该使用注释。它在说: “我知道你不会理解我写的东西,所以我试图用另一种方式来解释它。”

我是第一个承认说起来容易做起来难的人。编写简单的代码很难。首先,为了向任何人解释一个概念,你需要自己理解它。要向计算机解释它,你需要彻底地了解它。事实往往并非如此。

你为什么讨厌乐趣?

另一方面,针对性能的调优代码既有趣又简单。我们都很享受。很多时候,我们就像醉汉在灯柱下面找钥匙,尽管他实际上把钥匙掉在了别的地方: 这里的光线比较好。我们看到一些东西可以很容易地优化和制造得更快,所以我们就这么做了。就像《侏罗纪公园》里的科学家们一样,我们总是全神贯注于我们是否能做到,我们不会停下来思考我们是否应该做到。

其次,我们之所以成为工程师,是因为我们喜欢聪明,喜欢做别人想不到的聪明、狡猾、巧妙的事情。在我们自己的私人项目和游戏时间里这样做是完全合法的。商业软件工程是完全不同的。“清晰比聪明更好(Clear is better than clever)”,Go 谚语如是说,这句话很好地概括了我的整个信息。

禅心,初心

作为一个 Go 导师和老师 ,我发现那些刚接触编程的人对这个想法没有任何困难。所有的代码一开始对他们来说都是莫名其妙的,所以他们完全同意这个想法,认为这对其他人来说可能也是困难的。他们不会被自己的聪明才智或者作为一个热门程序员的身份所束缚,所以他们乐于编写简单、优雅、直截了当的代码来实现自己的目标。

相比之下,对其他语言有丰富经验的人有时会很难掌握 Go 的简单性。如果它们来自像 Ruby 这样的解释性语言,它们倾向于以复杂的、不明显的、高度个性化的方式表达自己,而这些语言是允许的。如果他们来自 C++ 和 Java 的世界,他们编写的代码在一般的 Gopher 看来是荒谬的过度工程化。那边就是这么办事的。在许多情况下,当他们知道这不是 Go 的方式时,他们实际上松了一口气。

结论:放慢你的脚步,兄弟

“慢行”运动,如果我可以把这句话换成一个词的话,就是做得更少,更简单,做得更慢。

当然,我并不主张让程序不必要地慢下来。我想说的是,首先,你不需要像你想的那样担心性能问题。当你这样做的时候,通常有比编写晦涩难懂的代码更容易的方法来改进它。

其次,您应该比现在更多地关注简单性和可读性。当你考虑优化的时候,这就是你应该优化的。花一个小时来提高可读性。

第三,愿意在可读性上投资。如果你可以重构你的程序,让它显著地更清晰,代价是让它稍微慢一点,那么就去做吧。当性能很重要的时候,记住它不是免费的。如果您考虑为代码增加额外的复杂性以追求纯粹的速度(这里是一个特例,那里是一个聪明的位旋转技巧),那么请再考虑一下。你总是可以买到一台更快的电脑,但是你很难买到一个更快的大脑。

原文链接:https://bitfieldconsulting.com/golang/slower

作者:John Arundel

编译:polarisxu