编程 ESI 深度实战:当软件想要活过1000年——从 Subleq+ 极简虚拟机到 LLVM 后端、Linux 胶囊与长期保存的完全指南(2026)

2026-06-20 15:28:40 +0800 CST views 11

ESI 深度实战:当软件想要活过1000年——从 Subleq+ 极简虚拟机到 LLVM 后端、Linux 胶囊与长期保存的完全指南(2026)

2026 年 6 月,一个名为 Eternal Software Initiative(ESI) 的开源项目把“软件永生”这个听起来像科幻的命题,变成了一套可下载、可编译、可运行的技术栈。它的野心很大:用一段足够短的描述,让一千年后的人重建一台计算机,并直接运行今天的软件。更疯狂的是,这台计算机的指令集只有 一条指令subleq。本文将从 WHY、WHAT、HOW 三个层面,把 ESI 的设计哲学、极简架构、LLVM 后端、Linux 胶囊、以及一个可运行的 Subleq+ 虚拟机完整拆开,看看它到底是在做赛博诺亚方舟,还是一次值得每个程序员思考的工程实验。


一、软件为什么会“死”?——从 10 年半衰期说起

我们每天都在写代码,却很少认真想过:代码本身能活多久? 一个 Java 程序依赖特定版本的 JDK、Spring Boot、MySQL 驱动、某个 Kubernetes 发行版;一个前端项目被 npm 依赖树裹成粽子;一个游戏依赖 closed-source 的物理引擎和 DRM 服务器。只要其中任何一个环节停止维护,整件“数字文物”就会在几年到十几年内腐烂。

ESI 官网给了一个很扎心的对比:

介质寿命
泥板5000+ 年,今天仍可读
软件~10 年,依赖就开始过时

这不是危言耸听。今天的考古学家可以读懂几千年前的楔形文字,但 100 年后的工程师未必能跑起来一个 2026 年的 Docker 镜像。因为软件不是单一物品,它是一个生态系统:硬件、操作系统、编译器、运行时、库、框架、协议、证书、在线服务,全部要在位且兼容。一旦某一层缺失,整个金字塔就塌了。

传统的应对方案是模拟器。QEMU、DosBox、MAME 等工具把旧硬件翻译成软件,让老程序在现代 CPU 上运行。但模拟器本身也是数百万行代码,依赖现代语言、库和操作系统。你能想象 1000 年后的人先读懂 QEMU 源码、再复现 x86 的乱序执行、UEFI 启动流程、PCIe 枚举,然后才能运行你写的一个 Python 脚本吗?

“你不能用更复杂的东西去保存复杂的东西,你必须简化。” 这是 ESI 的出发点。它选择了一个极简到不可思议的靶子:一台只有一条指令的计算机。只要未来的人能理解这条指令,就能重建整台机器,进而恢复一整套现代软件。


二、Subleq+:一条指令的图灵机

Subleq 是“SUbtract and Branch if Less than or EQual to zero”的缩写。它只有一条指令:

subleq A, B, C

语义极其简单:

  1. M[B] = M[B] - M[A]
  2. 如果结果 <= 0,跳转到地址 C
  3. 否则继续执行下一条指令

其中 ABC 都是内存地址。整个计算机的状态就是一片可读写的内存加一个程序计数器(PC)。没有寄存器,没有特殊寄存器,没有复杂的寻址模式。你甚至可以把 CPU 规范写在一张餐巾纸上。

2.1 图灵完备:一条指令够吗?

很多人第一反应是:“这能干什么?”答案是:Subleq 是图灵完备的。也就是说,它能表达任何可计算问题。证明思路很直接:

  • 条件跳转subleq Z, Z, label 先把 Z 清零,再 subleq A, Z, label,若 A <= 0 则跳转。因为 M[Z] = 0 - M[A],当 M[A] <= 0 时结果 >= 0?等等,需要更仔细地构造。但经典结论是:通过适当选择 ABC,可以实现分支、循环、函数调用。
  • 算术运算:加法 C = A + B 可以通过 A = A - (-B) 实现;乘法可以通过循环累加实现;位运算可以通过算术技巧实现。
  • 内存访问:直接寻址已经够表达任何数据移动。

所以 Subleq 不仅“能跑”,而且在理论上可以跑任何程序。问题是,纯 Subleq 写程序太啰嗦。于是 ESI 做了一个关键扩展:Subleq+

2.2 Subleq+ 的升级:间接寻址

Subleq+ 在 Subleq 的基础上加入了间接寻址。官方说法是:这提供了“指针支持”,使得可重入代码、栈、函数调用成为可能,也让运行现代操作系统不再是天方夜谭。

在我们的示例实现里,可以把一条指令扩展为 4 个内存字:

[OP, A, B, C]

其中 OP 的高几位表示寻址模式:

OP 标志含义
0直接:AB 都是地址
1A 间接:M[A] 作为源地址
2B 间接:M[B] 作为目标地址
3AB 都间接

执行语义:

src = (op & 1) ? M[M[A]] : M[A]
dst = (op & 2) ? M[M[B]] : M[B]
M[dst_addr] -= src
if M[dst_addr] <= 0:
    PC = C
else:
    PC += 4

注意:这里的“目标地址”和“目标值”要分开。如果是直接模式,目标地址就是 B,目标值就是 M[B];如果是间接模式,目标地址是 M[B],目标值是 M[M[B]]。这个细节是 Subleq+ 能支撑高级语言的关键:它让我们可以用一个指针指向内存,再对那块内存做读写。

2.3 一段 Subleq+ 汇编示例:两数相加

; 计算 M[sum] = M[a] + M[b]
Z:    .word 0
a:    .word 7
b:    .word 5
sum:  .word 0

start:
    subleq Z, Z, next    ; Z = 0
next:
    subleq b, Z, next2   ; Z = 0 - b = -b
next2:
    subleq Z, sum, end   ; sum = sum - (-b) = sum + b
end:
    halt

这段代码只有 3 条有效指令,却展示了 Subleq+ 编程最核心的技巧:用临时变量把加法变成减法。因为指令只有减法,所以加法 x + y 要写成 x - (-y)。先把 y 取负存入临时变量,再用一次减法把它加回去。这是所有高级语言被编译到 Subleq+ 时的底层模式之一。


三、Eternal Computer 架构全景

Eternal Computer 不是一台真实物理机,而是一个目标架构规范加一个参考虚拟机。它的设计目标不是跑得最快,而是“最容易被未来的人重建”。因此它的架构有以下几个特征:

3.1 扁平内存模型

所有数据都放在一个统一的大数组里。没有寄存器文件、没有缓存一致性协议、没有特权级。一个字有多大?ESI 的实现选择了 32 位或 64 位有符号整数。在本文的示例里,我们统一使用 32 位有符号整数。

这意味着:

  • 指针就是一个整数地址。
  • 栈指针也是内存里的一个普通字。
  • 进程切换时,只需要保存 PC 和若干内存字,不需要保存寄存器上下文。

3.2 指令格式

一条 Subleq+ 指令占 4 个字:

[OP | A | B | C]

程序计数器每次默认前进 4。如果 OP == -1,表示停机。整个指令集规范不到 200 个字符就能写清楚。

3.3 内存映射 I/O

为了和外部世界交互,ESI 的 VM 通常把一部分地址空间留给 I/O。例如:

  • 某个固定地址写字符,即向控制台输出。
  • 某个固定地址读字符,即从键盘输入。
  • 图形版本会有一块帧缓冲区,也是内存的一部分。

这样一来,运行《毁灭战士》只需要把显存映射到帧缓冲区,然后由 VM 把这块内存渲染到屏幕。没有驱动程序,没有复杂的 GPU 接口,只有“读内存→显示像素”。

3.4 架构与实现的解耦

规范是规范,实现是实现。参考 VM 可以用 50 行 C 写完;你也可以用 Python 写一个教学版;未来的人甚至可以用齿轮、继电器或 DNA 链实现。只要它执行同一条指令集,同一个 capsule 就能跑起来。这种规范与实现的解耦是长期保存的核心:复杂的是硬件实现,保存的却只有一串数字和一页规范。


四、把 C/C++ 和 Linux 塞进 Subleq+:LLVM 后端与系统移植

如果你只是做了一个一指令 CPU,没人会理你。ESI 真正让人震惊的是:他们给这个 CPU 做了一个 LLVM 后端,把 C/C++ 程序编译成 Subleq+ 指令流,还移植了 Linux、uClibc-ng 和 BusyBox。

4.1 LLVM 后端:从高级语言到极简指令

LLVM 的架构是模块化的。你可以为新的 CPU 定义一个 Target:描述寄存器、指令集、调用约定、ABI、汇编格式。然后 LLVM 的代码生成器会完成指令选择、寄存器分配、指令调度。

但 Subleq+ 几乎没有寄存器,所以它的后端更像是一个栈机/内存机后端:

  1. 前端把 C 代码编译成 LLVM IR。
  2. 后端把 LLVM IR 里的每个操作(addloadstorecallret)翻译成 Subleq+ 指令序列。
  3. 由于没有寄存器,所有中间结果都存放在内存的临时槽位里。
  4. 函数调用约定:参数按顺序压入栈,返回地址也放在内存里,栈指针由 Subleq+ 间接寻址维护。

来看一个最简的 C 函数如何被“脑内编译”到 Subleq+:

int add(int a, int b) {
    return a + b;
}

在 Subleq+ 后端里,它可能被翻译成类似下面的伪代码(假设栈从高地址向低地址增长,参数已经通过调用者压栈):

; 帧布局简化示意
; sp 指向栈顶
; 参数 a 在 sp+1,参数 b 在 sp+2
; 返回值写回 sp+1

    subleq tmp, tmp, next      ; tmp = 0
next:
    subleq [sp+2], tmp, next2  ; tmp = -b
next2:
    subleq tmp, [sp+1], ret    ; a = a + b,结果留在原 a 的位置
ret:
    ; 恢复栈,跳转到返回地址

真实的 LLVM 后端当然要处理类型、对齐、调用约定、优化、调试信息,但底层模式就是:不断用临时零槽和 subleq 的组合,把所有高级抽象还原成内存之间的减法。

4.2 为什么选 uClibc-ng 和 BusyBox?

ESI 的目标不是重造一个 Linux 发行版,而是构造一个能自举的最小 Linux 环境。所以选择:

  • uClibc-ng:一个为嵌入式系统设计的 C 库,体积比 glibc 小得多,功能却足够运行大多数 Linux 程序。因为它是 C 写的,可以被 ESI 的 LLVM 后端直接编译。
  • BusyBox:把 dozens of Unix 工具合并成一个可执行文件,俗称“嵌入式 Linux 瑞士军刀”。它让胶囊里的根文件系统保持最小。
  • Linux 内核:ESI 需要把内核里与架构相关的部分(启动、上下文切换、中断/异常、系统调用、页表或内存保护)重新实现到 Subleq+ 上。因为 Subleq+ 支持间接寻址,所以可以维护进程栈、保存 PC、实现抢占式多任务。

最后,内核、C 库、Shell、应用程序全部编译成 Subleq+ 指令,被打包进一个胶囊


五、Capsule:把软件封进一串数字

ESI 对“软件永生”给出的工程答案是 Capsule(胶囊)。它的定义非常朴素:

A capsule is a sequence of numbers that encodes an entire software stack — OS, libraries, applications — into a single self-contained artifact.

也就是说,最终交付物不是 ISO 镜像、不是 Docker 镜像、不是 git 仓库,而是一串整数。这串整数可以刻进钛合金圆柱、写进玻璃、打印在纸上,甚至编成一首歌。只要未来有人按规范重建 Eternal Computer VM,把数字加载进内存,软件就会重新运行。

5.1 胶囊的结构

一个最小化的胶囊可以想象成:

[ 魔数 | 内核长度 | 根文件系统长度 | 应用数据长度 | 内核字节... | 根文件系统字节... | 应用数据字节... ]

因为 Subleq+ 的字长是整数,所以所有字节数据会被对齐成 32 位或 64 位字。VM 启动时:

  1. 读取魔数,确认格式版本。
  2. 把内核加载到固定起始地址。
  3. 把根文件系统加载到另一段地址。
  4. 设置 PC 到内核入口点。
  5. 开始执行。

5.2 一个玩具级胶囊打包器

下面是一个用 Python 写的概念级打包器,展示如何把多个二进制片段合并成一个胶囊文件:

import struct

MAGIC = 0xE51CA_0001  # 假的魔数,仅用于演示

def pack_capsule(parts):
    """
    parts: [(name: str, data: bytes), ...]
    返回:扁平化的整数列表,每个整数占 32 位。
    """
    # 头部:魔数 + 段数
    header = [MAGIC, len(parts)]
    # 每个段的目录项:名字长度、数据偏移(字)、数据长度(字)
    directory_size = len(parts) * 3
    data_offset = 2 + directory_size
    directory = []
    payloads = []
    cur = data_offset
    for name, data in parts:
        name_bytes = name.encode('utf-8')
        name_len = (len(name_bytes) + 3) // 4
        data_len = (len(data) + 3) // 4
        directory += [name_len, cur, data_len]
        padded_name = name_bytes + b'\0' * (name_len * 4 - len(name_bytes))
        padded_data = data + b'\0' * (data_len * 4 - len(data))
        payloads += list(struct.unpack('<' + 'I' * name_len, padded_name))
        payloads += list(struct.unpack('<' + 'I' * data_len, padded_data))
        cur += name_len + data_len
    return header + directory + payloads

# 示例:把两个“二进制文件”打包成胶囊
parts = [
    ("kernel", b'\x00\x01\x02\x03'),  # 假的内核
    ("initrd", b'hello capsule'),      # 假的根文件系统
]
capsule = pack_capsule(parts)

with open('demo.capsule', 'wb') as f:
    for word in capsule:
        f.write(struct.pack('<I', word & 0xffffffff))

print(f"生成胶囊,共 {len(capsule)} 个字,{len(capsule)*4} 字节")

这个示例当然不能运行真实的 Linux,但它揭示了胶囊的本质:用一段可自我描述的整数序列,把多个软件组件绑定成单一工件。真实的 ESI 工具链会更复杂(例如 ELF 重定位、动态链接、符号表、压缩、校验和),但核心思想不变。

5.3 为什么“一串数字”比“Docker 镜像”更适合保存?

Docker 镜像本质上是 Linux 文件系统的层级快照,它的可运行性依赖于:x86 CPU、Linux 内核、containerd、runc、OCI 规范、网络、DNS、仓库认证。只要这些外部依赖中有一个在未来失效,镜像就不可解释。

而胶囊的依赖是:知道 Subleq+ 指令语义、能存储数字、能减法。这门槛低得多。你甚至可以把 VM 规范和 capsule 一起刻在石碑上:

subleq a,b,c: mem[b] -= mem[a]; if mem[b] <= 0 goto c。
下面是 1,247,893 个数字。加载它们,从地址 0 开始执行。

六、动手实现一个 Subleq+ 虚拟机

理论说再多,不如跑一段代码。下面我们用 Python 实现一个教学版 Subleq+ VM,再配一段汇编代码,展示它真的能算出结果。

6.1 Python 版 Subleq+ VM

import sys

MMIO_OUT = -1  # 写入该地址即输出字符
MMIO_IN  = -2  # 读取该地址即输入字符

def run(image, pc=0):
    """
    image: 初始内存,整数列表
    pc: 起始程序计数器
    """
    M = image[:] + [0] * (1 << 18)  # 预留 1M 字空间
    stdin = iter(sys.stdin.read())

    while True:
        op = M[pc]
        if op == -1:
            break
        a = M[pc + 1]
        b = M[pc + 2]
        c = M[pc + 3]
        pc += 4

        # 取源地址和源值
        if op & 1:
            src_addr = M[a]
        else:
            src_addr = a
        src = M[src_addr] if src_addr != MMIO_IN else ord(next(stdin, '\0'))

        # 取目标地址
        if op & 2:
            dst_addr = M[b]
        else:
            dst_addr = b

        # 执行减法并写回
        if dst_addr == MMIO_OUT:
            sys.stdout.write(chr(src & 0xff))
        else:
            M[dst_addr] -= src
            res = M[dst_addr]
            if res <= 0:
                pc = c

if __name__ == '__main__':
    # 从文件读取整数列表,空格分隔
    words = list(map(int, open(sys.argv[1]).read().split()))
    run(words)

这个 VM 有这几个要点:

  • 每条指令 4 个字:OP, A, B, C
  • OP 的最低两位控制间接寻址:
    • 0:直接-直接
    • 1:间接 A
    • 2:间接 B
    • 3:间接-间接
  • OP == -1 时停机。
  • -1-2 做两个内存映射 I/O 地址,方便做“Hello World”。

6.2 计算 1 + 2 + ... + 10 的 Subleq+ 程序

下面是一段用文本助记符写的程序,配合一个极小的汇编器即可运行:

; 寄存器/变量定义
Z:     .word 0
one:   .word 1
n:     .word 10
sum:   .word 0

loop:
    subleq Z, Z, l1      ; Z = 0
l1:
    subleq n, Z, l2      ; Z = -n
l2:
    subleq Z, sum, l3    ; sum += n
l3:
    subleq one, n, done  ; n -= 1; if n <= 0, done
    subleq Z, Z, loop    ; 无条件跳回 loop(Z 已经是 0)
done:
    halt

这段代码最终把 1+2+...+10 = 55 写入 sum 所在的内存字。它没有用到间接寻址,但已经展示了 Subleq+ 里循环、条件分支、累加三大基本控制结构是怎么用减法拼出来的。

6.3 C 语言参考 VM:50 行真的够

ESI 官方说参考 VM 用 C 写大约 50 行。下面是一个等价但更紧凑的版本,突出“餐巾纸级复杂度”:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char **argv) {
    int32_t M[1 << 20], pc = 0, n = 0;
    FILE *f = fopen(argv[1], "rb");
    while (fread(&M[n], sizeof(int32_t), 1, f)) n++;
    fclose(f);

    while (1) {
        int32_t op = M[pc], a = M[pc+1], b = M[pc+2], c = M[pc+3];
        if (op == -1) break;
        pc += 4;
        int32_t src = (op & 1) ? M[M[a]] : M[a];
        int32_t *dst = (op & 2) ? &M[M[b]] : &M[b];
        *dst -= src;
        if (*dst <= 0) pc = c;
    }
    return 0;
}

编译命令:

gcc -O2 eternal_vm.c -o eternal_vm
./ eternal_vm demo.capsule

就这几行代码,已经足够表达一个能运行 Linux 的虚拟机。这是 ESI 最震撼人的地方:

不是“这台机器很强大”,而是“这台机器的简单性让它可以活很久”。


七、性能优化:让极简架构跑得快

Subleq+ 的简单是有代价的:执行同样算法,它可能需要比 x86 多几个数量级的指令。但 ESI 不是要替代现代 CPU,而是要提供一个可长期保存的通用规范。在这个前提下,性能可以通过规范层之上的优化来解决。

7.1 虚拟机实现层优化

即使是同一个规范,VM 实现也可以很快:

  • 直接内存映射:不要每条指令都解码,而是把 capsule 直接映射到内存数组,PC 递增 4。
  • 计算跳转(computed goto):用 GCC 的 &&label 特性把指令分发从 switch 改成跳转表,减少分支预测失败。
  • 超指令(superinstruction):把常见的指令序列(如 清零临时变量 + 取负 + 加法)合并成一条内部超指令,减少分发开销。
  • 缓存友好的内存布局:尽量让热路径数据在相邻地址,利用 CPU 缓存。

7.2 提前编译与即时编译

更激进的做法是:把 capsule 里的 Subleq+ 指令翻译成宿主 CPU 的机器码。例如:

  • AOT(Ahead-of-Time):启动时扫描整个 capsule,为每个 Subleq+ 基本块生成对应 x86 或 ARM 指令,然后直接执行原生代码。
  • JIT(Just-in-Time):只在热点路径上动态编译,冷路径保留解释执行。

这样,用户在前端得到接近原生的速度,但底层保存格式仍然是那串数字。未来的人哪怕没有 AOT/JIT 技术,也能用最简单的解释器把软件恢复出来。性能优化不污染保存格式,这是分层架构的胜利。

7.3 硬件实现

如果你真愿意,可以直接在 FPGA 或 ASIC 上实现 Subleq+ 处理器。因为它只有一条指令,控制逻辑极小。你可以做出一个能耗极低、寿命极长的“千年计算机”原型。它不需要乱序执行、分支预测、缓存一致性,只需要:

  • 一个减法器
  • 一个比较器
  • 一个程序计数器
  • 一个内存接口

这对于太空探测器、地质档案馆、核废料存储设施等“需要长期自主运行”的场景特别有吸引力。


八、能跑 DOOM,还能保存什么?

ESI 的演示 capsule 里已经能跑 DOOM——这款游戏是程序员圈的“经典试金石”。如果一个系统能跑 DOOM,说明它至少有:

  • 可工作的 CPU
  • 可运行的操作系统(至少文件系统 + 进程调度)
  • 图形输出能力
  • 用户输入处理
  • 足够的内存和性能

所以 DOOM 不仅是游戏,它是一个最小化的现代软件生态验证。ESI 能跑 DOOM,意味着它已经把“硬件抽象层、操作系统、C 库、图形、输入”这一整串链路跑通了。

8.1 适合保存的软件

Subleq+ + Linux 胶囊最适合保存的是:

  • 开源操作系统和系统工具:Linux、BusyBox、uClibc-ng、coreutils、编辑器。
  • 科学计算和模拟程序:依赖 CPU 计算、不依赖在线数据库或专有硬件的程序。
  • 经典游戏:DOOM、Quake、大量独立游戏。
  • 文档与数字艺术:如果把渲染器也打包进去,PDF、图片、文本都可以变成可运行对象。
  • 开发工具链:编译器、解释器、构建系统,让未来的人可以在这个环境上继续开发。

8.2 不太容易保存的东西

也要诚实地说,ESI 不能包治百病:

  • 强依赖云服务的应用:在线协作、流媒体、SaaS,一旦服务器消失,前端再完整也没用。
  • 专有硬件驱动:GPU 加速、TPU、专用 DSP,这些程序依赖无法被标准化的黑盒硬件。
  • 需要实时交互和极低延迟的系统:高频交易、工业控制,Subleq+ 的抽象层开销太大。
  • 法律和授权问题:很多软件不是开源的,即使技术上能打包,法律上也不能随意保存和分发。

所以 ESI 更像是一个数字文明的“种子库”,而不是“把所有软件都冻起来”的万能方案。


九、总结:一次关于“时间”的程序员实验

Eternal Software Initiative 让我想到一个问题:我们每天写代码,到底是在建造,还是在制造短期消费品

ESI 给出的答案不是“让我们回到 1980 年代”,而是**“用最简单的抽象层,把复杂度锁进当下,把未来交给未来”**。它用 Subleq+ 这条极简指令作为时间胶囊的通用语言,用 LLVM 后端把现代软件翻译进去,用 Linux 胶囊把完整生态封装起来,最终交付物只是一串数字。

这套方案的可贵之处不是性能,而是思想

  1. 简化才能永生:复杂的东西必须依赖更多复杂的东西,而简单的东西只需要被理解。
  2. 规范与实现分离:保存规范,让未来的实现者自行选择最合适的硬件。
  3. 自包含:把所有依赖都放进一个胶囊,而不是依赖外部不断变化的生态。
  4. 分层优化:保存格式保持极简,运行时可以通过 VM、AOT、JIT、硬件任意加速。

作为一个程序员,我未必会把明天的生产环境直接搬到 ESI 上,但我会把它当作一个思考工具:每次引入一个新依赖、一个新框架、一个云原生服务时,问问自己——如果 50 年后有人要运行这段代码,他需要知道多少东西?

如果答案是“很多,而且大多数都依赖还在运营的公司”,那这段代码可能正在走向 ESI 所说的“10 年半衰期”。

1000 年的软件保存听起来宏大,但它背后的工程原则其实很小:

用最少的假设,做最长久的承诺。


十、给程序员的实践启发:如何写更长寿的代码

ESI 最牛的地方不是它的代码,而是它提出的问题:我们该用什么标准评价一段代码的“生命周期”?

在 2026 年的开发者眼里,一个好项目通常看:CI 绿不绿、测试覆盖率、QPS、启动速度、社区 Star 数。但很少有人问:如果 30 年后我的依赖仓库 404 了,这段代码还能不能编译?如果 100 年后没有 npm、没有 Docker Hub,它还能不能被理解?

ESI 给出了一组可以迁移到日常工程的启发:

  1. 降低外部依赖的“隐式深度”
    每引入一个依赖,都要想一想它背后又依赖了什么。一个日志库可能拉起半打 JSON 解析器和网络客户端。对于要长期维护的核心模块,依赖越少,未来被恢复的概率越高。

  2. 用文本协议和明文格式保存数据
    二进制专有格式在未来几乎无法被逆向。CSV、JSON、Markdown、纯文本日志,虽然低效,但可读性极强。ESI 用“一串整数”保存软件,也是同一思想的极致。

  3. 把架构假设写进文档,而不是藏在代码里
    未来的维护者不会知道你为什么用某个特定的 API。把架构决策、约束、不可变假设写成 ADR(Architecture Decision Records),是降低未来理解成本最有效的做法。

  4. 保留可自举的构建链
    如果项目需要 17 个现代 SaaS 才能编译,那它的寿命不会超过这些 SaaS 的寿命。保留一个能离线运行的、最小化的构建脚本,是一种“数字末日保险”。

  5. 接受性能与寿命的权衡
    就像 ESI 用极简指令换取可解释性,有时候为了长期可维护,我们应该主动选择更“笨”但更少依赖的方案。一个手写的小脚本,可能比一个基于 20 个微服务的系统活得更久。

这些原则不是让我们退回到石器时代的开发方式,而是提醒:不要把“现在能跑”等同于“未来还在”。短期看,复杂的架构和依赖能提升效率;长期看,它们会加速腐烂。


参考与延伸阅读

  • Eternal Software Initiative 官网:https://eternal-software.org/
  • 相关报道:Eternal Computer 极简虚拟机发布(2026-06-18/19)
  • Subleq 图灵完备性证明:OISC(One Instruction Set Computer)相关文献
  • LLVM 后端开发文档:LLVM Target-Independent Code Generator
  • uClibc-ng、BusyBox、Linux 内核源码

本文示例代码为教学简化版,不代表 ESI 官方实现的精确 ABI 或文件格式。实际使用请以官方仓库和文档为准。

推荐文章

API 管理系统售卖系统
2024-11-19 08:54:18 +0800 CST
Python 微软邮箱 OAuth2 认证 Demo
2024-11-20 15:42:09 +0800 CST
Vue3中的Slots有哪些变化?
2024-11-18 16:34:49 +0800 CST
Vue3中如何进行性能优化?
2024-11-17 22:52:59 +0800 CST
用 Rust 构建一个 WebSocket 服务器
2024-11-19 10:08:22 +0800 CST
基于Flask实现后台权限管理系统
2024-11-19 09:53:09 +0800 CST
淘宝npm镜像使用方法
2024-11-18 23:50:48 +0800 CST
CSS Grid 和 Flexbox 的主要区别
2024-11-18 23:09:50 +0800 CST
【SQL注入】关于GORM的SQL注入问题
2024-11-19 06:54:57 +0800 CST
php内置函数除法取整和取余数
2024-11-19 10:11:51 +0800 CST
Golang实现的交互Shell
2024-11-19 04:05:20 +0800 CST
程序员茄子在线接单