写作
用勾股定理画脚踝
前两周,我在练球时扭伤了脚踝,歇了两周依然没好全,而且还出现一种我无法理解的症状「 走路的时候不疼,坐一会儿再站起来就又开始疼,接着走一会儿就又好了 」。出于好奇,我咨询了 AI,这是我们的 完整的对话 。关于脚踝的症状并没有什么值得在这里展开,让我真正感到惊讶的是,AI 为了向我说明「距腓前韧带」的位置,画了一张我在数学课上才会见到的图:
我的第一个 AgentSkill
我在 Cambly 和外教上课时,多数时候用的是 Engoo Daily News 中的课程( 网站示例 、 课程示例 )。每节课程对应一篇英文时事新闻,上课的一般流程就是:课前准备 → 文章阅读 → 问题讨论,同时每节课程都标记有难度,从 Intermediate (Level 4-6)、Advanced (Level 7-8) 到 Proficient (Level 9),课程内容难度依次递增,具体体现在词汇难度、句子复杂度、讨论…
AI 究竟在缩小还是放大软件工程师之间的差距?
有人认为,随着模型推理能力变强,写代码正在变得更容易,程序员之间的差距也会逐渐被拉平。新手能更快写出可用的代码,很多过去需要经验积累才能跨过的门槛,现在只要能写好提示词就能轻松迈过。 别妄想了,AI 一定不会拉平软件工程师之间的差距,差距只会越来越大,且越来越快,就像宇宙的加速膨胀。
两年魔方速拧路,体验优化的艺术
魔方速拧之路 走上魔方速拧路既是机缘巧合,也是冥冥之中天意使然。2022 年 8 月 28 日,我见到郑天晴坐在地上摔打奶奶给她买的玩具魔方,忽然回忆起高中班上有个小伙子能在 3 分钟内复原一个魔方,令同学们既赞叹又羡慕,我心中的少年之火在这一瞬间被点燃,决定也试上一试。于是我找到了博主 LeesRandomVids 制作的保姆级教学视频「 How to Solve a Rubik's Cube, Step by Step Begin…
为什么要「卷」
有一个问题困扰了我很久: 为什么公司里的团队要互相卷? 明明 X 团队已经造了轮子,为什么 Y 团队常常视而不见,吭哧吭哧地继续造?而且领导似乎也默许这种游戏规则?本来产研资源就贵,为什么要浪费在相似的工作上,而不节省资源去专心做业务?最近在这个问题上稍微有点心得,就先记录于此。
赤道计划
多数人高估他们一年能做的事,却低估他们十年能的事(Most people overestimate what they can do in one year and underestimate what they can do in ten years)。 大概在两年前,我开始酝酿「赤道计划」:在人生结束之前跑完 40075 公里,这个距离正是赤道的周长。毛主席的「坐地日行八万里,巡天遥看一千河」也来源于它。如果每两天跑一次 5 公里…
面向工程师的内部系统需要 Web 界面吗?
每个互联网公司内部都有一些 Web 界面是为工程师开发,比如 CMDB、容器平台、应用发布系统、可观测性平台、配置中心、数据库管理平台等等。这些界面往往设计风格不一致,功能简陋,易用性差强人意,简单概括就是「能用,但既不好看,也不好用」。
我开发的口语跟读练习工具 RAM
平时,我习惯在跑步、散步或通勤时做一些口语跟读练习。散步或通勤时还好,在手机上来回播放、暂停音频即可,但这种方法不适合在跑步中使用。另外,北京入冬后,在室外这么干容易生冻疮。于是我就想:能不能让音频自动地播放一句,停留一段时间让我跟读,然后再播下一句?
Software Engineering at Google - 阻碍工程师成长的几种想法
前言 从 2022 年 10 月中旬开始到 12 月中旬,日拱一卒,终于把「Software Engineering at Google」通读了一遍。书中介绍的是每个软件公司都会遇到的问题:如何培养好的工程师文化?如何共享知识?如何组建和带领工程师团队?如何长期维持软件质量?等等。同样的问题,在不同的规模、时间范围下的挑战不同,思考角度、解决方案、落地周期也都不同。这本书介绍的正是这家拥有 超过两万名工程师 的软件公司在这些问题上的思…
纸牌游戏:24
可能是太想排到车号了,最近上下班路上总是盯着过往车辆的号牌。盯着盯着就会下意识地思考:「怎么用上面的数字经过加、减、乘、除得到 24」,比如下面这个车牌:
猫和女儿教会我的道理
没有屏蔽我朋友圈的人估计都知道,我有一只帅气的猫叫郑小钱,一个可爱的女儿叫郑天晴。小钱已经快 5 岁了,天晴刚刚 1 岁 3 个月,她们和我 (爸爸)、我媳妇 (妈妈) 以及我妈妈 (奶奶),4 人 1 猫生活在北京租住的一套小房子里。 都说养猫是养娃的演习,这话颇有道理。二者的确有很多相似的地方,比如我们会忍不住给她们买玩具,花时间陪她们玩耍,给她们准备饭菜与零食,管她们拉屎撒尿。最有意思的,也是我和媳妇经常讨论的一点就是「她们跟谁…
面试官毁掉技术面试的三大法宝
在伴鱼的三年,我作为面试官参与超过 100 场面试,遇到许多风格各异的候选人;最近的两个月里,我也作为候选人参与将近 30 轮面试,见过不少形形色色的面试官。在参与这些面试的过程中,我心中逐渐累积了一些对面试的看法,本文我想站在面试官的角度,谈一谈面试官毁掉技术面试的三大法宝。
从 MapReduce 到 SQL
在最近的工作中,为了做数据分析,我开始写一些复杂的 HiveSQL。每次执行 HiveSQL 时,都会看到 Map/Reduce jobs 被调度、执行,直到最后展示出数据。渐渐地我心中多了两个疑问: MapReduce 引擎如何工作? SQL 是如何被翻译成 MapReduce job 的? 为了解决这两个疑问,我用比较熟悉的 Go 语言实现了一个玩具版本的 MapReduce 引擎,然后基于此实现基本的 select,join。 …
一次实验、两种错误、三个直觉
最近,我们在公司内部做了一些 Hacking Growth 方向的探索,我们团队俨然成了增长团队,从用户增长、转化的各个环节上尝试不同的策略,拉新、激活、留存、促活、商业化,整个核心流程是一个大漏斗,不同的阶段和渠道又可以拆分成不同的小漏斗,哪个环节损失大就优化哪个。但无论做何种尝试,都绕不开 A/B 测试。
捋一捋 Accuracy 与 Precision 间的区别和联系
Accuracy 和 Precision 是在科学技术领域中经常出现的两个概念,本文将通过一张图来捋一捋二者之间的区别与联系。
我明明是福建人,为什么别人以为我是胡建人?
在和不同地区的人聊天时,我们常常会有疑惑:为什么有些人说话时分不清 x 和 y?这里的 x 和 y 可能是拼音中的 f 和 h,l 和 n,l 和 r,z 和 zh,ang 和 an。比如,我明明是福建人,为什么别人以为我是胡建人?在最近刚刚读完的一本书《Fluent Forever》中,有两张图片正好能解释这个问题。
中小型 Go 语言项目应该如何布局?
每个工程师来到新环境,大概率需要从维护老项目开始切入,逐渐熟悉公司的技术栈和效率工具。这时候,老项目的一些习惯,如命名、布局、错误处理等等,不论好坏,都会不自觉地影响新人,形成路径依赖。在这个过程中,如果没有人主动去思考为什么,这些习惯也将被无理由地继承下去。
复利的隐喻
💡 人们常常高估自己一年能成就之事,而低估自己十年能成就之事 尽管我的博客中绝大多数内容都与计算机相关,但实际上我还有另一个身份:经济学学士。在对外经贸大学度过的四年,是我对人生的认识井喷的四年。毕业之后选择计算机,并不是因为我厌恶经济学。相反,在学习经济学的过程中建立起的心智模式,一直对我的学习和实践产生着指导性作用。 在货币银行学中,有一个与金钱的时间价值紧密相关的概念: 复利 ,即本金产生的利息会在下一个计息周期成为本金的一部…
从头开始实现 RNN
What I cannot create, I do not understand. -- Richard Feynman Andrej Karpathy 在 2015 年发表了题为 The Unreasonable Effectiveness of Recurrent Neural Networks 的博客,并配套开源了其中实验所用的 char-rnn 代码仓库 ,以及用 numpy 手写的 gist: min-char-rnn ,…
翻译能有多快?在 Mac 上实现一键翻译
因为平时需要阅读大量的英文资料,翻译对我来说是一个高频需求,但我一直没能找到一个足够趁手的工具。对于一个理想的翻译工具,我有三点期望: 翻译准确:翻译的结果与原文贴合不显得尴尬 触发简单:复制到剪贴板后快速触发翻译指令 响应迅速:发起翻译请求到获得结果小于一秒
从头开始构建一个 Pascal 的解释器
前阵子无意中发现了一个系列教程:「 Let's Build A Simple Interpreter 」,简称 lsbasi。本来只是随便翻翻,但刚看完 Part-1 就发现作者 Ruslan Spivak 不仅是一个出色的软件工程师,文笔也相当不错,更难得的是他对学习这件事本身有着很深入的理解,这些见解甚至反馈到了这套教程的设计上。
Make It Stick - 学习本身是一件值得思考的事情
前段时间,我的朋友「肚子」向我推荐了 Make It Stick: The Science of Successful Learning 这本书 (以下简称 MIS),读毕感觉相见恨晚。该书的讨论主题是学习这件事情本身,即研究人类学习的特点,找到适合人类的高效学习策略。如果用一句话向其它朋友推荐这本书,我想这句话一定是: 学习本身是一件值得思考的事情 。
对话系统-101
今年 6 月底,由于工作需要,花了两周时间调研对话系统,并在公司内部做了一次调研报告。本文意在将此报告整理成文字版,算是对这段时间付出的一个交代。
Born a Crime - 崔娃语录谈
因为之前在 Youtube 和 B 站上零星地看了一些 Trevor Noah 的 stand-up 和 Daily Show,加上最近在伴鱼 App 上与来自南非的老师学英语,我在大约四月中旬决定读一读「Born a Crime」这本书,书的内容本来并不多,但个人时间安排原因使得这个过程变得很长,直到昨天终于读完。
代码搜索引擎:基础篇
Google 内部曾对工程师做一次 调研 ,发现平均每位工程师每天会进行 5.3 次代码搜索会话 (session),执行 12 个代码搜索请求;在 Github/Gitlab 等仓库托管服务中,搜索是工程师最常用的功能之一。
调用链追踪系统在伴鱼:实践篇
此文同时发表在 伴鱼技术博客 上 在 理论篇 中,我们介绍了伴鱼在调用链追踪领域的调研工作,本篇继续介绍伴鱼的调用链追踪实践。在正式介绍前,简单交代一下背景:2015 年,在伴鱼服务端起步之时,技术团队就做出统一使用 Go 语言的决定。这个决定的影响主要体现在: 内部基础设施无需做跨语言支持 技术选型会有轻微的语言倾向
调用链追踪系统的设计维度
本文将调用链追踪系统的设计维度归结于以下 5 个:调用链数据模型、元数据结构、因果关系、采样策略以及数据可视化。我们可以把这 5 个维度当作一个分析框架,用它帮助我们在理论上解构市面上任意一个调用链追踪系统,在实践中根据使用场景进行技术选型和系统设计。如果你对调研相关系统很感兴趣,也欢迎参与到 Database of Tracing Systems 项目中,一起调研市面上的项目,建立起调用链追踪系统的数据库。
So, you want to trace your distributed system? Key design insights from years of practical experience (2014)
本文主要介绍一篇关于调用链追踪系统设计的论文。行文会尊从原论文的结构,但不是逐字翻译,以意译和加入个人理解的转述为主。
如何在 Golang 项目中处理好错误
造一辆能跑在路上的车并非难事,但要这辆车能在各种路况、气候和突发事件下安全行驶,事情就不再简单。如果把写程序比喻成造车,构建程序的主要功能就是让车跑起来,而处理好错误就是让车安全地跑。 错误是程序的重要组成部分,能否在程序中处理好错误决定了软件的质量上限 。在这篇博客中,我将介绍个人在 Golang 项目中错误处理的思考。
TiDB 为什么要用 Apache Arrow - 一个门外汉的思考
最近在阅读 TiDB 源码 util/chunk package 的过程中,看到了 Apache Arrow 这个项目 (下文简称 Arrow): // Chunk stores multiple rows of data in Apache Arrow format. // See https://arrow.apache.org/docs/format/Columnar.html#physical-memory-layout //…
The Anatomy of a Large-Scale Hypertextual Web Search Engine (1998)
引言 最近因为工作的关系接触 ElasticSearch,发现搜索引擎也是计算机应用的一个有意思的分支。于是通过 Freiburg 的 Information Retrieval 公开课开始系统地了解信息检索这个领域,感觉收获颇丰。周末一时兴起,上 Google Research 找到了 Google 的开山之作,近距离地感受一下 19800+ 引用量、造就如今 Google 万亿市值的这篇文章。
I ❤ Logs - 以日志为中心的系统设计理念
I ❤ Logs 出版于 2014 年,是一本很短小的书,100 页不到,利用这周的零散时间就看完了。作者 Jay Kreps ,是前 LinkedIn 的 Principal Staff Engineer,也是 LinkedIn 许多著名开源项目的负责人及联合作者,如 Kafka、Voldemort 等。他是现任 Confluent 的 CEO,主要工作在于围绕实时数据提供企业级服务支持。这本书算是 Jay Kreps 过去多年实践…
Jaeger 的 Go 客户端的源码导读
Jaeger Walkthrough 系列文章之一,旨在深入理解 Jaeger 项目内部的实现细节。本文介绍的是 Jaeger 的 Go 客户端, jaeger-client-go 。
Prometheus Alertmanager 的源码导读
Alertmanager 是 Prometheus 提供的报警分发平台,它主要满足的是报警的路由、分组、抑制、去重等常见需求。
最美的程序:用 Lisp 写的 Lisp 解释器
本文来自于 2017 年 PWL NYC Meetup,作者的简介如下: William E. Byrd (@webyrd) is a Research Assistant Professor in the School of Computing at the University of Utah. He is co-author of 'The Reasoned Schemer', and is co-designer of the…
报警平台的匹配器演进
简介 本文介绍伴鱼内部服务报警平台中匹配器模块的演进,及其利用 Lex 和 Yacc 同类工具构建 DSL 编译器的过程。是我和团队成员在伴鱼的质量工程小组的一小部分工作。
What's Really New with NewSQL (2016)
在进入文章之前,应该先介绍两位重量级作者: Andrew Pavlo 和 Matthew Aslett 。Andrew 在 CMU 的计算机科学学院任教,主攻方向包括内存数据库、自动驾驶系统架构、事务处理系统和海量数据分析,他是 CMU Database Group 的核心成员,在 CMU 开设的两门课程 Database Systems (15-445/645) 和 Advanced Database System (15-721)…
分布式锁方案:效率与正确的权衡
提到分布式锁,很多人也许会脱口而出 redis ,可见利用 redis 实现分布式锁已被认为是最佳实践。这两天有个同事问我一个问题:“如果某个服务拿着分布式锁的时候,redis 实例挂了怎么办?重启以后锁丢了怎么办?利用主从可以吗?加 fsync 可以吗?” 因此我决定深究这个话题。
Kafka: a Distributed Messaging System for Log Processing (2011)
论文引用量:744 (截止至 2020-03-15) Kafka 是开发者耳熟能详的开源项目,它已经成为近年来互联网公司必不可少的基础组件。Kafka 得名于作家 Franz Kafka,大概是因为二者都比较擅长写日志 : )。它孵化于 LinkedIn 内部,在 2011 年被捐赠给 Apache 基金会,2012 年末正式从 Apache Incubator 中毕业。本文于 2011 年发表于 NetDB workshop,如今原…
Scaling Memcache at Facebook (2013)
本文介绍 FB 基于 memcached 构建统一缓存层的最佳实践。全文递进式地讲述 单集群 (Single Front-end Cluster) 、 多集群 (Multiple Front-end Clusters) 、 多区域 (Multiple Regions) 环境下遇到的问题和相应的解决方案。尽管整个解决方案以 memcached 为基本单元,但我们可以任意地将 memcached 替换成 redis、boltDB、leve…
Prometheus TSDB 的存储层演进 —— PromConf 演讲笔记
注:如果只想了解 Prometheus TSDB 的存储层现状,可以直接移步 Ganesh Vernekar 的博客 ,他写了 7 篇系列文章介绍这个主题。 Prometheus 无疑是时下最流行的监控平台,它负责定期从不同的采集目标拉取样本数据,然后持久化到内建的时序数据库中,向外部提供便捷的查询接口。本文主要探讨的是 Prometheus 存储层的演进过程,整理自 Prometheus 团队在历届 PromConf 上的分享以及相…
用 LSM Tree 实现一个键值数据库 —— GopherConf 2017 演讲笔记
Background 数据库中的各种奇技淫巧,实际上都来自于内存与磁盘的读写模式和性能区别。
缓存管理策略综述
在计算机系统设计实践中,我们常常会遇到下图所示架构: 为了解决单个存储器读吞吐无法满足要求的问题,常常需要在存储器上面增加一个或多个缓存。但由于相同的数据被复制到一个或多个地方,就容易引发数据一致性问题。
Consistent Hashing and Random Trees (1997)
论文作者的贡献主要包含两部分:Consistent Hashing 和 Random Trees。Consistent Hashing 主要用于解决分布式哈希表 (Distributed Hash Table, DHT) 的桶增减带来的重新哈希问题;Random Trees 主要用于分布式缓存中的热点问题,它利用了 Consistent Hashing。下文主要关注 Consistent Hashing。
Dynamic Hash Tables (1988)
摘要 Linear Hashing 和 Spiral Storage 是两种动态哈希算法。这两种算法最初都是为了优化外部存储 (secondary/external storage) 数据访问而设计的。本文将这两种算法引入到内存中,即键值数据可以一次性读入内存的场景,对比、分析二者之间,以及与其它动态哈希算法的性能。实验结果表明:Linear Hashing 的性能上要优于 Spiral Storage,实现难度上要小于 Spiral…
Dapper, a Large-Scale Distributed Systems Tracing Infrastructure (2010)
早在 2008 年,Google 就已开始分布式调用链追踪的工作,经过两年的打磨后,Dapper 系统问世,并通过这篇文章将其设计公之于众。遗憾的是,Dapper 并不是开源项目,但它的设计理念依然深刻影响到后来的 Jaeger、Zipkin 等开源分布式追踪项目,以及相关的标准 Opentracing、OpenTelemetry。 本文不是原文的精准翻译,而是一次重述和简述,旨在记录分布式调用链追踪要解决的核心问题和潜在解决方案。
LFU Implementation With O(1) Complexity (2010)
Abstract 缓存置换算法 (Cache Eviction Algorithm) 在操作系统、数据库以及其它系统中被广泛用于缓存置换模块,当缓存空间不足时,它利用局部性原理 (Principle of Locality) 预测未来数据的使用模式,将最不可能被访问的数据清出从而提高缓存命中率。目前已经存在的缓存置换算法包括 MRU (Most Recently Used)、MFU (Most Frequently Used)、LRU…
Time, Clocks, and the Ordering of Events in a Distributed System (1978)
简介 本文是分布式系统理论的开山鼻祖、2013 年图灵奖获得者 Lamport 的成名作,也是分布式计算领域杰出论文最佳影响力奖 Dijkstra Prize 的第一篇论文,高达 11692 的引用量(截至 2019/12/08)足以证明其广泛的影响力: 本文主要讨论 3 个话题: 分布式系统中的事件偏序 利用逻辑时钟实现事件偏序 利用逻辑时钟实现事件全序
Gorilla: A Fast, Scalable, In-Memory Time Series Database (2015)
Abstract 在大型微服务架构中,服务监控和实时分析需要大量的时序数据。存储这些时序数据最高效的方案就是使用时序数据库 (TSDB)。设计时序数据库的重要挑战之一便是在效率、扩展性和可靠性中找到平衡。