2024-12-27

38 篇热帖

1. Ghostty 1.0 (ghostty.org)

Ghostty 1.0 摘要

产品概述

Ghostty 是一款高速、功能丰富、跨平台的终端模拟器,具有以下核心特性:

  • 速度快:高性能终端模拟器
  • 功能丰富:提供全面的终端功能
  • 跨平台支持:兼容多个操作系统
  • 原生UI:使用各平台原生界面
  • GPU加速:利用图形处理器加速渲染

项目信息

文档结构

项目提供详尽的文档体系,包括:

  • 安装指南:二进制包、源码构建、打包说明、预发布版本
  • 配置参考:选项说明、键绑定、操作参考
  • 平台支持:Linux(Systemd/D-Bus)、macOS(AppleScript、登录Shell、窗口管理器兼容)
  • 功能特性:色彩主题、Shell集成、SSH支持
  • 终端API (VT):控制序列、ESC序列、CSI/OSC命令的完整参考
  • 帮助文档:Terminfo、GTK单实例、OpenGL上下文、同步输出等技术细节

版本历程

项目已发布多个版本,从1.0.1到最新的1.3.1,持续迭代改进。

3. Does current AI represent a dead end? (www.bcs.org)

文章访问状态总结

提供的网页内容并非关于“当前AI是否代表死胡同”的文章正文,而是一个 Cloudflare 的安全验证(挑战)页面。这意味着用户或爬虫在访问该文章时,被网站的安全系统拦截,要求完成验证才能继续。

关键信息

  • 页面标题Just a moment...(“请稍候...”)
  • 核心状态访问受阻。页面提示用户必须启用 JavaScript 和 cookies 才能继续(Enable JavaScript and cookies to continue)。
  • 页面功能:此页面是网站 反机器人(Anti-bot)保护系统 的一部分。它通过加载和执行来自 challenges.cloudflare.com 的 JavaScript 脚本来进行验证,以区分真实用户和自动化程序。
  • 技术细节
    • 页面包含严格的 内容安全策略(CSP),限制了脚本、样式等资源的加载来源。
    • 会自动在后台加载验证脚本(如 orchestrate/chl_page/v1)。
    • 有一个360秒的自动刷新(http-equiv="refresh" content="360")。
  • 可见内容:页面主体仅显示一个错误提示区域的框架,但默认情况下,如果脚本未运行,该提示(“启用JavaScript和cookies...”)是可见的。

结论

根据所提供的实际网页内容无法获取文章《Does current AI represent a dead end?》的任何实质性信息、观点或摘要。所得到的仅是一个表明访问被安全机制拦截的技术性页面。要访问原文内容,需要在支持JavaScript的浏览器环境中通过此验证。

4. Bill requiring US agencies to share source code with each other becomes law (fedscoop.com)

美国法案要求联邦机构共享自定义源代码

美国总统拜登签署了《信息技术源代码协调与重用法案》(SHARE IT Act,H.R. 9566),要求美国各联邦机构相互共享自定义开发的源代码,以减少重复软件开发合同,节约政府开支。

主要目的与内容:

  • 减少浪费:该法案旨在解决联邦政府每年在软件采购上约120亿美元开支中的低效问题,避免各机构在不知情的情况下,重复雇佣承包商开发已有代码。
  • 共享要求:机构需公开列出自定义代码,并与其他机构共享。
  • 适用范围:该要求不适用于涉密代码、国家安全系统或共享后可能带来隐私风险的代码。

关键实施细节:

  • 制定政策:各机构的首席信息官需在法案生效后180天内制定实施政策。
  • 政策内容:政策需确保自定义代码符合最佳实践,建立公开自定义代码元数据的流程,并制定标准化的报告流程。
  • 元数据定义:法律规定的元数据包括:代码是合同开发还是来自共享仓库、合同编号以及指向共享仓库的超链接。

背景与支持:

  • 该法案由参议员特德·克鲁兹(共和党)、加里·彼得斯(民主党)和众议员尼古拉斯·兰沃西(共和党)、威廉·蒂蒙斯(共和党)发起,于12月在两院获得压倒性支持通过。
  • 协作软件公司Atlassian和GitLab Inc.对该立法表示支持,认为更大程度的代码共享将促进联邦机构间的开放、效率和创新。
5. Why OpenAI's Structure Must Evolve to Advance Our Mission (openai.com)

OpenAI 为推进其“确保通用人工智能(AGI)造福全人类”的使命,正在评估并调整其公司结构。其董事会旨在实现三个核心目标:选择最利于使命长期成功的结构、确保非营利部分可持续发展,并赋予每个部分相应的能力。

历史与现状 OpenAI 于2015年作为非营利研究实验室成立,初期依靠捐赠(现金、计算资源等)运营。随着AI研发对算力需求激增,所需资本远超捐赠所能支持。2019年,OpenAI转型,创立了一家由非营利控制、投资者和员工享有利润上限的营利性公司,以筹集所需资金(如从微软获得10亿美元投资)。

营利部分的成功(如ChatGPT等产品)使OpenAI影响力扩大,推动了行业竞争和安全创新。然而,为继续领跑AGI研发,所需资本规模再次大幅增长。投资者在如此大规模下,需要更传统的股权结构和更少的定制化条款。

未来计划 进入2025年,OpenAI旨在从“实验室与初创企业”转变为“可持续的公司”。董事会正考虑将现有营利实体转型为特拉华州公益公司(PBC)。PBC结构要求公司在决策中平衡股东、利益相关者和公共利益,这符合其使命,也便于以常规条款融资。

此次调整的具体目标包括:

  1. 优化结构:采用PBC结构,以常规条款筹集必要资本,支持使命长期成功。
  2. 使非营利可持续:现有非营利部分在营利实体中的重大权益将转换为PBC股份(由独立财务顾问公平估值),这将使其成为资源最雄厚的非营利机构之一,其资源将远超捐赠者最初投入。
  3. 赋能各方:PBC将负责运营OpenAI的业务;非营利部分则将组建团队,在医疗、教育、科学等领域开展慈善项目。

OpenAI强调,AGI的使命是持续的目标,而非单一系统的构建。公司希望通过此次结构进化,参与构建21世纪的AGI经济,并确保其造福人类。

6. Fake Nintendo lawyer is scaring YouTubers, and its not clear YouTube can stop it (www.theverge.com)

近期,YouTube平台上出现多起假冒任天堂律师的版权攻击事件,对游戏内容创作者构成严重威胁。以下是事件的核心要点:

事件概述

德国YouTuber Domtendo(拥有超150万粉丝)在发布《塞尔达传说:智慧的再现》系列视频后,收到署名“Tatsumi Masaaki,任天堂法务部”的版权警告,其视频被下架并累计两次版权警告(再收到一次将导致频道被封)。类似事件也波及其他创作者,如Waikuteru(Zelda模组开发者)和Retro Game Corps等。

虚假警告的特征

  • 可疑发件地址:警告来自加密邮箱“tatsumi-masaaki@protonmail.com”,而非任天堂官方域名。
  • 伪造官方邮件:攻击者使用邮件欺骗技术,使部分邮件看似来自“anti-piracy3@nintendo.co.jp”等任天堂合法地址。
  • 持续骚扰与威胁:假冒者“Tatsumi”通过邮件不断要求删除视频,威胁法律诉讼,甚至声称已获取创作者地址信息。
  • 矛盾与反常:警告内容包含法律错误(如错误引用保护平台而非创作者的DMCA条款),且要求删除所有使用Switch模拟器的视频(与任天堂通常策略不符)。

YouTube系统漏洞

  • 低门槛举报机制:用户可通过网页表单或直接邮件提交版权投诉,YouTube承认约6%的表单投诉涉嫌滥用。
  • 验证不足:法律虽要求投诉方提供真实信息并承担伪证责任,但YouTube未强制核实身份即自动处罚创作者。
  • 申诉困难:创作者反映,小型频道难以有效申诉版权警告,YouTube可能根据频道规模自动拒绝其抗辩文件。

各方回应

  • 创作者反应:Domtendo等人因担心频道被封,一度自行删除视频。部分创作者开始自我审查以避免风险。
  • 任天堂确认:任天堂法务部回复Domtendo,确认protonmail地址并非合法,且警告内容不符合其执法惯例,但表示正在调查。
  • YouTube回应:平台确认“Tatsumi”提出虚假主张,声称有团队检测并逆转此类滥用行为,但未解释为何初期接受可疑地址的投诉,也未承诺系统性改进。
  • 假冒者态度:The Verge联系“Tatsumi”时,对方仍以任天堂授权代理人身份回应,拒绝采访。

影响与争议

  • 创作者风险:虚假警告可直接导致频道关闭,且创作者难以区分真假威胁,可能面临收入与职业生涯损失。
  • 法律设计缺陷:DMCA的“安全港”条款旨在保护平台而非创作者,平台为免责倾向于快速响应投诉,加剧了滥用问题。
  • 业界担忧:事件凸显YouTube版权系统易被恶意利用,且缺乏有效制衡机制,任天堂等公司的真实执法行动也可能因假冒事件而复杂化。

此次事件揭示了在线内容平台上版权管理机制的脆弱性,以及创作者在虚假投诉下的被动处境。

7. Quiver: A Modern Commutative Diagram Editor (github.com)

Quiver:现代交换图编辑器
Quiver 是一个现代化的图形编辑器,用于创建交换图和粘贴图,能够渲染高质量的图表以供屏幕查看,并支持通过 tikz-cd 或 fletcher 导出为 LaTeX 或 Typst 格式。与手写 LaTeX 或 Typst 代码相比,使用 Quiver 创建和修改图表的速度显著提升,经验熟练后甚至可媲美纸笔绘图。用户可通过教程学习高效使用,并访问 q.uiver.app 在线试用。

主要特点与功能

  • 提供高效直观的界面,轻松绘制复杂交换图、粘贴图,包括拉回、推出、伴随和高阶单元等结构。
  • 对象放置基于灵活网格,自动根据标签大小调整尺寸。
  • 支持多种可组合箭头样式,并允许自定义标签和箭头颜色。
  • 设计兼顾截图美观性,导出的 LaTeX 和 Typst 代码尽可能还原原始图表。
  • 支持鼠标点击拖拽和完整键盘快捷键操作,提升编辑效率。
  • 导出图表时嵌入链接,便于后续修改或分享。

扩展功能

  • 多重选择:支持批量修改,快速完成大面积更改。
  • 历史系统:允许撤销和重做操作。
  • 自定义宏定义:通过粘贴 URL 引入包含 \newcommands 的文件。
  • HTML 导出:生成可嵌入网页的图表。
  • 平移与缩放:适用于大型图表的导航。
  • 智能对齐:自动优化标签对齐和边缘偏移。

编辑器集成与构建
编辑器集成详情可在 Quiver wiki 中查看。本地构建时,运行 make 命令并在浏览器中打开 src/index.html;若遇问题,可手动下载 KaTeX 至 src/KaTeX/ 目录。Quiver 需通过 localhost 运行,建议使用 Python 的 python -m http.server 命令启动本地服务器,然后访问 localhost:8000

致谢
感谢 S. C. Steenkamp、AndréC、Andrew Stacey、Théophile Cailliau、Nathan Corbyn、Paolo Brasolin、Carl Davidson 等贡献者,以及所有通过提交请求、报告问题或建议改进参与优化 Quiver 的人员。

9. Lua Is So Underrated (nflatrea.bearblog.dev)

Lua Is So Underrated 文章总结

本文旨在强调Lua语言设计优秀但未被广泛认知的现状,并概述其核心优势与特性。

核心观点:Lua因其设计精良、代码高效而备受推崇,但因缺乏市场宣传,常被视为游戏与嵌入式领域的“小众”语言,其潜力未被充分认识。

主要优点:

  1. 简洁易学:Lua语法极简、设计干净,易于理解且能快速掌握。其C API封装良好,在提供高性能的同时,确保了源码与二进制层面的兼容性。
  2. 高度可嵌入:作为设计初衷,Lua能轻松嵌入到C/C++等语言编写的应用程序中,是扩展游戏和嵌入式应用的绝佳选择。
  3. 多范式支持:Lua支持命令式、函数式、面向对象等多种编程范式,提供了灵活性。

值得注意的特性(可能对部分开发者而言不直观):

  1. 索引惯例:惯例上索引从1开始,且标准库函数(如ipairs)均基于此假设。尽管技术上可从任意非nil值开始索引,但为通用性,建议遵循从1开始的惯例。
  2. 错误处理:错误可以作为值返回和处理(类似Go),使用pcall捕获错误,这需要习惯。
  3. nil终止数组:作为数组使用的表会以遇到的第一个nil值终止。ipairs迭代将因此提前停止。若数组可能存在间隔(nil值),应使用pairsnext函数进行遍历。

结论:文章鼓励寻求高效、直接的脚本语言的开发者尝试Lua,并以Neovim(自0.5.0版起使用Lua作为插件语言)为例,佐证其效率。

10. Build a working game of Tetris in Conway's Game of Life (2014) (codegolf.stackexchange.com)

在Conway生命游戏中构建Tetris(2014)

架构概述

本文描述了为在Conway生命游戏中实现Tetris而设计的一种16位异步RISC Harvard架构计算机。其关键设计决策包括:

  • 无寄存器设计:所有RAM地址均可作为指令操作数,实现类似寄存器的功能。
  • 内存映射:程序计数器(PC)地址为0,控制流通过写入PC实现。
  • 串行数据传输:采用小端序串行传输,简化加法/减法电路,避免复杂总线。
  • Harvard架构:程序存储器(ROM)与数据存储器(RAM)分离,优化尺寸。
  • 16位数据宽度:支持足够范围(-32768至32767),满足Tetris棋盘需求(10列)。
  • 异步设计:数据携带“时钟信号”,适应不同路径延迟。
  • 统一指令格式:每条指令包含1个操作码和3个操作数(值、值、目标地址)。
  • 简化寻址模式:支持立即、直接、间接和双间接寻址。

功能与ALU操作

  • 条件移动:实现“非零则移动”(MNZ)和“负则移动”(MLZ),支持条件执行和跳转。
  • 算术运算:原生支持加法/减法,采用二进制补码表示,乘法等需软件实现。
  • 位运算:包括AND、OR、XOR及“与非”(ANT),后者避免从无信号生成信号。
  • 位移操作:支持左移(SL)、逻辑右移(SRL)和算术右移(SRA),用于图形操作和乘除基础。

指令流水线

每个CPU周期包含五个阶段:

  1. 取指令:从ROM获取当前PC对应的指令。
  2. 写前一结果:将上一指令结果写入RAM(若条件满足)。
  3. 读操作数:根据寻址模式从RAM读取当前指令的数据。
  4. 计算结果:ALU执行运算或条件移动。
  5. 递增PC:更新程序计数器。

分支延迟槽:跳转指令后必须跟随一条指令(或空操作),影响程序优化。

寻址模式

通过两位代码指定操作数处理方式:

  • 立即模式(00):直接使用硬编码值。
  • 直接模式(01):从指定RAM地址读取数据。
  • 间接模式(10):通过地址间接读取数据。
  • 双间接模式(11):通过两级地址间接读取数据。

QFTASM汇编语言

  • 为处理器设计的汇编语言,与机器码一一对应。
  • 11个操作码:包括条件移动(MNZ、MLZ)、算术(ADD、SUB)、位运算(AND、OR、XOR、ANT)和位移(SL、SRL、SRA)。
  • 示例代码:斐波那契序列和格雷码程序展示了条件跳转和间接寻址的使用。
  • 提供在线解释器,支持单步执行和内存可视化。

Cogol高级语言

  • 基于QFTASM的高级语言,语法类似C,但结构简化。
  • 主要特性
    • 变量赋值和基本运算符。
    • 循环结构(if、while、do-while)。
    • 一维数组和指针运算。
    • 子程序与调用栈,支持递归。
  • 编译器功能
    • 全局变量分配及临时地址管理。
    • 将Cogol代码转换为QFTASM,优化分支延迟槽。
  • 调试标签:在代码块前添加描述性标签,便于定位。

Tetris实现

  • Tetris程序用Cogol编写,编译后QFTASM代码少于300条指令。
  • 为优化指令长度,部分子程序被内联,数组替换为变量列表或硬编码值。
  • 最终代码仅保留一个子程序,体现Cogol在复杂逻辑下的实用性。
11. Short Message Compression Using LLMs (bellard.org)

文章标题: 使用LLMs的短消息压缩

本文介绍了基于大型语言模型(LLMs)的短消息压缩工具ts_sms。该工具通过示例展示了压缩和解压功能:使用./ts_sms c压缩英文文本后输出Unicode字符串,解压时使用./ts_sms d恢复原文。与brotli压缩工具相比,ts_sms在处理短消息时更高效,因为brotli虽嵌入字典优化压缩,但压缩结果较长。ts_sms提供Linux和Windows版本的下载。技术上,ts_sms类似ts_zip,采用兼容算术编码的填充系统,无需显式编码消息长度。作者为Fabrice Bellard。

12. OpenAI is Visa – Buttering up the government to retain a monopoly (sherwood.news)

文章对比了OpenAI与Visa的发展路径,指出OpenAI可能正效仿Visa通过非技术手段(如政策游说、排他性协议)巩固市场垄断地位,以应对AI技术商品化的潜在威胁。

一、Visa的垄断策略历史

  • Visa始于银行信用卡网络,早期通过建设账户验证和反欺诈系统构建技术壁垒,成为支付处理领域的事实垄断者。
  • 2010年代面临数字支付商(如PayPal)和国家级实时支付系统(如印度UPI、欧洲各国的免费银行间转账)的竞争威胁。
  • 应对方式:通过激进商业条款锁定大客户(如Costco、Apple),并花费巨额游说美国政府,延迟了美国联邦即时支付系统(FedNow)的推出(至2023年),从而维护自身市场地位。

二、OpenAI面临的类似挑战

  • 收入高度依赖大语言模型(LLM),但该技术正快速商品化。Meta、谷歌、亚马逊等公司已推出基础模型,部分开源模型(如Llama)可免费使用,降低了技术壁垒。
  • OpenAI高管Sam Altman承认“AI推理引擎将变得廉价且普及”,API业务收入可能萎缩。
  • 竞争对手众多(谷歌、Meta、亚马逊、Anthropic等),且硬件端(如苹果可能推出设备端LLM)也可能削弱云端模型需求。

三、OpenAI的垄断布局策略

  1. 政策与政府关系:Altman频繁游说美国国会,推动AI监管立法,可能借此建立准入门槛。
  2. 排他性投资条款:最新融资中要求投资者不得资助竞争对手(如Anthropic)及应用层公司(如Perplexity),限制行业竞争生态。
  3. 客户锁定:声称已服务92%的《财富》500强企业,通过长期合同巩固企业级市场。
  4. 资源控制:可能通过与合作伙伴签订排他协议,限制对手获取芯片、数据中心、能源等关键资源。

四、策略风险与外部环境

  • 政治阻力:马斯克等竞争对手影响力上升,可能推动AI监管放松,削弱OpenAI的政策游说效果。
  • 技术民主化:开源模型与设备端AI发展可能加速技术扩散,难以维持技术壁垒。
  • 文章指出,OpenAI和Visa均奉行“竞争是失败者的游戏”,但过度依赖非技术手段可能招致反垄断诉讼(如Visa近期遭美国司法部起诉)。

五、相关科技动态概要

  • 微软计划在Build大会推出新AI模型,以减少对OpenAI技术的依赖,试图重振在AI编码工具领域(如GitHub Copilot)的竞争优势。
  • 特斯拉自动驾驶技术被前员工质疑存在安全数据美化、过度依赖人力标注等问题,其Robotaxi业务规模远低于预期。
13. Sub-pixel distance transform (2023) (acko.net)

本文探讨了在生成有符号距离场(SDF)时,传统欧几里得距离变换(EDT)在亚像素精度方面的缺陷,并提出了一种改进的亚像素欧几里得距离变换(ESDT)算法。

核心问题与EDT的局限性 传统EDT算法基于二值掩码计算距离,但在处理抗锯齿的灰度边缘像素时存在问题。直接将灰度值减0.5作为初始有符号距离会导致错误,因为它在二维空间中引入了额外的维度(z²),破坏了距离的准确性。此外,将灰度像素同时视为内部和外部会导致正距离场(P)和负距离场(N)在边缘产生不正确的重叠和形状。

ESDT算法设计 ESDT旨在解决这些问题,生成亚像素精确的距离场:

  1. 亚像素偏移量计算:对于每个灰度像素,通过分析其3x3邻域来拟合平面,估算指向真实边缘的梯度方向,从而确定亚像素偏移量。对于纯黑白边缘,则视为偏移量为0.5的灰度。
  2. P和N字段的处理:关键创新在于正确处理灰度像素的归属。通过将灰度像素中心在P和N字段中分别向相反方向扩展半像素(加上计算的偏移量),然后通过SDF = max(0, P - 0.5) - max(0, N - 0.5)合并,确保了P和N字段的平滑衔接和正确的45度斜率。
  3. 改进的传播机制:算法在X和Y方向的传播过程中,不仅记录距离,还传播每个像素的亚像素偏移量(Δx, Δy),最终计算平方距离为Δx² + Δy²。这比仅用距离平方传播更精确。
  4. 后处理修正:为解决可交换性(先X后Y与先Y后X结果不同)导致的对角线误差,增加了一个松弛步骤,检查每个像素的目标是否可由其带偏移量的直接邻居更好地近似,从而修正对角线区域。

实际应用与渲染

  1. Emoji支持:ESDT可直接应用于Emoji的透明度掩码来生成SDF。为处理透明区域的颜色混合问题,算法利用计算出的偏移量向外传播颜色,填充背景,避免缩放时产生光晕。
  2. SDF渲染
    • 字形栅格化后被打包到纹理图集中。
    • 渲染时使用屏幕空间导数计算SDF像素与屏幕像素的比率,以动态调整对比度。
    • 采用以75%灰度为零点的对比度调整,为膨胀操作分配更多空间。
    • 引入了类似油墨渗透的视觉效果(bleed),在较小字号时效果更明显,增强了文本的视觉重量和一致性。
    • 使用线性RGB进行伽马校正混合,显著提升了小字号和低DPI屏幕上的文本可读性。

总结 ESDT通过精确计算亚像素偏移并改进距离场的合并方式,克服了传统EDT在边缘精度和对角线处理上的缺陷。这使得即使从较低分辨率的输入(如Emoji PNG)也能生成高质量、支持平滑缩放的SDF,实现了亚像素精确的抗锯齿渲染、轮廓膨胀以及稳定的视觉效果。

14. A Tour of WebAuthn (www.imperialviolet.org)

《WebAuthn 导览》摘要

本文系统介绍了WebAuthn认证技术,旨在取代传统密码,提供更安全、抗钓鱼的强认证方案。

1. 核心问题与公钥签名方案

  • 密码的弊端:存在重用、泄露(数据库被拖库)、钓鱼攻击、无意间记录等风险。
  • 解决方案:采用公钥签名方案(如ECDSA、RSA)。其核心操作包括:生成密钥对、用私钥签名、用公钥验证签名。
  • 基础设计:用户注册时在设备上生成私钥(安全存储)并将公钥发送至服务器。登录时,设备用私钥对消息签名,服务器用公钥验证。这解决了数据库泄露问题(公钥无法反推私钥)。
  • 关键增强
    • 防钓鱼:签名消息中包含来源(origin)信息,防止签名被转发给其他网站。
    • 防重放:签名消息包含服务器生成的随机挑战(challenge),使每次签名唯一。
    • 私钥存储:为最大化安全,私钥生成并存储在专用硬件中(如安全密钥)。

2. U2F(通用第二因素)

  • U2F是FIDO联盟制定的首个具体标准,作为密码的第二因素使用。
  • 核心是CTAP1协议,用于计算机与安全密钥间的通信,定义了生成凭证(generate)和签名(sign)两个命令。
  • 引入了依赖方标识(RP ID),用于限制凭证仅在特定网站使用,增强了隐私和安全。
  • 要求用户存在(物理触摸设备)以授权操作,阻止恶意软件后台滥用。
  • 证明(Attestation) 机制允许验证安全密钥的型号和真伪。

3. FIDO2、Passkeys与WebAuthn

  • FIDO2 包含CTAP2协议WebAuthn API,是U2F的演进。
  • 核心新概念
    • 可发现凭证:安全密钥或平台可以存储凭证及关联的用户标识(非用户名),允许在不提供凭证ID的情况下发起登录。
    • 用户验证:比“用户存在”更强,要求验证正确用户(如通过PIN、生物识别),可替代密码。
    • 平台认证器:利用设备内置的安全硬件(如手机指纹传感器、电脑TPM),无需外接安全密钥。
  • Passkeys:是同步的、可发现的WebAuthn凭证,旨在普及WebAuthn。它们通过云服务(如iCloud钥匙串、Google密码管理器)在设备间同步,解决了凭证丢失问题。

4. WebAuthn API核心流程

  • 创建凭证(注册)
    • 网站通过navigator.credentials.create发起请求,指定依赖方信息、用户信息、公钥参数、认证器选择策略等。
    • 响应包含凭证ID公钥(SPKI格式),服务器需存储。
  • 获取签名(登录)
    • 网站通过navigator.credentials.get发起请求,提供挑战值和可能的允许凭证列表。
    • 响应包含签名认证器数据客户端数据。服务器需验证签名,并检查挑战值、来源等上下文。

5. 依赖方标识(RP ID)与实现

  • RP ID 通常是域名,用于限定凭证的使用范围,防止跨站使用。网站可声明其控制的RP ID。
  • 移动端集成:Android和Apple平台通过特定机制(如assetlinks.json、关联域名)验证应用与RP ID的绑定关系。

6. 扩展功能

WebAuthn通过扩展支持额外功能:

  • credProps:报告凭证是否为可发现凭证。
  • PRF:允许基于凭证派生伪随机输出,用于派生加密密钥。
  • credProtect:设置凭证在安全密钥上的隐私保护级别。
  • minPinLength:获取设备要求的最短PIN长度。
  • largeBlob:允许在凭证中存储较大数据块(如证书)。

7. 混合传输

允许将手机用作认证器,通过扫描QR码与电脑配对。通过蓝牙广播建立近场连接,再通过互联网隧道传输CTAP2消息,兼顾安全(近场验证)与便捷。

8. 平台特定API

  • Apple平台:使用AuthenticationServices框架,分为处理本地/同步凭证和安全密钥的两类API。
  • Android:使用androidx.credentials库,采用JSON格式的WebAuthn请求和响应,与Web API兼容。
  • Web特性:包括条件UI(在登录框自动建议Passkey)、跨域iframe支持、JSON序列化辅助函数等。

9. 服务器端实现要点

  • 存储:为每个用户存储多个Passkey的凭证ID、公钥、备份状态等信息。
  • 验证签名时,需构造正确的签名数据(认证器数据+客户端数据哈希),并验证公钥。
  • 严格检查客户端数据(类型、挑战、来源)和认证器数据(RP ID哈希、用户存在标志)。

10. 公钥格式

  • X9.62格式:原始ECDSA公钥坐标。
  • SPKI格式:包装了算法标识的公钥,是WebAuthn getPublicKey()返回的标准格式。
  • COSE格式:用于认证器数据内部,是CBOR编码的公钥。

总结

WebAuthn通过公钥密码学、硬件安全认证器和可发现的Passkeys,构建了一个抗钓鱼、防数据泄露、用户体验良好的强认证体系。Passkeys的同步特性是其走向大规模应用的关键。WebAuthn已成为现代身份验证的核心标准。

15. The CAP theorem of Clustering: Why Every Algorithm Must Sacrifice Something (blog.codingconfessions.com)

聚类算法的CAP定理:为何每个算法都必须牺牲某项属性

核心定理

2002年,Jon Kleinberg在数学上证明了一个与分布式系统CAP定理类似的原理:不存在任何聚类算法能同时满足以下三个理想属性。这迫使我们在设计和选择聚类算法时必须做出权衡。

聚类的三个理想属性

  1. 尺度不变性

    • 定义:如果数据点间的所有距离按同一因子缩放,聚类结果不应改变。
    • 意义:确保算法不受数据单位(如米/英尺)、归一化方式或特征缩放的影响。
    • 违反实例:对距离进行缩放后,某些原本可合并的簇变得无法合并。
  2. 丰富性

    • 定义:聚类算法应能产生数据点的所有可能分组方式。
    • 意义:允许根据数据内在结构灵活发现任意数量的簇(如2组、4组或10组)。
    • 违反实例:预设簇数k的算法(如k-means)无法生成k以外数量的簇,限制了可能性。
  3. 一致性

    • 定义:如果现有聚类合理,当使簇内点更相似、簇间点更不相似时,聚类结果应保持不变。
    • 意义:当数据相似性模式强化时,算法应保持聚类结构的稳定性。
    • 数学表述:对距离函数d进行Γ变换得到新函数d'(满足同簇点距离减小、异簇点距离增大),一致算法应输出相同的聚类Γ。

实际算法中的权衡体现

单链接层次聚类

  • 固定簇数k:牺牲丰富性(无法发现k以外数量的簇)
  • 固定距离阈值r:牺牲尺度不变性(缩放数据会改变可合并簇的判定)
  • 基于最大距离比例αρ停止:牺牲一致性(距离函数变化后,最大距离ρ改变导致聚类结果不同)

基于中心的聚类(如k-means、k-median)

  • 预设k值首先违反丰富性
  • 此外也违反一致性:即使强化簇内/簇间模式,算法仍可能输出完全不同的聚类结果

实际应用启示

  1. 承认根本限制:这不是算法实现缺陷,而是数学上的不可能性
  2. 根据场景选择牺牲
    • 需要处理不同尺度数据 → 可能牺牲丰富性
    • 需要灵活发现任意分组 → 可能牺牲尺度不变性
    • 需要结果稳定可靠 → 可能牺牲丰富性
  3. 设计系统时的考量:明确哪个属性对具体应用最重要,可容忍哪种权衡

结论

Kleinberg定理指出聚类算法的固有局限性,理解这一原理有助于工程师做出更明智的选择——不是寻找“完美算法”,而是为特定需求选择恰当的权衡方案。

16. The new science of controlling lucid dreams (www.scientificamerican.com)

文章总结:清醒梦控制的新科学

清醒梦(即睡眠中意识到自己在做梦的状态)可通过训练和实验室技术实现。做梦者通过眼球运动、皱眉或手部动作与清醒世界交流,甚至完成数学计算或回答是/否问题。研究表明,清醒梦具有实时双向沟通能力,为梦境工程学奠定了基础。

核心应用包括治疗噩梦与创伤后应激障碍(PTSD)。通过清醒梦训练,PTSD患者可重构噩梦内容、与梦中威胁角色互动,从而显著减轻症状。实验显示,清醒意识本身即可缓解噩梦,因做梦者意识到梦境无现实危险。

清醒梦能改善整体睡眠健康。失眠患者通过清醒梦训练减少焦虑和抑郁症状,提升睡眠质量。其机制可能与增强前额叶皮层(负责认知控制)与杏仁核(情绪处理)的连接有关,有助于情绪调节。

神经科学研究揭示了清醒梦的独特脑活动模式,尤其是前额叶皮层的激活。研究者正尝试通过经颅交流电刺激(tACS)等外部干预引导脑波模式,诱导清醒梦。高密度脑电图(EEG)技术有助于精准识别清醒梦的脑特征。

技术手段包括感官刺激(如闪光、声音、振动)、可穿戴设备(如EEG头带)和虚拟现实。例如,睡眠中播放声音可融入梦境并触发清醒意识;飞行模拟游戏能增加飞翔梦的频率并诱导清醒梦。实验室中,做梦者还可通过眼部运动拼写字母与外界交流。

梦境工程学的未来发展可能聚焦于可穿戴设备的大规模应用,帮助人们在家控制梦境、缓解噩梦、提升创造力甚至体验非凡梦境(如飞行)。艺术与科技结合的项目(如博物馆中的摇床与感官刺激装置)已展示出通过梦境引导创造独特体验的潜力。

关键历史节点包括1980年代通过眼球信号证实清醒梦的真实性,以及2019年麻省理工学院媒体实验室召开的首届梦境工程学研讨会。当前研究正加速推进清醒梦的科学理解与应用转化。

17. Write a Shell in C (2015) (brennan.io)

本文介绍了如何用C语言从头实现一个简单的Unix shell(命名为lsh),旨在帮助读者理解shell的基本工作原理并提升编程信心。文章涵盖了shell的核心生命周期、主循环设计、命令读取与解析、进程启动机制、内置命令实现以及完整代码的整合。

核心结构与流程

shell的生命周期分为三个阶段:

  1. 初始化:加载配置文件(本例省略)。
  2. 解释:循环读取并执行命令。
  3. 终止:清理资源并退出。

主函数main()调用lsh_loop()进入命令循环。该循环依次执行以下步骤:

  • 读取:通过lsh_read_line()从标准输入获取命令行,支持动态缓冲区扩展(初始大小1024字节,按需增长),也可使用标准库getline()简化实现。
  • 解析lsh_split_line()使用空白字符作为分隔符,将命令行分割为程序名称和参数数组,不支持引号或转义字符。
  • 执行lsh_execute()判断命令类型:若为内置命令则直接执行,否则调用lsh_launch()启动外部进程。

进程启动机制

Unix进程启动依赖两个关键系统调用:

  • fork():复制当前进程,创建父子进程。
  • execvp():在子进程中替换为新程序(通过环境变量PATH搜索程序路径)。 父进程使用waitpid()等待子进程结束,处理其退出状态或信号终止。

内置命令

部分命令需内置在shell中执行,主要包括:

  • cd:调用chdir()切换当前目录(影响shell自身及后续子进程)。
  • exit:返回0以终止命令循环。
  • help:列出所有内置命令。 通过函数指针数组和字符串数组映射命令名称与处理函数,便于扩展。

代码整合与编译

文章提供了完整的lsh实现代码,需包含特定头文件(如sys/wait.hunistd.h等),可通过gcc -o main main.c编译运行。作者强调了代码的局限性:

  • 仅支持空白分隔参数,无引号或转义处理。
  • 不支持管道、重定向、通配符等高级特性。
  • 内置命令较少。

作者鼓励读者在理解基础后自行扩展功能,并提醒学生不应抄袭该代码作为课程作业。

18. A Simple ELF (4zm.org)

文章总结:构建简单ELF可执行文件

背景与目标

本文探讨如何逐步简化一个Linux下的“Hello World”程序,移除标准库、安全特性和调试信息,以理解ELF文件的基本结构和执行流程。作者强调“简单”(缺乏复杂性)与“容易”(依赖技能)的区别。

初始复杂性分析

  • 初始程序:使用printf编译后,生成包含大量符号和节(如.text.rodata.dynamic等)的ELF文件。
  • 入口点:程序从_start(而非main)开始执行,_start由C运行时库(CRT)提供。
  • 依赖:程序依赖标准库(如libc)进行输出和初始化。

简化步骤

1. 移除标准库(-nostdlib

  • 通过自定义入口点(startup函数)和系统调用(syscall)实现输出和退出。
  • 使用内联汇编直接调用writeexit系统调用。
  • 结果:符号表和节数量减少,程序仅包含.text.eh_frame等少量节。

2. 移除位置无关可执行文件(PIE)

  • 使用-no-pie编译,使程序使用固定地址(如0x401000)。
  • 关闭栈保护(-fno-stack-protector)、控制流保护(-fcf-protection=none)等。
  • 结果:程序进一步简化,仅保留.text.comment节,地址为绝对地址。

3. 使用自定义链接器脚本

  • 创建链接器脚本(hello.ld)定义内存区域(如IRAMRAMROM)和节(使用emoji命名)。
  • 指定.text.data.bss.rodata节的存储位置。
  • 结果:程序内存布局完全可控,符号地址根据脚本分配(如0xC0DE0000)。

关键技术细节

  • 系统调用:使用syscall指令,通过寄存器传递参数(如rax=系统调用号,rdirsirdx传递参数)。
  • 内联汇编:使用GCC内联汇编调用系统调用,并注意volatile关键字防止优化。
  • 链接器脚本:允许自定义节名称、内存区域和入口点,实现精细控制。

最终结果

经过三步简化,程序从一个包含数十个符号和节的复杂ELF文件,变成一个仅包含必要部分(如自定义入口点、系统调用、简单数据节)的简单ELF文件。整个程序的反汇编代码可完全展示在一个屏幕上。

意义与扩展

  • 本文展示了Linux下ELF程序的基本组成和执行机制。
  • 通过剥离现代特性和库,深入理解底层原理。
  • 作者提供了示例代码仓库,并推荐了链接器脚本文档和进一步探索ELF的资源。
  • 更新提示:内联汇编示例需注意栈对齐问题,且不适用于生产环境。

总结

文章通过逐步简化“Hello World”程序,揭示了ELF文件的复杂性和简化方法。从依赖标准库到直接使用系统调用,再到自定义链接器脚本,每一步都减少了程序的复杂性,使其更易于理解。这体现了“简单即少复杂性”的编程理念,并为理解Linux底层执行机制提供了实用指导。

19. Building AI Products–Part I: Back-End Architecture (philcalcado.com)

构建AI产品:后端架构深度解析

本文是系列的第一篇,重点探讨构建可扩展、可靠的AI产品(特别是AI Agent)的后端架构设计。作者以自身从AI助手转向开发者平台的经历为基础,分享了关键的技术决策和架构演进过程。

核心架构组件

在生成式AI系统中,存在两种主要组件类型:

  1. 推理管线:确定性的操作序列,通过一个或多个AI模型转换输入以产生特定输出(例如,RAG管道)。
  2. Agent:有状态的自主软件实体,能够编排AI模型和工具来完成复杂任务,具备推理和自我调整能力。

从单体到Agent的架构演进

  • 初期阶段:产品始于简单的Slack机器人,仅使用独立的推理管线,手动连接结果。随着功能扩展,管线变得复杂且脆弱。
  • 转向多Agent系统:为解决复杂性,引入了多Agent架构。Agent的核心特征包括:半自主、专业化、反应式、记忆驱动、具备决策能力、能使用工具、目标导向
  • 关键认知:并非所有组件都需要是Agent。传统设计模式(用于连接器、用户管理等)仍然适用,因此架构采用分层模式。

Agent不是微服务

团队最初尝试将Agent实现为无状态微服务,但很快发现存在根本性矛盾:

  • 状态管理冲突:Agent需要维护跨交互的丰富上下文,与微服务的无状态本质冲突。
  • 非确定性行为:Agent本质上是状态无界的状态机,破坏了缓存、测试和调试的核心假设。
  • 其他问题:数据密集性、对外部API的重度依赖带来的不可靠性,以及复杂的实现和调试。

Agent更像面向对象中的对象

微服务不适用后,团队转向面向对象编程这一经典范式来抽象Agent。

  • 对齐OOP原则:Agent天然具备封装的状态(记忆)、暴露的方法(工具和决策能力)、并通过消息传递通信。
  • 演进为实体:Agent从无状态服务转变为具有独特身份和生命周期的实体。每个用户/组织拥有持久化的Agent实例,通过数据库的Repository管理。
  • 优势:简化了函数签名(无需传递大量上下文参数),能利用SQLAlchemy、Pydantic等成熟工具,并便于单元测试。

实现Agent记忆

Agent的记忆复杂度各异。团队采用了两种策略:

  1. 简单持久化:针对如“今日优先级”Agent,使用SQLAlchemy ORM在专用表中存储数据。
  2. 复杂记忆模型:针对如“组织架构维护”Agent,采用了CQRS(命令查询职责分离)与事件溯源
    • 原理:所有状态变更(如创建会议、更新成员)都记录为按时间顺序排列的事件(命令)。当前状态通过重播事件重建。
    • 优化:维护一个查询优化的、持续更新的物化视图(类似关系数据库的物化视图)以加速读取。
    • 事件路由:采用受SoundCloud启发的语义事件总线模型。所有状态变更事件发布到总线,Agent自行订阅并过滤不相关事件,避免了“上帝对象”路由器。

扩展至10,000用户

随着用户增长,系统面临性能挑战:

  • 初期策略:保持单体架构,依赖AWS ECS部署,利用FastAPI和asyncio处理负载。
  • 初步优化:当个性化报告生成变慢时,实施了基于组织的分片,为大账户提供专用资源,并为非活跃用户设置处理优先级。
  • 深度优化
    • 利用Python的异步特性,重构Agent与模型交互,分离CPU和IO密集型工作。
    • 为应对OpenAI速率限制,引入了令牌预算系统、指数退避、缓存和后备机制。
    • 将最重的计算移至非高峰时段。
    • 从OpenAI API迁移至Azure GPT部署,利用其每部署配额而非全组织配额,通过负载均衡进行扩展。

零、一、无穷大原则与系统分解

遵循“零、一、无穷大”规则,团队逐步将组件从单体中拆分:

  1. 提取GPT代理服务,专门处理与GPT的交互和配额管理。
  2. 提取数据集成服务,负责从用户连接的工具中拉取数据。为此,将事件总线实现为基于Postgres的发布/订阅系统。
  3. 尝试提取Agent和推理管线,但遇到了新的挑战。

Agent作为分布式对象与采用Temporal

  • 分布式对象的谨慎实践:在将Agent分布式部署时,团队遵循了分布式对象的教训,仅通过粗粒度API(使用数据传输对象DTO)进行远程交互,避免了细粒度操作的透明远程调用陷阱。
  • 引入工作流编排:当Agent需要引入回压和弹性模式时,团队发现需要更强大的编排能力。评估了Apache Airflow、AWS Lambda等方案后,最终选择了Temporal
    • 优势匹配:Temporal专为长时间运行、有状态的工作流设计,提供开箱即用的持久性和弹性。其核心抽象(工作流和活动)完美映射到面向对象的Agent模型(主逻辑作为工作流,工具/API调用作为活动)。
    • 实际采用:尽管Python SDK存在一些限制,但团队成功迁移。Temporal Cloud因其可靠性和成本效益成为核心依赖,并计划将其也应用于推理管线和其开发者平台Outropy。

总结

本文的核心教训在于:构建生产级AI产品需要超越快速原型演示的架构思考。关键在于理解AI系统(尤其是Agent)的独特性质(有状态、非确定性、数据密集),选择与之匹配的架构范式(如面向对象、事件溯源、CQRS),并在面临扩展性挑战时,采用合适的技术栈(如Asyncio、Temporal)来构建可靠、可演进的系统。

20. Execution units are often pipelined (blog.xoria.org)

执行单元通常流水线化,这意味着在乱序微架构中,执行单元可以在处理一个µop时接受新的µop。作者最初错误地认为执行单元会一直占用直到µop完成,但实际情况相反。

以Firestorm微架构为例,它有两个可执行乘法的整数执行单元,每个乘法需3周期完成。对于依赖指令序列(如连续乘法),总执行时间取决于依赖关系,例如4个依赖乘法需12周期。但对于独立指令序列,作者原以为需6周期(两个执行单元各处理两个乘法,每个乘法3周期),实际由于流水线化,仅需4周期:每个周期每个执行单元可发出新µop,实现更高的吞吐量。

流水线化允许执行单元重叠处理多个µop。在极限情况下,两个执行单元持续供µop时,原预测吞吐量为1.5 cycles/instruction,实际可达0.5 cycles/instruction,因为每个执行单元每周期可处理一个乘法µop,两个单元并行工作。

这解释了指令延迟和带宽表中指定倒数吞吐量的原因,它等同于cycles/instruction指标。作者提供了GitHub仓库供验证,需调整CPU频率设置。

21. Show HN: I send myself automated emails to practice Dutch (github.com)

项目概述

该项目通过自动化每天发送包含三个单词的电子邮件,帮助用户练习语言词汇(如荷兰语),包括单词、翻译和例句。作者创建此项目是因为在寻找合适的C1级荷兰语词汇应用未果,发现ChatGPT能提供高质量单词建议,并通过电子邮件检查更一致来增强学习效果。项目不替代正式语言学习,但有助于保持语言接触。

架构与功能

项目使用AWS服务构建简化架构:

  • 触发机制:AWS CloudWatch Event Rule每天触发Lambda函数。
  • Lambda函数:从DynamoDB数据库检索已发送单词,调用ChatGPT获取三个新单词(支持自定义语言和难度),将新单词存储回DynamoDB。
  • 电子邮件发送:通过Amazon SES将单词、翻译和例句发送到用户邮箱。
  • 数据存储:DynamoDB存储单词历史,避免重复发送。 关键功能包括:自动生成词汇、多语言支持(如荷兰语、法语)、翻译选项(如英语、德语),以及基于ChatGPT的内容质量依赖其语言知识。

设置与部署

部署前需准备:

  • 工具:Python 3.12.8、pip 24.3.1、Terraform 1.10.3、AWS CLI 2.15.58。
  • 权限:AWS CLI用户需具备足够权限以部署资源,遵循最小权限原则。
  • Amazon SES:需要验证一个电子邮件地址,与项目中使用地址匹配。
  • 可选:如修改代码,需使用setup.sh脚本重新打包Lambda部署包。 部署步骤:
  1. 复制terraform.tfvars.example为terraform.tfvars并填写配置值。
  2. 在variables.py中填写必要值。
  3. 运行Terraform命令:terraform initterraform planterraform apply

考虑因素

  • 项目旨在辅助语言学习,不替代课程或专用应用。
  • 作者偏好使用AWS和Terraform等标准行业服务,确保广泛支持和可靠性。
22. Write Your Own Virtual Machine (2022) (www.jmeiners.com)

编写你自己的虚拟机 (2022) 总结

本文介绍如何用 C 语言编写一个约250行的虚拟机,用于运行LC-3汇编程序。

什么是虚拟机?

虚拟机(VM)是模拟计算机硬件的程序,能执行机器语言。它可以重现特定硬件(如游戏机模拟器),或创建可移植的软件平台(如JVM)。VM在安全隔离执行(如垃圾回收、区块链智能合约)和提供可移植性方面有重要作用。

LC-3 架构

我们的虚拟机模拟教学用的LC-3计算机架构,包含以下核心组件:

  • 内存:65,536个16位存储位置(128KB)。
  • 寄存器:10个16位寄存器,包括8个通用寄存器(R0-R7)、程序计数器(PC)和条件标志寄存器(COND)。
  • 指令集:16种操作码,包括加法(ADD)、加载(LD)、存储(ST)等基本操作。
  • 条件标志:正(P)、零(Z)、负(N)三种标志,用于记录计算结果状态。

执行程序流程

虚拟机的主循环遵循“取指-解码-执行”步骤:

  1. 从PC指向的地址读取指令。
  2. 递增PC。
  3. 根据操作码(指令高4位)执行对应操作。
  4. 使用指令中的参数完成计算或内存访问。
  5. 返回步骤1。

指令执行涉及立即数符号扩展、条件标志更新等细节。

实现关键指令

ADDLDI为例:

  • ADD:支持寄存器模式和立即数模式,将两个数相加并存入目标寄存器,最后更新条件标志。
  • LDI:间接加载指令,通过两级地址访问将内存中的值加载到寄存器。

其他指令(如AND、NOT、BR、JMP等)实现方式类似,遵循LC-3规范。

陷阱例程

陷阱例程提供基本I/O功能,通过TRAP指令调用:

  • GETC/OUT/IN:字符输入输出。
  • PUTS/PUTSP:字符串输出。
  • HALT:停止程序。

在虚拟机中,这些例程用C函数实现以提高效率和可移植性。

加载程序

程序文件包含起始地址(原点)和指令数据。加载时需处理字节序转换(大端转小端)。通过读取文件内容并复制到内存指定位置完成加载。

内存映射寄存器

LC-3通过内存映射地址访问键盘状态寄存器(KBSR)和键盘数据寄存器(KBDR),实现非阻塞输入检测。

平台特定处理

为实现终端输入,需要调整缓冲设置。不同操作系统(Unix/Windows)需使用对应API,程序中断时恢复原始设置。

运行与调试

编译后运行虚拟机,加载LC-3程序(如2048游戏)即可执行。调试时建议对照汇编源码单步执行,检查指令行为是否符合预期。

可选优化(C++)

文章提供C++模板元编程技巧,通过位标志组合处理步骤,减少代码重复,更接近硬件实现方式。

资源

最终代码约250行C代码,支持Unix和Windows。教程以“文学编程”形式组织,代码与讲解交织。社区贡献包括多语言实现和参考卡片。

通过本教程,读者可深入理解计算机底层运作和虚拟机原理,无需预先掌握汇编知识,只需熟悉基础C语言和二进制运算即可。

23. Show HN: Instantly visualize any codebase as an interactive diagram (gitdiagram.com)

代码库可视化工具

该工具是一个在Hacker News上展示的项目,能够将任何GitHub仓库即时转换为交互式图表,以便进行可视化分析。

主要功能

  • 即时可视化:支持将GitHub代码库快速转换为交互式图表,帮助开发者直观理解代码结构和项目架构。
  • 便捷操作:用户可以通过简单修改GitHub URL,将其中的hub替换为diagram来直接使用该工具,无需额外安装或复杂配置。

使用方式

  • 替换URL示例:对于任何GitHub仓库链接,如https://github.com/user/repo,将其改为https://github-diagram.com/user/repo即可生成交互式图表。
  • 目的:简化代码库的可视化过程,便于团队协作、项目文档或代码审查。

优势

  • 易用性:基于URL操作,降低使用门槛,适合各类开发者。
  • 交互性:生成的图表支持交互,允许用户探索代码细节和关系。

该工具旨在提升代码理解的效率,适用于软件开发和项目管理场景。

24. The paper passport's days are numbered (www.wired.com)

随着人脸识别技术与智能手机的普及,纸质护照正逐步被数字化的旅行凭证取代。目前全球多个国家已开始测试“无护照通关”系统,目标是让旅客在国际飞行中无需出示护照即可完成身份核验。

技术原理与进展
各国试验的系统大多基于“数字旅行凭证”技术。该技术由国际民航组织推动,将传统护照芯片中的面部数据等信息存储于手机应用,并通过加密方式与虚拟凭证关联。机场通过人脸识别摄像头匹配手机中的护照照片,实现快速验证。芬兰的试点显示,此类检查仅需八秒即可完成。

全球应用现状
芬兰、加拿大、新加坡、英国等多国机场已开展不同程度的免护照旅行试验。新加坡自2023年10月起允许本国居民及外国旅客无需护照即可出入境,已有超150万人使用该系统。欧盟也在开发官方旅行应用程序,整合数字证件功能。

推动因素与潜在风险
新冠疫情加速了无接触旅行的发展,各国政府与航空业希望通过减少流程摩擦来提升旅客通行效率。然而,隐私专家对相关技术的透明度提出担忧,认为数据可能面临泄露风险,且广泛的人脸识别应用可能加剧监控体系的扩张。

尽管目前大多数数字旅行凭证仍需旅客携带纸质护照作为备用,但技术发展可能在未来彻底消除对实体护照的依赖。研究人员指出,数字护照有望成为主流旅行方式,但其大规模应用仍需平衡效率、安全与隐私保护之间的关系。

25. Coding Font Selection 'Tournament' (daringfireball.net)

文章核心概述
本文介绍了一款由Typogram推出的编程字体选择“锦标赛”工具,旨在帮助用户从32种免费等宽字体中通过对比淘汰的方式选出个人偏好的编程字体。作者基于Jason Snell的分享及自身体验,总结了该工具的特点、局限与改进。

工具特点与局限

  • 形式:用户通过多轮对比在字体中做出选择,最终决出“冠军”。
  • 免费限制:仅包含免费字体,部分热门付费字体(如Consolas、Berkeley Mono、SF Mono)未被收录。
  • 质量参差:部分收录字体体验较差。
  • 测试基准:初始示例代码为CSS,后更新为JavaScript,更贴近编程场景需求。

优化与建议

  • 工具在短期内进行了改进,新增了更优的字体选项。
  • 建议使用时隐藏字体名称,以避免用户对现有字体的主观偏见影响选择。

作者体验

  • 作者多次测试后,结果一致倾向Source Code Pro(Adobe出品)为首选,IBM Plex Mono为次选。
  • 缺失字体:作者指出Intel One Mono未被收录。

信息来源
文章发布于2024年12月24日,内容基于Jason Snell于同年10月的分享及作者后续使用体验。

26. Ask HN: Is ChatGPT down?
29. Show HN: I've made a Monte-Carlo raytracer for glTF scenes in WebGPU (github.com)

项目概述

这是一个使用 WebGPU API 编写的 GPU 软件光线追踪器,用于渲染单个 glTF 格式的 3D 场景。它不依赖于硬件光追(如 RTX),而是通过手动计算光线与场景的交点实现。项目基于 MIT 许可证开源。

核心功能

  • 场景输入:接受单个 glTF 文件作为输入。
  • 材质支持:支持平面颜色以及带有 albedo(反照率)、normal(法线)和 material(材质)贴图的纹理材质。目前不支持折射
  • 重要技术:模型的 UV 必须是非退化的,因为即使没有法线贴图,也需要用它们来重建用于法线映射的切线。

技术实现细节

  1. 光线追踪:使用标准的蒙特卡洛积分配合多重重要性采样
  2. 加速结构:程序启动时,使用表面积启发式构建 BVH(层次包围体)来实现快速的光线与场景相交计算。
  3. 采样策略:在多个方向采样策略间应用多重重要性采样,包括:
    • 余弦加权采样(适用于漫反射材质)
    • 直接光采样(适用于粗糙材质)
    • VNDF 采样(适用于光滑材质)
    • 传输采样(适用于透明材质)
  4. 材质模型:使用标准 glTF Cook-Torrance GGX 模型,并实现了 KHR_materials_transmission 描述的薄壁传输效果。使用 VNDF 法线分布来改善收敛。
  5. 环境与灯光:支持 HDRI 环境贴图和固定颜色背景。可对发光三角形按面积和强度进行采样。
  6. 着色器:项目中实现了自定义的着色器导入机制。

用户交互

  • 运行:构建后,通过命令行传入 glTF 文件路径运行,例如 ./webgpu-raytracer path/to/scene.gltf。可选第二个参数设置背景颜色或环境贴图。
  • 控制
    • 移动视角:WASD/ZX移动,QE滚动,鼠标左键拖动旋转。
    • 切换模式:按空格键在简单预览和完整光线追踪模式间切换。
    • 曝光调节:上下箭头键调整曝光。
    • 注意:在光追模式下移动相机会丢弃当前追踪结果,自动返回预览模式。

构建与依赖

  • 构建系统:CMake。
  • 主要依赖
    • SDL2(用于窗口管理)。
    • wgpu-native(WebGPU 的一个实现,建议使用 v0.19.4.1 版本)。
  • 子模块
    • glm:用于向量与矩阵数学。
    • rapidjson:用于解析 glTF 场景。
    • stb:用于加载图像。
    • MikkTSpace:用于重建网格切线(法线映射所需)。
  • 可重用组件
    • sdl2_wgpu:一组可在项目中复用的文件,用于从 SDL2 窗口创建 WebGPU 表面。
    • Findwgpu-native.cmake:一个 CMake 查找脚本,方便其他项目集成 wgpu-native。

待办事项

项目列出了一些未来可能(但不保证)实现的功能:

  • 已完成:支持环境图、基于面积和强度的发光三角形采样、albedo/material/normal 贴图支持。
  • 计划中:基于强度的环境图像素采样、实现折射与 VNDF 结合、测试不同 BVH 变体的性能、实现波前路径追踪、支持 GLB 输入格式。
30. Homebrew Batteries (www.hanssummers.com)

自制电池实验总结

本文详细记录了作者为给40米QRSS发射器供电,探索使用天然材料制作电池的系列实验,旨在评估不同电解质和电极组合的电压、电流、功率及持久性。

1. 柠檬电池的尝试与局限

作者首先尝试经典的柠檬电池(使用铜线与钢螺栓),测得开路电压约0.5V,但带负载能力极差(10kΩ负载下仅输出0.3μW)。更换为镀锡罐头条作为电极后,功率提升至8.7μW,仍远低于网络声称的1mA电流。实验表明,柠檬电池功率低,难以直接驱动实用设备。

2. 改进设计:柠檬汁电池

为降低内阻,作者设计了柠檬汁电池,使用镀锡罐头做杯、铜线螺旋做电极,以厨房纸巾隔离。小型版本功率为17μW,大型多腔室版本(增大电极面积)功率提升至322μW,但长期放电功率约73μW。要为发射器供电,仍需约140个此类电池,实用性差。

3. 突破:漂白剂电解质电池

改用家用漂白剂后,性能显著提升。小型漂白剂电池开路电压达0.8V,功率约152μW,比柠檬汁版本高10倍。作者随后制作了大型实用电池:使用烘焙豆罐为容器,铜线缠绕于橙汁瓶作为正极,以漂白剂为电解质。单个电池在330Ω负载下输出1.4mW。将四个电池串联(总电压>3V),成功为QRSS发射器供电,输出约3-6mW射频功率,持续工作超过五天,并收到了业余无线电爱好者的接收报告。这是首个成功的实用原型。

4. 其他电解质试验

  • 盐水电池:电压较低,但电流能力尚可。
  • 醋电池(香醋):电压约为漂白剂的一半,但毒性低。
  • 他人建议:Anders Sandstrom使用醋酸与氢氧化钠混合电解质获得更高电压(>1V)和电流(>100mA),并实现可再充电。John Beech G8SEQ分享了使用铝罐/铜线与含氯漂白剂的经验,并指出碳棒作为正极可提升性能,一个电池可点亮LED两周。

5. 实验结论与电池衰减

漂白剂电池工作期间,罐体在空气-电解质界面处出现严重腐蚀,但铜线保持完好。电池容量估计约250mAh。所有实验数据以表格形式提供。

总结:本文通过系统实验,证明漂白剂作为电解质、镀锡罐头与铜线为电极的组合是自制电池中性能较优的方案,能够产生实用功率,为小型无线电设备短暂供电,但功率密度和寿命仍远低于商业电池。

31. Joco almost died at launch. Now, it's a lifeline for e-bike delivery riders (techcrunch.com)

Joco是一家面向外卖配送骑手的电动自行车共享初创公司,由两位同名创始人Jonathan Cohen于2021年在纽约创立。公司最初意图与Lyft旗下的Citi Bike竞争,但因未获授权运营共享服务而被纽约交通部起诉,被迫转向服务零工配送员这一细分市场。这一转折点迫使Joco专注于客户和运营效率,最终成为其存活和盈利的关键。

核心业务与模式:

  • 服务对象: 同时服务零工配送员(按日/周租赁电动自行车)和企业客户(提供专属车队)。
  • B2B服务: 为Grubhub、Reef、Fresh Direct等约18家企业客户提供车队管理技术、维护服务、停靠站和电池充电柜。
  • 电池充电柜: 针对纽约等地因不当充电引发的电池火灾问题,Joco推出了经消防部门批准的充电柜,已售出约100个,成为新的增长点。
  • 差异化优势: 与提供长期租赁的竞争对手不同,Joco提供车辆存取服务,骑手无需自行保管、上锁或充电,车辆使用率更高。

成功关键与客户关怀: Joco将生存归功于对客户服务的极致专注(“痴迷于客户”)。其措施包括:

  • 提供“礼宾服务站”,为骑手提供休息、充电、使用卫生间及获取物资的场所。
  • 创始人亲自提供紧急救援服务(如深夜修车),通过超预期服务建立忠诚度。
  • 免费提供安全头盔、反光背心等装备。
  • 这些服务虽不一定直接带来财务收益,但创造了强大的口碑和客户粘性,公司声称“在营销上花费为0”,增长主要依靠口碑。

财务与运营状况: Joco仅筹集了750万美元风险投资,但目前已成为“净盈利”公司,拥有真实薪资发放。其精打细算的运营体现在:

  • 保持精简的公司团队(约50名员工,核心团队约7人),部分岗位外包或雇佣兼职高管。
  • 计划依靠现金流和可能的债务进行扩张,而非进一步稀释股权的融资。

发展现状与未来规划:

  • 现状: 在纽约、芝加哥和迈阿密运营,拥有约50个停靠站,管理着约3000辆电动自行车,每日利用率极高。
  • 扩张: 计划到2025年底将零工车队扩大至1万辆,在布鲁克林和皇后区新建站点,并将电池充电柜业务扩大至1000个,同时增加四轮货运自行车品类。
  • 环境利好: 纽约即将实施的拥堵费政策可能带来更低的仓库租赁成本,有利于Joco基础设施的建设。

总之,Joco从监管挫折中转型,通过专注于服务外卖骑手的独特需求、提供全方位的运维支持和极具人情味的客户服务,建立了稳固的业务模型和增长路径,并计划在现金流支持下继续扩张。

32. Reverse Engineering the Stream Deck+ (den.dev)

Stream Deck+ 设备逆向工程总结

本文详细记录了作者对 Elgato Stream Deck+ 设备进行逆向工程的过程,旨在绕过官方软件限制,实现对设备的完全控制。作者基于对隐私的重视,开发了开源替代方案 DeckSurf。

设备特性与工具

Stream Deck+(售价179.99美元)包含以下硬件组件:

  • 8个可编程按钮:支持120x120像素JPEG图像,由主机动态更新。
  • 窄条触摸屏:800x100像素彩色屏幕,支持触摸输入。
  • 4个旋转旋钮:可无限旋转(左右)并按下(点击)。

逆向工程主要工具:

  • Wireshark(带USBPcap插件)用于USB流量抓包。
  • 虚拟机隔离设备,使用官方软件生成参考流量。

通信协议分析

1. 按钮功能

  • 图像设置:主机通过USB中断传输(URB_INTERRUPT out)向设备发送JPEG图像。数据包以8字节头开始,包含设备ID、分片标识、载荷长度等信息。图像通常被分割为多个1051字节的包。
  • 按钮输入:设备通过URB_INTERRUPT in向主机发送10字节状态映射。按下按钮时,映射表中对应位设为1;松开时设为0。

2. 屏幕显示

  • 屏幕可作为整体800x100图像更新,也可分段更新(每段200像素宽)。图像设置数据包有16字节头,包含分段偏移量、图像尺寸、分片信息等。
  • 触摸输入:触摸屏幕时,设备发送10字节数据包,其中第6-7字节为X坐标,第8-9字节为Y坐标。

3. 旋钮控制

旋钮数据包为10字节,结构如下:

  • 第4字节:01表示旋转,00表示按下/释放。
  • 第5-8字节:分别对应旋钮A、B、C、D的状态。旋转时,顺时针为01,逆时针为FF;按下时对应字节为01,释放时为00

工具与应用

作者开发了 DeckSurf SDK(版本0.0.4)作为开源替代方案。通过C#代码示例展示了如何:

  • 设备发现与连接。
  • 监听按钮、旋钮和触摸事件。
  • 设置屏幕和按钮图像。
  • 控制设备亮度。

该SDK已在NuGet上发布,文档可在 https://docs.deck.surf 获取。作者强调此项目仍处于早期预览阶段,但已能实现完整的设备控制功能,为不希望依赖官方软件或账户的用户提供了可行选择。

33. The semver trick (2019) (github.com)

The semver trick (2019) 总结

该文章介绍了在 Rust 库生态中应对破坏性更新(breaking change)的一种技术,称为 semver trick。其核心思想是:当一个库需要发布破坏性更新时,无需强制要求其下游依赖库立即进行协调升级,从而避免了大规模的依赖升级难题。

问题背景:依赖升级的困境

  • 历史案例:Rust 库生态曾经历过痛苦的升级事件,如 libc 从 0.1 到 0.2 的“libcpocalypse”以及 Serde 的多次预发布版本升级,这些都迫使整个生态进行协调升级。
  • 根本原因:许多 crate 在其公开 API 中使用了这些库暴露的类型(如 libc 中的 c_void)。根据语义化版本(SemVer)规则,当库发布破坏性更新(主版本号或 pre-1.0 的次版本号变更)时,其类型被视为不兼容。
  • 连锁反应:如果 crate A 依赖 crate B,而 crate B 的公开 API 使用了某个库的类型,那么 A 无法单独升级该库,必须等待 B 先升级并发布新主版本,然后 A 才能升级。对于长依赖链,这需要巨大的协调工作(如 Servo 项目曾协调升级 52 个库)。

Semver Trick 的解决方案

技巧的核心在于:让一个库的旧版本依赖并重新导出其新版本中的未改变 API

libc 库为例:

  1. 发布破坏性更新:修复 EVFILT_AIO 常量类型(从 i32 改为 u32),发布为 libc 0.3.0
  2. 发布旧系列的最终兼容版本:发布一个 libc 0.2.1 版本,在其 Cargo.toml 中声明对 libc 0.3 的依赖,并在代码中用 pub use libc::c_void; 重新导出 c_void 类型。
    • 效果:libc 0.2.1libc 0.3.0 中的 c_void同一个类型,解决了类型不兼容问题。
    • 好处:下游用户可以在自己的节奏下从 0.2.x 升级到 0.3.x,无需所有依赖库同步升级,避免了强制性的主版本号更新。

技巧的适用性与限制

  • 适用场景:当一个库需要破坏性地更改一个很少在公开 API 中使用的 API(如某个常量),而其广泛使用的 API(如某个核心类型)保持不变时,此技巧最有效。它也适用于在模块层级中移动类型。
  • 不适用场景
    • 向未密封(non-sealed)的广泛使用的 trait 添加新方法。
    • 提升其公开依赖(public dependency)的主版本(除非该依赖本身也使用了此技巧)。
    • 提升最低支持的 Rust 编译器(rustc)版本。

许可信息

文章提到,这种“依赖自身未来版本”的思想本身在 CC0 1.0 许可下开源,可不署名使用。文中的代码示例和文档则在 Apache-2.0 或 MIT 许可下双许可授权。

总结:Semver trick 通过允许旧版本库重新导出新版本库中未更改的类型,实现了类型的跨版本一致性,使得下游 crate 可以独立、渐进地升级,极大地缓解了因小范围破坏性变更导致的大规模协调升级问题。

34. My failed attempt at AGI on the Tokio Runtime (www.christo.sh)

这篇文章记录了作者尝试在Tokio异步运行时上构建通用人工智能(AGI)的一次失败尝试。作者自认非机器学习或神经科学专家,其核心动机是避开与大型机构在Transformer/深度学习路径上的直接竞争,转而探索一条“完全受生物学启发”的全新路径。

核心思路与模型 作者构建了一个受生物神经元启发的异步神经网络。神经元模型采用简化的“泄漏积分与触发”机制:接收到的突触前脉冲会增加膜电位;膜电位随时间自然衰减;当膜电位超过阈值时,神经元会发放脉冲,并进入一个绝对不应期。作者假设信息编码于神经元的发放时序(及其产生的发放频率)中,而非脉冲的具体强度。

实现方式

  • 神经元与大脑:每个神经元被实现为Tokio中的一个异步任务。它使用 broadcast::Sender 作为轴突来广播脉冲,使用 broadcast::Receiver 作为树突来接收来自其他神经元的信号。神经元内部循环处理输入流,实现膜电位的积分、衰减与触发逻辑。
  • 连接与DNA:神经元之间的突触连接由一个“DNA”结构定义,该结构包含一个邻接矩阵(连接矩阵)、输入/输出神经元的索引以及其他参数(如衰减常数、阈值)。作者参考了C. elegans线虫的神经系统,仅使用了512个神经元。
  • 游戏与有机体:为了测试网络,作者设计了一个类似“贪吃蛇”的简单游戏。一个“有机体”负责将游戏状态编码为信号输入给神经网络的输入神经元,并将输出神经元的脉冲解读为游戏动作。

训练方法 由于网络的异步、脉冲特性,作者无法使用基于梯度的反向传播算法,转而采用了遗传算法。具体过程是:初始化一组随机的DNA(即随机连接矩阵);让每个DNA发育成的“大脑”在游戏中运行并获取得分;选择得分最高的个体进行“繁殖”(通过交叉和变异产生新的DNA);重复这个过程。

失败原因与结论 实验未能取得有意义的进展。网络的最佳得分仅为3分,且此表现不稳定,会在下一轮进化中消失。作者将失败归因于两个主要问题:

  1. 性能与时间敏感性:大量脉冲信号的异步处理可能给Tokio运行时带来了沉重负担,而神经元的工作机制对时间精度敏感。
  2. 优化策略不匹配:通过随机分割连接矩阵并进行遗传操作来优化一个复杂的神经网络结构,这种粗粒度的搜索方式可能从根本上是无效的。

作者最终发现,他所尝试构建的系统实际上是一种早已存在(至少50年)的“脉冲神经网络”(SNN)。尽管此次尝试失败,作者表示将搁置项目,继续学习神经科学以寻找新的灵感。

36. Implementing SM-2 in Rust (borretti.me)

本文介绍了作者为理解间隔重复算法SM-2而使用Rust编写的简单实现,重点阐述了算法原理、作者对所用软件(Mochi)修改版的看法以及代码结构。

背景与动机

作者使用的Mochi软件采用SM-2算法的修改版,主要区别在于:

  1. 不根据表现调整容易因子(EF),以避免“Ease Hell”问题。
  2. 记忆失败时,复习间隔减半而非重置。 作者不理解对EF调整的改动,且对间隔减半的修改感到不满,因此决定实现标准SM-2算法以加深理解。

SM-2算法核心

算法旨在优化复习时间,基于卡片状态安排下次复习。卡片状态由两个变量表示:

  • 容易因子(EF):表示卡片难度的反面,取值范围[1.3, +∞],初始值为2.5。
  • 重复次数(n):卡片连续正确回忆的次数。

复习间隔(I) 根据重复次数计算,公式为:

  • I(0)=0, I(1)=1, I(2)=6
  • I(n) = I(n-1) × EF (当 n ≥ 3)

用户在复习后对回忆质量评级(0-5,0为完全忘记,5为完美回忆),系统据此更新卡片状态:

  • 若评级在0-2(忘记):重复次数重置为0(间隔重置)。
  • 若评级在3-5(记住):重复次数增加1。
  • EF更新:EF' = max(1.3, EF + f(q)),其中 f(q) = -0.8 + 0.28q - 0.02q²。只有完美回忆(q=5)才能提高EF,其他情况EF会下降或保持不变,这正是“Ease Hell”现象(EF易降难升)的原因。

Rust实现概述

代码定义了相关类型和结构体:

  • 标量类型:Repetitions (u32), Ease (f32), Interval (u32)。
  • 枚举 Quality:表示6种回忆质量评级,并包含判断是否“忘记”或需“重复”的方法。
  • 结构体 Item:存储卡片状态(nef)。
  • 核心方法:
    • interval():根据当前状态计算下次复习间隔。
    • review(q: Quality):根据质量评级更新卡片状态(调用辅助函数 npefp)。
  • 辅助函数:np 根据评级更新重复次数,efp 根据评级计算新EF值(受最小值1.3约束)。

修正说明

作者后续指出,Mochi当前版本实际采用更简单的算法(成功时乘以>1的倍数,失败时乘以[0,1]的系数),而非基于EF的SM-2算法。

37. When Zig Is Safer and Faster Than Rust (zackoverflow.dev)

文章标题:当Zig比Rust更安全和更快时

本文通过一个具体项目——为需要标记-清除垃圾回收的语言编写一个字节码解释器(虚拟机),对比了使用unsafe Rust和Zig的实现。作者发现,对于需要大量内存不安全操作的场景,Zig的实现不仅更易编写,而且更安全、性能更高。

unsafe Rust的挑战

  1. 规则复杂且隐蔽unsafe Rust需要遵守复杂的未定义行为规则,尤其是别名规则。即使使用原始指针,若将其转换为引用,也必须保证其生命周期内遵守引用规则,这极易违反且难以追踪。
  2. 工具支持有限:虽然Miri工具可检测未定义行为,但修复过程缓慢且困难,缺乏实时反馈(如LSP支持)。
  3. 代码可读性差:为了规避借用检查器,代码中大量使用原始指针,导致解引用语法丑陋(如(*ptr).field),无法使用切片等高级抽象,代码变得像“半Rust半C”的混合体。
  4. 心理负担重:开发者始终如履薄冰,担心引入难以察觉的未定义行为,破坏了Rust通常带来的编码乐趣。

Zig实现的优势

Zig从设计上就考虑了内存不安全操作,提供了以下关键特性:

  1. 显式分配策略:所有分配函数必须接受一个Allocator参数。作者轻松实现了垃圾收集器作为自定义分配器,跟踪内存分配并触发回收。这使得针对不同生命周期采用最优分配策略(如快速的线性 arena 分配)变得自然。
  2. 内存错误检测:内置的GeneralPurposeAllocator可在运行时检测释放后使用双重释放错误,并打印详细的堆栈跟踪信息,极大简化了调试。
  3. 默认非空指针与安全检查:Zig指针默认非空,需显式使用?语法允许空值,并默认启用空指针解引用检查,使更安全的选择成为默认行为。
  4. 优良的指针设计
    • 人体工程学:使用点操作符即可解引用,语法清晰。
    • 类型区分:区分单值指针(*T)、未知长度的数组指针([*]T)和切片(带长度,[]T,支持索引和边界检查)。
    • 转换便捷:不同类型指针间可轻松转换,便于根据需要选用安全或灵活的类型。

性能对比

对同一解释器实现的多项基准测试表明,Zig版本比Rust版本快1.56至1.76倍。作者推测主要原因是:在Rust中为满足Miri检查,在某些高频操作(如栈操作、指令获取)中被迫使用索引而非指针,导致了额外的算术运算开销;而Zig版本则自由地使用了更高效的指针操作。

结论

  • 当项目需要大量unsafe代码(如手动内存管理、垃圾回收器)时,unsafe Rust的复杂性和易错性会抵消其安全优势,使语言变得难以使用。
  • Zig 通过其语言设计(如显式分配器、改进的指针系统)和实用的调试工具,为内存不安全操作提供了更安全、更高效、更愉快的开发体验
  • 作者强调,这一权衡在Rust与Zig的对比中常被忽视,对于考虑性能关键型项目的开发者而言,Zig是一个值得考虑的选择。