Read It Never
74 subscribers
66 links
Download Telegram
https://www.sigarch.org/fast-memcpy-a-system-design/

Fast memcpy, A System Design。优化目标是 CPU 的每个 cycle 移动 16 bytes,从 CPU 的角度来考虑达到这个目标 CPU 需要提供什么样的能力。也可以看 ClickHouse 的 memcpy 实现(的注释):https://github.com/ClickHouse/ClickHouse/blob/master/base/glibc-compatibility/memcpy/memcpy.h

大体上分成三个阶段:
- Small Size: 复制的长度小于一次 load 的宽度(16 bytes)
- Medium Size: 复制的长度小于完整的一轮循环展开(如果循环展开 8 次,就是 128 bytes)
- Large Size: 在对齐的内存上循环展开复制
https://dl.acm.org/doi/10.1145/3510003.3510111

"Did you miss my comment or what?": understanding toxicity in open source discussions。对 GitHub 上的 toxic 行为做了一些采样归类和总结,只能说就算同为开源项目维护者有时候也未必能对其他维护者共情。
https://www.unison-lang.org/learn/the-big-idea/

Unison。基于 content-addressed code 来设计的语言,这样让对任何函数的 reference 天然的具有了不可变的特性,无论其被分发到什么环境中。其文档列举了一些这么做的应用实例。
https://slsa.dev/spec/v0.1/threats

Supply chain Levels for Software Artifacts: Threats and mitigations。总结了从开发者到终端用户所有可能的攻击区间和一些对应的攻击实例,以及提供了对应的减缓其影响的方式。SLSA 在接下来几年有可能会成为缓解供应链攻击的行业方案。
https://thenewstack.io/internode-cache-thrashing-hunting-a-numa-performance-bug/

Internode Cache Thrashing: Hunting a NUMA Performance Bug。无意中跨 NUMA 节点写入内存导致的性能问题。很少看到完整的定位这类 NUMA 性能问题的调试过程,关于 NUMA 为什么会产生这类性能问题可以参考:https://queue.acm.org/detail.cfm?id=2513149 经验数字来说 NUMA 相对 L1 cache 来说一次 load 的成本可能是 300 倍。
https://www.usenix.org/publications/loginonline/prodspec-and-annealing-intent-based-actuation-google-production

Prodspec and Annealing: Intent-based actuation for Google Production。 对 Google 的生产管理系统的概述,可以认为是 Kubernetes 的内部版本。这篇文章对阐述 Kubernetes 的抽象模型的设计原则比大多数 Kubernetes 的介绍文章都更清晰。

一个典型的传统部署流程是 "canary in cluster X, then deploy N at a time in clusters Y and Z, run a test, and so on.",最早可能是手动,然后可能会有一些脚本来自动化。这么做最大的问题是每个服务往往都有特有的部署流程,一个尽可能去泛化不同的可能步骤的部署系统最后总会变成一个足够执行任何行为的脚本语言。另一个让这个方式难以扩展的原因是每一个步骤都是一个将系统从状态 A 转化到状态 B 的带有副作用的操作,但是要精确的确定系统处在状态 A 和系统达到了状态 B 都是非常困难的,往往最后都依赖于没有写明的隐含状态。

要解决这个问题最显然(2023 年,这个系统设计于 2015 年)的方式就是把最终想要达到的状态(intention)声明到 spec 里,然后再设计一个闭环控制系统来不断生成改变系统状态的操作,直到系统达到了声明的状态。Kubernetes 和 Prodspec/Annealing 都设计了一个非常类似于 Entity-Component-System(ECS)的系统:Prodspec/Annealing 中 Partitions = Entity,Assets = Component,System = Annealing。比如相对于 “把服务 X 部署到 A 和 B”,用户只需要定义一个 “Replicas: 2” 的 Assets 到自己的 Partition 上,而 Annealing 会找到达到这个最终状态的方法。

我个人感觉 Kubernetes 与 ECS 的映射对理解 Kubernetes 的设计逻辑会更有帮助,但是这条已经很长了。
https://doi.org/10.1145/3593856.3595887

FIFO can be Better than LRU: the Power of Lazy Promotion and Quick Demotion。使用真实生产环境的数据来测试各个不同的缓存淘汰算法,LRU 相对于一些优化的 FIFO 算法并没有命中率并没有显著的优势甚至更低。本文主要考虑了两种优化策略:
- Lazy Promotion:当一个值被淘汰时才判断是否需要晋升(比如放到队首)。
- Quick Demotion:让低命中率的值尽可能快的被淘汰。
LRU 除了实现复杂且对并发不友好,另一个问题是任何一个值被淘汰都需要走遍整个队列(在此期间有且仅有一次访问)。对于一个长度为 L,平均命中率为 H 的 LRU,每一个被 LRU 淘汰的值在被淘汰前的命中率都是 (1-H)/L。所以加快低命中率的值被淘汰的门槛(减小 L)预期上可以提高缓存利用率。
https://doi.org/10.1145/3593856.3595909

Towards Modern Development of Cloud Applications。本文提出了一种新的部署微服务但是向开发者隐藏微服务复杂度的方式,描述的方式粗看很难和 Actor 模式区分开来(特别是代码组织的结构几乎一样)。本文没有很好的来抽象总结新的方式在架构上的变化,我试着重新描述一下

- Actor Model 的 Runtime 功能上可以认为等价于 Kubernetes,而每个进程相当于一个 Pod,但是和 Kubernetes 一样,只解决了 Actor 在这个 Runtime 内的部署问题,而不解决 Runtime 本身的部署问题,而 Runtime 的抽象(一个巨大的虚拟机器)与物理部署的不完全对应,最后导致物理部署的状态泄漏抽象到 Actor 实现。
- 本文描述的方式更接近于集成了 Kubernetes Operator,也就是说每个单体具有控制自身部署的能力,在架构上更接近应用对于部署的控制反转而没有引入额外的抽象层。也就是说 Runtime 并不包括 Kubernetes 而是控制 Kubernetes 来满足自身的需求,尽可能的贴近了物理部署的状态来避免抽象泄漏带来的复杂度。

别的一些设计目标比如因为部署和所有模块现在在同一个 self-contained 单体内,本身提供了一个类似全局锁的效果,保证了这个版本的部署逻辑满足这个版本的业务需求,同时模块只和单体内的模块通讯,避免了异步部署微服务带来的复杂度。
https://dl.acm.org/doi/10.1145/121132.121151

Scheduler activations: effective kernel support for the user-level management of parallelism。提出一种用户态线程调度的设计,主要引入的几个新的抽象:

Processor:进程空间的虚拟处理器,类似于系统线程但是不会被阻塞,也可以直接对应物理的处理器。由内核来分配每个进程的处理器的数量。
Activation:相当于一个激活(运行)的状态,Activation 总是和 Processor 的数量相等,也就是说对于每个进程来说正在运行的用户态线程总是应该等于虚拟处理器的数量。

一些典型的场景:
- 当持有 Activation 的线程被阻塞在内核时(如 IO 系统调用),内核会 upcall 进程创建新的 Activation,而进程的调度器负责废弃被阻塞的 Activation 并用新创建的 Activation选择下一个执行用户态线程。
- 当内核要增加分配给进程的 Processor 数量时,内核会upcall 进程创建一个新的 Activation;当内核要减少分配给进程的 Processor 数量时,内核会暂停两个 Activation 并upcall 进程创建一个新的 Activation。

Activation 严格的对应于线程的实际运行状态,把系统调度的抽象映射到了用户态,这样进程的调度器可以根据 Activation 来决定调度策略,也可以和现有的同步 syscall 兼容。
https://doi.org/10.1145/564585.564601

CAP 定理的原始证明。找这篇看起因是因为 The CAP Theorem. The Bad, the Bad, & the Ugly 对 CAP 定理的抨击,看了下原始的证明这个定理确实没有太多现实意义。感觉最大的问题是对于 Availability 的定义过于狭隘,节点对所有请求都必须给出结果,但现实中在检测到网络隔离之后节点完全可以拒绝回复让客户端去重试。

权衡一致性和可用性确实是一个很好的考虑系统设计取舍的框架,但是 CAP 定理并没有否定一个同时满足高可用和强一致性的系统在实践上可以存在。毕竟对于理论来说 “可用” 是个正确性问题,而对实践来说是只是个请求成功率的指标。
https://doi.org/10.1145/2509578.2509584

What's wrong with git? a conceptual design analysis。从 git 设计中引入的概念来分析 git 为什么对新用户来说这么不友好,主要讨论的是从修改文件到 commit 以及 branch 的部分。本文基于 Brooks 提出的概念完整性的框架来分析,认为一个好的概念设计应该:
- 正交:功能之间的行为应该互相独立
- 适当:单个功能应该只包含其用途所必需的行为
- 泛化:单个功能应该适用于所有类似场景
- 一致:单个功能应该在不同的参数或者状态下表现出同类的行为
在这个框架下 git 的分析 git 的设计,如 working versions 和 staged versions 不正交,git commit 不同情况下有不同的行为,branch 不能泛化到 working/staged versions (只适用于 commited versions) 等等,并且提出了一个改进设计实现。

题外话,就我目前的观察来看就算招的人再聪明或者做了很多年开源项目,大家还是都不太会用 git。
https://www.usenix.org/publications/loginonline/evolution-sre-google

The Evolution of SRE at Google。用 System Theory 来分析灾难。传统的思路是事故是一连串的事件的结果,所以解决方法往往是如何打破这一串事件的因果链条(如加冗余,避免单点故障)。从系统的角度来看系统在正常工作时处在一个稳态,也就是说必然存在一套控制系统来维持系统,而一个事故是系统从稳态到亚稳态再最后到灾难的过程,其中亚稳态可能维持了很长的时间。识别出为什么控制系统无法从亚稳态回到稳态可以从一开始避免进入可能会发生事故的状态。System Theory 也能更好的把非技术的因素考虑进来(如组织架构,流程,外部环境)。

Instead of asking "What software service failed?" we ask “What interactions between parts of the system were inadequately controlled?” In complex systems, most accidents result from interactions between components that are all functioning as designed, but collectively produce an unsafe state.
Read It Never
https://ckrybus.com/static/papers/Bainbridge_1983_Automatica.pdf Ironies of automation (1983) - 系统自动化的部分出发点是降低维护成本 - 维护高度自动化的系统需要对该自动化系统相关领域知识有深入了解的操作员,高技能的操作员需要极高的培养成本 - 在系统自动化程度大于某个阈值时,培养操作员的成本会大于开发自动化系统的人员的成本,这个界限就是 ops 失去意义,devops 和 SRE 成为系统维护员的时刻 “Debugging…
LLM 带来的问题和 1983 年自动化的问题本质是类似的,自动化程度越高需要的干预越少,操作员越缺少足够机会来习得维护系统的技能,然后复杂度和成本转嫁到了培养有能力维护自动化系统的操作员的教育系统上,因为不可能在工作过程中习得这些技能。

复杂度是不可能靠自动化来消解的,一个自动化系统必须内化其所自动化的系统的模型,所以必然继承了所有的复杂度并且增加了自动化系统本身的复杂度。

这不是说自动化是没有意义的,只是自动化不能降低系统的复杂度,认为用 LLM 来维护复杂系统会降低维护的复杂度可能是一个错误的优化目标。其结果和过去每一轮的自动化从结构上来说或许是类似的 - 减少低技能岗位的数量,增加高技能岗位的数量,成本转嫁给教育系统。