每周见闻(79):为什么坦克几乎不用 Windows?
约 2906 字大约 10 分钟
2026-08-09
每周见闻:2026-08-03 - 2026-08-09
为什么坦克几乎不用 Windows?[^9]
标签:FUN,操作系统
这是个很有意思的话题。相信不少朋友见过 ATM、地铁、医院自助机故障时出现的 Windows 系统界面,做开发的小伙伴或许会会心一笑:这居然用的是 Windows?虽然有听说过军工领域不用 Windows,但背后的原因倒是很少了解。要感谢作者揭开这层迷雾。
原因在于 Windows 的内核从根上就是为桌面体验设计的:即插即用、注册表、延迟写入的文件系统缓存、系统恢复点——后台绑着一大堆不可分割的状态。你点关机,内核要一层层通知服务、刷缓存、写注册表状态。而战场环境复杂,物理冲击、电磁干扰,瞬间断电。主炮刚开完一轮,车长等火控计算机重新启动,屏幕上跳出请按 F1 继续。那是人命。
这些对于坦克反而不是必须的。死得干脆,活得极快,原始得近乎野蛮,但这才是物理世界冲击下最让人安心的东西。作者最后说了一句话,我印象很深:Windows 能统治桌面,是因为它足够包容。坦克不需要包容。它只需要确定。

AI 工具的成本控制
上周对我影响最大的新闻,莫过于 DeepSeek 官宣会大幅涨价。因为这个月我的 Trae 国际版包年到期,正在重新复盘 AI 工具成本。
而我又是 DeepSeek 的重度用户,在工作以外的时间基本都使用它来辅助,目前的支出是 60 元/月。本来打算在 Trae 之后全面转向 DeepSeek 的,目前只能再做观望了。
更详细的 AI 工具成本分析,我会在近期整理成文章,敬请期待。

生活
1、别急着说自己做不了[^1]
标签:AI,职场,方法论
作者领导提了个需求:用户和大模型对话的时候,右边实时同步出一份真 Word。然而团队评估了两周,回来的反馈是各种问题:流式难处理、Word 格式坑多、编辑器选型麻烦、模型输出不稳、导出兼容性堪忧。
作者当晚自己动手试了一遍。以 Tiptap + ProseMirror + docx.js 直接做出了一个原型。中间遇到协议、部署等问题,但借助 AI,最后确实跑通了,完成度还比预想的高一点。
以前学个新东西成本高,用身份画边界多少有点道理。现在 AI 把动手验证的门槛拉下来了,再用我不是程序员我不会设计把自己拦在外面,更多是惯性。不会可以查,可以试,试过了还是做不到也没关系,至少知道自己卡在哪。
Coding
1、Your JSON Is Lying to You[^2]
标签:JavaScript,序列化,前端
在浏览器控制台跑一行代码,结果会让你大吃一惊:JSON.stringify({ id: 9007199254740993 }) 序列化出来 id 变成了 9007199254740992。没有报错,JSON 也完全合法,但数据已经变了。
看着这个数字,直觉好的朋友可能已经猜到原因了——就是大整数的关系。当大整数超出 2^53-1 的安全范围会静默舍入——更坑的是,这个舍入在字面量被解析的时候就发生了,轮不到 JSON 出手。
undefined 的属性会被对象丢弃、数组里变成 null,函数和符号也是同样的双标。Date 会被 toJSON 转成 UTC 字符串,解析回来就是普通字符串,时区信息全丢。NaN 和 Infinity 全部变成 null,Map、Set、RegExp、Error 全部变成空对象,类实例的私有字段和原型全没。这些都是 JSON 中的坑。
所以当使用 JSON.parse(JSON.stringify(x)) 做深拷贝时要多留一个心眼。API 边界上的类型约定必须显式,ID 和高精度数字一律用字符串。
const original = {
id: 9007199254740993,
missing: undefined,
createdAt: new Date('2026-07-21T12:00:00Z'),
score: NaN
}
const copy = JSON.parse(JSON.stringify(original))
console.log(copy)
// {
// id: 9007199254740992,
// createdAt: "2026-07-21T12:00:00.000Z",
// score: null
// }标签:JavaScript,工具库,Tools
Microdiff 是一个零依赖且高性能的比较库,API 只有一个 diff(obj1, obj2)。自带 TS 类型支持在 Deno, Node, Bun, 浏览器上都支持。适合用来做 Object 对比、数据检查等工作。
import diff from "microdiff";
const obj1 = {
originalProperty: true,
};
const obj2 = {
originalProperty: true,
newProperty: "new",
};
console.log(diff(obj1, obj2));
// [{type: "CREATE", path: ["newProperty"], value: "new"}]3、Why npm Dependency Trees Are So Big[^5]
标签:NPM,前端工程
这篇文章介绍了为什么 npm 的依赖树会如此巨大。作者以 Rails 举例,Rails 每次发大版本,整个 gem 生态系统都会跟着连锁发版。因为 bundler 强制整个应用里每个 gem 只能有一个版本。只要有冲突就会报错。
而 npm 则从根上就不一样。Node 的 require 是按文件路径找模块的,不是按包名。同个库在不同 node_modules 里有两份,那就是两份独立文件。所以 npm 遇到冲突的默认操作不是报错,而是再装一份。
因此 npm 的依赖树会变得非常大。同时还有一个隐藏的代价,比如 React,如果一个应用里有两个 React 就会导致 hooks 出错。
4、Debugging stuck Node.js processes | HOAi[^7]
标签:Node.js,调试,性能
作者线上的 Node 服务出了很烦的故障:偶发健康检查失败,K8s 自动拉起。单 CPU 打满 100%、没有任何进出流量、日志彻底沉默——典型的事件循环被某段同步代码焊死了。
这种问题我在工作中也遇到过,由于没有日志或者日志不全,排查起来非常头疼。作者一开始也是自己实现了事件循环阻塞检查器。但运行一段时间后发现抓到的错误并非根本原因。于是他们编写了一个脚本:当健康检查超时时,将 node inspect 连接到 Node 进程上。通过 profile 命令获取火焰图进行分析。
这个解法很妙!我用 AI 帮忙解读了代码,有兴趣的朋友可以参考一下,对排查 Node 的错误或许会有帮助。
expect <<EOF
set timeout 30 ;# 设置 expect 超时时间为 30 秒(防止卡死)
spawn node inspect -p $NODE_PID ;# 生成子进程,附加到指定 PID 的 Node.js 调试器
expect "debug>" ;# 等待调试器提示符 "debug>" 出现,表示已连接
send "profile\r" ;# 发送 profile 命令并回车,开始 CPU 性能采样
expect "debug>" ;# 等待提示符再次出现,确认 profile 已开始执行
sleep 5 ;# 睡眠 5 秒钟,采集这段时间内的 CPU 性能数据
send "profileEnd\r" ;# 发送 profileEnd 命令,停止性能采样
expect "debug>" ;# 等待提示符,确认采样已停止,数据暂存在内存
send "profiles\[0\].save()\r" ;# 发送 save 命令保存刚才捕获的第一个剖析文件(注意转义方括号,防止 Tcl 误解析)
expect "debug>" ;# 等待提示符,确认 .cpuprofile 文件已成功写入磁盘
send ".exit\r" ;# 发送 .exit 命令,退出 Node.js 调试器会话
expect eof ;# 等待子进程(node inspect)彻底退出,脚本结束
EOF工具
1、Nutlope/hallmark: Anti-AI-slop design skill for Claude Code, Cursor, and Codex.[^3]
标签:AI,前端,设计系统
设计是 AI 暂时无法触及的领域(至少我是这么认为的,网页设计也是我头疼的事)。
这个 hallmark SKILL 内置了内置 20 套主题,四种工作模式:
- 默认 build 新建页面
- audit 给现有页面打 slop 分数(只列问题不改代码)
- redesign 推翻结构但保留文案和 IA
- study 则是从截图或 URL 里提取设计 DNA,甚至能导出 portable 的 design.md 交给其他 AI 工具。
展示的样例确实看得出差别:面包店的 Hum 主题、唱片公司的 Carnival 主题、旅行类的 atmospheric Wayfare,十几种放一起完全看不出是同一套系统出的。
不敢说有了这个 SKILL 就能代替设计师,但至少拯救了我这种设计小白。我同时会结合第 76 期周刊的 Kill-ai-slop 结合使用。

AI
1、OpenCode 源码解析[^6]
标签:AI,架构
这是一份介绍 OpenCode 源码和架构的电子教材。之前从 Claude Code 换成了 OpenCode,就对其源码有些好奇。虽然指导大致的 ReAct 循环,但对实际的编排并不熟悉,正好借此了解一下。
作者也在附录中为不同目的的读者列出了阅读顺序,如果只是想快速上手,那只要看 1、3、7、8 四个章节即可。

其他
1、An Inside Look at the Relay Market Powering Token Resellers and Fraud | Vectoral[^8]
标签:安全,AI
介绍中转站原理的文章,起因是作者所在的团队被薅得受不了:先有人批量注册号刷免费额度,接着是客服聊天机器人被人当成免费 API 往外转。顺着来源摸下去,他摸到了 V2EX 上的一个帖子,打开了中文 AI API 中转站这个完整的平行世界。
中转站 本质是把美区模型的调用流量以极低折扣转卖给国内开发者。他跟踪的 10 家大站,中位数折扣是官方定价的 94% 到 98%。
整个产业是标准四层。
- 上游是卡商和号商:做能过美欧账单校验的虚拟信用卡,批量注册各种账号。
- 中游是账号池:几十上百个上游账号聚合在一起,token 维护、限流、账号被封时自动切走,向下游暴露一个统一 API。
- 下游就是中转站本身:给池子套一个中文界面的计费面板,做充值、开票、微信群客服。
- 最后是终端用户:小开发者、小公司、SaaS 创业者买便宜算力,还有更大的客户买了去做模型蒸馏。
技术栈主要是 one-api 和它的 fork new-api。用来给内部账号做统一网关和用量统计——问题出在渠道:你的 channel 里塞的是自己买的 key、还是盗刷拒付来的、还是批量薅的免费号。
作者把常见手法列了一遍:免费试用滥用、盗刷后 chargeback、预付费卡头上限薅、套壳支持聊天的产品做 open inference,还有一种新的叫 denial of wallet——不求赚钱,纯并发烧你预算。
参考文章:
- [1] 别急着说自己做不了: https://blog.solazy.me/20260803/
- [2] Your JSON Is Lying to You: https://blog.gaborkoos.com/posts/2026-08-03-Your-JSON-Is-Lying-to-You/
- [3] Nutlope/hallmark: Anti-AI-slop design skill for Claude Code, Cursor, and Codex.: https://github.com/nutlope/hallmark
- [4] AsyncBanana/microdiff: A fast, zero dependency object and array comparison library. Significantly faster than most other deep comparison libraries and has full TypeScript support.: https://github.com/AsyncBanana/microdiff
- [5] Why npm Dependency Trees Are So Big: https://nesbitt.io/2026/07/28/why-npm-dependency-trees-are-so-big.html
- [6] OpenCode 源码解析: https://opencode-book.myhubs.dev/
- [7] Debugging stuck Node.js processes | HOAi: https://engineering.myhoai.com/posts/debugging-stuck-node-js-processes/
- [8] An Inside Look at the Relay Market Powering Token Resellers and Fraud | Vectoral: https://vectoral.com/blog/token-relay-market
- [9] 为什么坦克几乎不用 Windows?: https://mp.weixin.qq.com/s/Y9nx1HJL5KWXdOHc0ucyLA
