QIAOPANG.COM · 陈天(TYR CHEN)2013–2026 精选技术与随笔文集 · 共 260 篇按时间顺序浏览(2013 → 2026)↗
程序人生 · 陈天文集QiaoPang · Systems, Craft & Agentic Era
时间轴 ↗

谈谈 process

谈谈 process

erlang/elixir 是那种你用得越多,就越喜欢的语嫣。

一个多月前,我在 erlang 哪篇文章里,写下了这篇文字:

在 erlang 的世界里,万事万物都是 process。process 就像原子一样,组成分子,细胞,组织,器官,最终构成一副机体(见我的文章:boundary)。那么,process 究竟是什么?

其实它和 OS 的 process 概念几乎一样,就是 PCB(Process Control Block),以及围绕 PCB 的 heap,stack,mailbox 等内存空间。只不过,erlang 的 process 的 memory footprint 很小很小,一个刚初始化的 process,也就占用几百个 words(32bit CPU 下,1 word = 4 bytes,64bit CPU,1 word = 8 bytes)。所以,erlang VM 能创建的 process 理论上取决于内存的大小,我们可以轻易创建百万级,甚至千万级的 process(32bit CPU 的 pid 用 28 bit,64 bit CPU 的 pid 用 60 bit,大家可以自行算算 process 的上限)。erlang 的 process 源自 actor model 的思想,它是几种常见的 concurrency model 的一种(其它的 model 请参考我的文章:)。process 和 process 通过发送和接收消息来处理各种事务。

谈谈 process (出自:erlang garbage collector and why it matters)

process 其实很像是 OOP 中的 object:process 之间是隔离的 —— 一个 process 无法访问另一个 process 的内部状态,这是封装的概念,而通过使用 parent/child process 也可完美实现继承和多态。实际上,erlang 算得上是 OOP 始祖 smalltalk 的正统的传承者(另一个渐渐淡出大家视野的传人是 ObjC)。

今天我们着重讲讲 process,以及我对 process 的一些不成熟的认知和使用方法。

表面上看 process 似乎和任何一门 OOP 语言中的 object 类似。它有 state,有 behavior,能接受外界的输入,并为这个输入返回结果,或者改变自己的状态。下面是一个非常简单的,仅用于 demo 的 kv store 的 python 版本:

class KVStore(object):
    def __init__(self):
        self.store = {}

    def put(self, k, v):
        self.store[k] = v

    @memoize
    def get(self, k):
        return self.store[k] if k in self.store else None

elixir/OTP 版本:

defmodule KVStore do
    use GenServer

    # public interface    
    def start_link, do: GenServer.start_link(__MODULE__, nil, name: __MODULE__)
    def put(k, v), do: GenServer.cast(__MODULE__, {:put, k, v})
    def get(k), do: GenServer.call(__MODULE__, {:get, k})
    
    # callback
    def init(_), do: {:ok, %{}}
    def handle_call({:get, k}, _from, state), do: {:reply, get(state, k), state}
    def handle_cast({:put, k, v}, state), do: {:noreply, put(state, k, v)}
    
    # private functions
    defm get(state, k), do: Map.get(state, k)
    def put(state, k, v), do: Map.put(state, k, v)
end

注:这里我们先别管 @memoize 和 defm 是干嘛的,稍后揭晓。

二者的调用代码,异曲同工,前者生成一个对象,后者生成一个 named process:

In [23]: store = KVStore()
In [24]: store.put("tyr", "chen")
In [25]: store.get("tyr")
Out[25]: 'chen'
iex(7)> KVStore.start_link()
{:ok, #PID<0.176.0>}
iex(8)> KVStore.put("tyr", "chen")
:ok
iex(9)> KVStore.get("tyr")
"chen"

实现同样的功能,就这个 case 而言,elixir 的代码量大大高于 python。然而,他们运行的状态截然不同。elixir 版本的 KV Store(下文称 EKV)生活在自己的世界里,有独立的人格;而 python 版本的 KV store(下文称 PKV)则严重依赖宿主 —— 运行的上下文是啥它就依附于啥,管他是 WSGI process 还是一个 CLI process。

MORE IN 系统与架构

同专栏延伸阅读

查看「系统与架构」全部文章 →

日志的未来:必也正名乎

我们花了十年,把可观测性盖成一座漂亮的大厦,地基却是漂浮的字符串:字段名靠默契、基数靠运气、账单靠忍。这篇文章给出一个激进的方案,用 protobuf 给每一件被观测的事正名,把日志、指标、审计统一成一份带版本、带 owner、带保留策略的事件目录,旁边留一扇叫 ForensicEvent 的逃生舱兜住所有未知未知。AI 已经成为代码的主笔,schema-first 的最后一道阻力随之消失。是时候让 schema 重新成为可观测性大厦的

New Hope (2025–2026)10,772 字 · 24 分钟

彻底抛弃多环境:用 Rust 与 Pingora 重塑下一代 Serverless 架构

当我们退回原点重新思考"计算"的本质,会发现多环境是个幻觉,K8s 是个过度抽象,而 Serverless 的冷启动和连接池风暴是自找的。这篇文章拆解一套基于 Baggage Header 路由、Pingora 智能网关、Firecracker 微虚拟机和 Rust Data Bus 的无环境架构,试图回答:Post-Kubernetes 时代的计算该长什么样。

New Hope (2025–2026)23,788 字 · 53 分钟