2024-07-04

26 篇热帖

1. Twilio confirms data breach after hackers leak 33M Authy user phone numbers (www.securityweek.com)

Twilio 数据泄露事件总结

事件概述

Twilio 公司近日确认发生数据泄露事件,导致与其双因素身份验证应用 Authy 相关的 3300 万个用户电话号码 被泄露。知名黑客组织 ShinyHunters 在 6 月下旬通过重新上线的 BreachForums 论坛公布了这一数据。

泄露内容

  • 主要数据:3300 万个随机电话号码,均关联 Authy 用户账户。
  • 附加信息:账户 ID 及部分其他非个人身份数据。

Twilio 官方回应

  1. 漏洞原因:威胁行为者通过一个未验证的端点获取了 Authy 账户数据。
  2. 已采取措施
    • 已对端点进行安全加固,禁止未验证的请求。
    • 未发现黑客入侵公司系统或获取其他敏感信息的证据。
  3. 安全建议
    • 呼吁 Authy 用户及时安装最新的 Android 和 iOS 安全更新。
    • 提醒用户警惕可能利用泄露电话号码进行的钓鱼攻击和短信钓鱼(smishing)攻击,对收到的短信保持高度警觉。

背景与关联事件

Twilio 此前曾多次遭遇安全事件,包括:

  • 2022 年遭供应链攻击(Codecov 事件波及)。
  • 员工被欺诈手段窃取登录凭证导致系统被入侵。
  • 员工成为短信钓鱼和语音钓鱼(vishing)攻击的目标。

此次数据泄露再次凸显了第三方应用及通信服务面临的安全风险。用户需密切关注账户安全,并采取必要防护措施。

2. The Joy of Reading Books You Don't Understand (reactormag.com)

这篇文章探讨了阅读那些无法完全理解的书籍所带来的独特快乐。作者以自身经历为例,讲述了多年前读尼尔·斯蒂芬森的《巴洛克循环》系列时,因不熟悉历史细节而频繁查阅百科全书,结果这个过程本身与阅读小说一样充满乐趣,并由此开始寻求这种“未知之旅”。

作者指出,在当前的出版环境中,许多书籍倾向于追求“稳妥”和易于理解,但仍不断有充满挑战、令人困惑甚至怪异的佳作问世。他列举了艾拉亚·道恩·约翰逊、海伦·奥耶耶米、莫莉·麦吉等作家的作品,认为它们需要读者的耐心和信任,其世界构建和叙事方式可能超越常规,但正是这种特质使其珍贵。

文章的核心体验来自于阅读瓦杰拉·钱德拉塞卡的小说《Rakesfall》。作者坦言,由于文化背景差异,他无法完全理解书中涉及的《罗摩衍那》等文化元素。然而,他不仅不为此沮丧,反而欣然接受这种“不理解”,并享受于通过主动探索、反复阅读来拼凑故事脉络的过程。

作者倡导读者突破阅读舒适区,拥抱不确定性,给予那些看似怪异或难以理解的书籍一个机会。他认为,承认理解的局限性并沉浸于这种“未知”中,能带来发现新叙事结构、等待故事元素融合、以及在结尾也无法简单概括“主题”的纯粹喜悦。这种在不完全理解中徜徉的体验,本身就是一种深层次的阅读乐趣。

3. Jeffrey Snover and the Making of PowerShell (corecursive.com)

PowerShell 的诞生:杰弗里·斯诺弗在微软内部推动变革的故事

这篇文章讲述了 PowerShell 的创造过程,重点阐述了其创造者 杰弗里·斯诺弗 如何在微软内部克服巨大阻力,最终成功推出这款彻底改变 Windows 系统管理的工具。

背景与动机

  • 1999年,比尔·盖茨 认识到微软不理解企业数据中心市场,于是招募了外部专家杰弗里·斯诺弗。
  • 斯诺弗的目标是让基于Windows NT的系统在数据中心胜出,核心策略是 降低总拥有成本,特别是通过培养企业内部的专业管理员,取代昂贵的外部系统集成商。

核心挑战与理念冲突

  • 斯诺弗发现微软文化 崇尚GUI和鼠标操作,命令行被视为过时。高管甚至质疑:“你到底对Windows的哪部分感到困惑?”
  • 他最初尝试将Unix工具(如awk、grep)移植到Windows,但发现根本行不通。因为 Windows是基于API和结构化数据(如注册表、WMI),而非Unix的“一切皆文件”模型。
  • 微软团队倾向于为每个场景开发专用GUI产品,而斯诺弗坚信 Unix的“组合”模型:提供一套小型、可组合的命令行工具,让管理员能灵活应对各种独特问题。

技术突破与内部斗争

  1. 初代尝试(WMIC):团队利用Windows管理规范(WMI)开发了约70个命令行工具,但效率低下,成本高昂。
  2. 元数据驱动架构:斯诺弗提出关键创新——将命令定义为元数据,由一个通用引擎执行。这大幅降低了开发和测试成本,绕过了微软测试部门的瓶颈。尽管遭到反对,斯诺弗坚持推行。
  3. .NET 的机遇:当时比尔·盖茨强力推行“.NET”战略以创造“Windows 95时刻”。斯诺弗巧妙利用这一战略,决定将新Shell(最初叫Monad)构建在.NET之上,从而获得了微软内部对提供广泛API覆盖的支持。

艰难的上位之路

  • 项目团队规模很小,且斯诺弗为此 接受了降职,放弃了高管职位,全心投入这个他相信能改变世界的项目。
  • 他撰写了著名的 《Monad宣言》,清晰阐述了项目的价值主张、目标用户和竞争优势,以此凝聚团队并向其他产品部门“推销”协作。
  • 项目多次面临被取消的风险。斯诺弗通过 赢得关键客户(如Exchange团队)的支持,以及坚持符合Windows架构的所有严苛要求,最终使PowerShell(从Monad改名)被重新纳入Windows发行。

最终的成功与影响

  • PowerShell经历了四个版本的持续迭代才完全实现最初的愿景。
  • 创建了一个强大的管理员社区,使Windows管理员转变为“脚本工程师”,能够通过脚本自动化复杂任务,并分享技巧与工具。
  • 最深远的影响在于 它为微软的云计算之路奠定了基础。正如Office部门负责人所言:“没有PowerShell,我们就无法实现云计算。”脚本化管理使得大规模服务器配置、故障修复和自动化部署成为可能,直接助力了Azure的诞生。

总结

杰弗里·斯诺弗创建PowerShell的故事,是一个关于技术远见、组织内变革领导力和坚持不懈的典型案例。他面对根深蒂固的文化和反对,凭借清晰的“可行成功理论”、巧妙的策略利用(如.NET)、以及对长期目标的专注,最终交付了一款不仅变革了Windows管理,也影响了整个IT行业基础设施演进的基础性工具。

4. Beating NumPy matrix multiplication in 150 lines of C (salykova.github.io)

使用150行C代码实现超越NumPy的矩阵乘法

本文介绍了如何用约150行纯C代码(无汇编),利用现代处理器的AVX2和FMA3 SIMD指令,实现高性能的多线程FP32矩阵乘法。目标是使其能够在所有现代x86-64处理器上运行,并与OpenBLAS等现有BLAS库竞争。实现的关键在于精细的算法优化和硬件特性利用。

核心优化策略

  1. 内核优化:高性能矩阵乘法的核心是设计一个高效计算C矩阵子块的“内核”函数。通过将计算过程分解为一系列外积的累加(rank-1更新),并利用SIMD的FMA(乘加融合)指令并行处理,可以大幅提高计算密度。实验发现,对于测试的AMD CPU,一个16x6大小的内核性能最佳。
  2. 缓存分块:为了减少缓慢的主内存访问,算法对输入矩阵进行分块(Tiling),使其能够充分利用CPU的L1、L2和L3高速缓存。数据在缓存中被重复使用,有效降低了内存带宽压力。
  3. 数据打包:为了提高内核中数据访问的连续性和SIMD加载效率,将分块后的矩阵数据重新排列(打包)到连续的缓冲区中,并对边界情况进行零填充。
  4. 多线程并行:使用OpenMP对计算和打包操作进行并行化。并行化的循环选择需要保证足够的迭代次数以使所有线程忙碌,同时分块大小需与缓存容量匹配。

性能与基准测试

  • 测试环境:AMD Ryzen 7 9700X (8核),DDR5内存,GCC编译器,Ubuntu系统。为公平比较,OpenBLAS编译时禁用了AVX512指令。
  • 性能指标:使用FLOPS(每秒浮点运算次数)衡量,计算公式为(2 * M * N * K) / 执行时间
  • 理论峰值:基于Ryzen 7 9700X的FMA指令吞吐量和时钟频率,其单线程理论峰值约为150 GFLOPS,多线程理论峰值约为1203 GFLOPS。
  • 结果:该实现展示了强大的性能,在单线程和多线程场景下均表现优异。文中提供了与OpenBLAS在方阵上的性能对比图(具体数值见原文图表)。

关键实现细节

  • 边界处理:通过生成掩码并使用_mm256_maskstore_ps指令,内核能够处理矩阵维度不是内核大小整数倍的情况。
  • 缓存块参数:选择缓存分块大小(nckcmc)时,需考虑缓存容量(L3、L2、L1)和线程数量,通常较大的值能带来更好性能。
  • 并行化选择:并行化嵌套循环中的内层循环(如遍历缓存块内m_Rn_R子块的循环)通常能获得更好的负载均衡和性能。
  • 微优化:通过显式展开循环变量和使用向量指令计算掩码,进一步提升了内核性能。

局限性与说明

  • 架构支持:本实现使用AVX2和FMA3指令,旨在支持广泛的x86-64 CPU。在支持AVX-512的CPU上,专门针对该指令集优化的BLAS库可能更快。
  • 超参数调优:要达到峰值性能,需要根据具体硬件微调超参数,如线程数、内核大小(m_R, n_R)和缓存块大小(nc, kc, mc)。
  • 代码结构:完整代码(sgemm.c)包含了从朴素实现到最终并行优化的所有步骤,并提供了多个头文件(matmul_kernel.h, matmul_pad.h, matmul_cache.h, matmul_micro.h, matmul_parallel.h)对应不同优化阶段。
5. The saddest "Just Ship It" story ever (2020) (www.kitze.io)

文章以第一人称叙述了独立开发者Kitze因过度追求完美而延误发布的亲身经历,强调“Just Ship It”(立即发布)的重要性。

核心事件与教训:

  1. 延误起点:2018年元旦,作者开始开发一款应用,几天内完成MVP(最小可行产品),但不断添加功能、学习新技术(如React Native),一拖再拖。
  2. 拖延原因:作者总认为“再加一个功能就完美了”,反复纠结技术栈选择,最终在两年后放弃开发。
  3. 竞争对手出现:作者发现一家公司已推出功能更全面的同类应用,尽管该应用不完善(如移动端同步慢、有bug),但通过持续发布和迭代,吸引了用户并成长。
  4. 心理冲击:作者经历复杂情绪(欣喜于问题被解决、愤怒于错失机会),最终成为该应用的付费用户,意识到及时发布比完美更重要。
  5. 反思与总结:作者指出多数开发者都类似,呼吁放下对完美的执着,尽早发布产品并根据反馈迭代。
  6. 后续更新:2024年补充中,作者于2022年发布了自己的综合型生产力应用“Benji”,因其愿景无法被现有应用满足,强调社区和持续改进的价值。

关键启示

  • 完美主义是发布产品的最大障碍。
  • 用户可接受不完美的产品,但要求持续改进。
  • 市场不等人,竞争对手可能抢先一步。
  • 通过实际发布和用户反馈迭代,比独自追求完美更有效。
6. AI's $600B Question (www.sequoiacap.com)

AI的6000亿美元问题

文章核心指出,AI基础设施投资(以英伟达为代表)所隐含的收入预期,与AI生态系统(作为终端用户价值代理)的实际收入增长之间存在巨大鸿沟,这一差距已从2023年9月的约2000亿美元扩大至如今的约6000亿美元。

差距的量化方法

该分析通过一个两步乘法进行计算:

  1. 取英伟达的年化收入预测,乘以2倍,以反映AI数据中心的总拥有成本(GPU成本约占一半,其余包括电力、建筑、备用发电机等)。
  2. 再乘以2倍,以反映GPU终端用户(如从Azure、AWS或GCP购买算力的初创企业)需要实现50%的毛利率才能盈利。

差距扩大的主要原因(自2023年9月以来)

  • GPU供应紧张已缓解:从2023年底的极度短缺转变为目前相对容易获取。
  • GPU库存正在积压:大型云服务商(如微软)是英伟达收入的主要买家,它们正在以前所未有的水平进行资本支出,囤积硬件。
  • 收入仍高度集中于OpenAI:尽管OpenAI收入增至34亿美元,但除其之外,能为消费者提供显著价值的AI产品寥寥无几,与其他公司收入差距巨大。
  • “窟窿”计算值大幅增加:即使假设谷歌、微软等巨头及若干新公司能从AI中获得可观的新收入,需要填补的差距也从1250亿美元膨胀至约5000亿美元。
  • 新一代芯片(B100)即将推出:其性价比的显著提升预计将引发新一轮需求激增和供应紧张,并加速旧芯片的贬值。

与“铁路投资”的对比反驳

作者同意AI投资类似于建设铁路的长期愿景,但指出几个关键差异:

  1. 缺乏定价权:GPU算力正日益成为按小时计费的大宗商品,市场竞争激烈,难以形成垄断,价格很可能被压至边际成本。
  2. 投资浪费:投机性技术热潮中,资本大量损耗是常态,历史(如铁路时期)表明很多投资者会亏损。
  3. 快速贬值:遵循类似摩尔定律的芯片性能提升,意味着当下采购的H100等芯片的价值在3-4年后将大打折扣,与物理基础设施不同。

核心观点与展望

  • AI将创造巨大经济价值,为终端用户创造价值的公司建造者将获得回报。
  • 投机狂热是技术发展的一部分,保持清醒者有机会建立重要公司。
  • 主要风险对象是投资者,而非创始人或公司建造者,后者将从更低的计算成本和试验期的经验积累中受益。
  • 作者警告,需要警惕“快速致富”的妄想,并认识到前路漫长,会有起伏,但最终是值得的。
7. Finding near-duplicates with Jaccard similarity and MinHash (blog.nelhage.com)

使用Jaccard相似度和MinHash查找近似重复文档

问题背景

在处理大规模文档集合(如网页爬取数据)时,需要识别内容近似相同的文档。这些文档可能存在元数据差异或微小编辑。直接比较所有文档对的相似性计算复杂度为O(n²),随文档数量增长而不可行。

相似性度量:Jaccard相似度

  • 定义:通过比较两个有限集合来表征相似度,计算其交集大小与并集大小的比率。 [ J(A,B) = \frac{|A \cap B|}{|A \cup B|} ]
  • 性质:值域为[0,1],0表示无重叠,1表示完全相同。该定义不满足传递性,因此“近似相同”并非等价关系。
  • 应用前提:需先将文档转换为特征集合(如通过分词或N-gram生成)。

核心技术:MinHash近似

直接计算Jaccard相似度需遍历集合,开销大。MinHash通过采样技巧高效近似该值。

单哈希函数签名

  1. 为每个特征分配哈希值。
  2. 对于每个文档,取其特征中最小的哈希值作为签名。
  3. 对于两个文档,若它们的最小哈希值相等,则该事件发生的概率恰好等于它们的Jaccard相似度: [ P(a_{\text{min}} = b_{\text{min}}) = J(A,B) ]

多哈希函数签名

使用k个独立哈希函数,为每个文档生成一个k维签名向量(每个分量为对应哈希函数下的最小值)。

  • 相似度估计:通过统计签名向量中相等分量的比例来近似Jaccard相似度: [ J(A,B) \approx \frac{1}{k} \sum_{i=1}^{k} \mathbf{1}{A{\text{sig}}[i] = B_{\text{sig}}[i]} ]
  • 要求:哈希函数需具备min-wise独立性,以保证随机性。

规模化检测近似重复

目标是在整个语料库中高效找到相似文档对,避免全对比较。

基于完整签名的分桶

  • 方法:使用文档的全部k个MinHash值作为分组键,将键相同的文档归入同一桶。
  • 特点:简单高效,易于分布式实现(如MapReduce中的shuffle)。所有k个哈希值均匹配的概率为 (J^k),因此主要检测极高相似度(如J>0.9)的文档。

检测更低相似度的文档

通过调整参数扩展检测范围:

  1. 减少分组键使用的哈希数:例如仅使用前r个哈希值分组(r < k),提高低相似度文档的碰撞概率。
  2. 多次分组:生成多个分组键(每键使用不同的哈希子集),文档可被放入多个桶中。
    • 碰撞概率:( p = 1 - (1 - J^r)^b ),其中b为分组次数。
    • 调整r和b可控制灵敏度与召回率,在相似度约0.7时即可获得50%的检测概率。

文档到集合的转换

在应用MinHash前,需将文档转换为特征集合:

  • 标准化:如Unicode归一化、大小写折叠、空白字符合并。
  • N-gram(或称“shingle”):将文档表示为所有连续n个单元的集合。n通常在5-9之间,n越小比较越粗糙,n越大特征集越大。
  • 分词(Tokenization):将文档切分为单词或标记,可结合N-gram(对token使用较小的n)。

算法关联与思考

MinHash与HyperLogLog在原理上相似:均通过哈希和极值(最小值/最大前导零)来压缩信息。两者可视为“对偶”:HyperLogLog估算并集大小,MinHash估算交集相对大小。结合二者可构建能查询交集与并集信息的紧凑数据结构。

该方法是实际中广泛使用的近似去重技术(如GPT-3数据集准备中提及),能高效处理大规模文档集合。

8. Show HN: Xcapture-BPF – like Linux top, but with Xray vision (0x.tools)

0x.tools:一套用于 Linux 性能分析的开源工具集

核心概述

0x.tools 是一套专注于 Linux 应用程序性能分析的开源实用程序。其核心设计理念是部署极简、依赖极少,旨在降低系统性问题排查的摩擦。工具集无需安装内核模块或重量级监控框架,即可测量线程级别的活动,包括执行的代码、睡眠状态、系统调用和等待位置。

核心工具详解

1. xcapture:性能数据采集器

xcapture 是该工具集的数据采集核心,其设计目标是超低开销、始终在线。它通过跟踪和采样合适的事件来提供系统可见性。目前存在三个版本:

  • xcapture v1:读取 /proc 文件系统,兼容性极佳,支持 Linux 内核 2.6 及以上版本(包括老旧企业环境)。
  • xcapture-bpf v2:基于 eBPF 和 BCC 的旧原型。
  • xcapture v3(alpha):最新版本,使用 libbpf 和现代 eBPF 特性,是未来发展的方向。

核心功能

  • 实时监控:默认每秒采样处于运行(R)和不可中断睡眠(D)状态的线程。
  • 持续归档:可将采样数据以小时为单位写入 CSV 文件,支持历史回溯分析。
  • 低开销:设计开销极低(通常低于 1% CPU),适用于生产环境。

2. xtop:具有“X光视觉”的增强版 top

xtop 是 Linux top 命令的增强版,被称为“用于挂钟时间的 top”。它利用 eBPF 的可编程能力,提供多维度的性能分析视角。

  • 透视能力:可进行从系统概览到单个线程活动,甚至内核事件(如锁等待、内存停顿)的深度钻取。
  • 状态:当前功能仅实现了其潜力的一小部分,但已能展示其强大的可定制和可编程性。

3. 其他实用工具

工具集还包含一系列辅助工具,它们主要通过读取 /proc 文件实现,无需 eBPF:

  • psn (Linux Process Snapper):用于实时故障排查的 Python 脚本,能报告更多 /proc 字段(如 IO 系统调用的文件名)。
  • schedlat:显示单个进程的 CPU 调度延迟占其运行时间的百分比。
  • syscallargs / tracepointargs:列出系统调用或跟踪点的参数、数据类型。
  • lsds:汇总列出所有 Linux 块设备及其设置。

使用场景与优势

该工具集适用于两类场景:

  1. 实时交互式分析:排查当前正在发生的系统问题。
  2. 持续低频剖析:用于生产系统的常开监控,捕获的连续数据允许用户在问题首次发生后或期间“回到过去”进行系统性排查。

关键优势

  • 部署简易:仅需编译安装,对系统环境要求低。
  • 生产安全:基于采样而非跟踪,开销极低且稳定,适合在关键业务系统中使用。
  • 聚焦底层原因:区别于高级分布式跟踪(如 Jaeger)或时间序列监控(如 Prometheus),0x.tools 专注于钻取系统活动、资源使用或内核行为异常的底层原因。

安装与使用

基本的安装流程为克隆 GitHub 仓库并编译安装。不同工具有各自的运行方式:

  • xcapture:直接运行,支持多种选项(如捕获所有状态、指定输出列、写入 CSV 目录)。
  • psn:需要 Python 环境,通过参数指定监控目标和分组。
  • schedlat:以 PID 为参数运行,持续输出 CPU 利用率、调度延迟和睡眠时间百分比。

未来计划

开发者计划进行打包与生产化改进,包括自动压缩归档、提供 RPM/DEB 包、内置数据可视化等功能。

9. Diffusion Forcing: Next-Token Prediction Meets Full-Sequence Diffusion (boyuan.space)

Diffusion Forcing:下一token预测与全序列扩散的结合

核心思想:Diffusion Forcing 是一种新的训练范式,其名称源于“Teacher Forcing”与“扩散模型”的结合。它旨在融合下一个token预测模型(如LLM)与全序列扩散模型(如SORA)各自的优势。通过一种“噪声即掩码”的技术,即在训练时为序列中的每个token分配独立的扩散噪声等级,使模型能够根据采样时设置的不同噪声水平,灵活地表现为其中一种模型或两者的混合。

技术原理

  • 统一视角:在扩散框架下,噪声等级可视为对token的掩码程度。全序列扩散以相同噪声等级同时去噪所有帧;下一个token预测则逐步去噪下一帧,且对过去token使用零噪声。
  • 训练方法:训练一个因果的序列扩散模型,但允许每个token具有独立的噪声水平。模型学习对一组token进行去噪,这些token的噪声等级各不相同。
  • 关键优势:结合了下一个token模型可变长度生成的能力,与全序列扩散模型通过引导实现序列级控制的能力。

主要能力与应用

  1. 稳定视频预测:在DMLab和Minecraft等数据集上,传统Teacher Forcing方法易崩溃,因果全序列扩散模型存在不一致问题。Diffusion Forcing能生成稳定、一致的视频序列,并可超越训练长度进行滚动生成(例如,训练36帧,可稳定生成2000帧以上),且无需滑动窗口重置。
  2. 扩散规划与决策:将每个token定义为[a_t, o_{t+1}],明确建模动作与观测的因果关系。在采样时,可通过对近期未来赋予低噪声(确定性高)、远期未来赋予高噪声(不确定性高)来进行规划,并能在获得新观测后更新信念。
  3. 长程模仿学习:应用于真实机器人任务(如交换水果位置),该任务具有非马尔可夫性,需要长期记忆。现有SOTA模仿学习方法无法完成,而Diffusion Forcing可以结合反馈控制实现成功执行,并对未见干扰具有鲁棒性。

理论保障:该方法被证明可以优化从真实联合分布中提取的所有token子序列的似然的变分下界。

未来研究方向(论文提及):

  • 条件化:将上下文token视为干净、未来token视为有噪声的更自然条件化方式。
  • 噪声即掩码的扩展:应用于MAE等自监督学习方法。
  • 组合性与灵活性:通过控制噪声水平,让模型自主决定何时忽略冗余历史。
  • 非因果版本:探索将训练好的非因果模型在采样时通过噪声掩码变为因果模型。
  • 替代引导方式:例如对学习到的奖励进行引导。
  • 不同噪声方案:探索针对任务特性优化的token间噪声等级关联方案。
  • 预测未来多token:在Transformer架构中效果良好,但在因果模型中可能因预测范围过大导致不一致。
  • 潜在空间与DiT架构:将方法应用于DiT架构,并在VAE潜在空间(更接近高斯分布)中使用,可能使稳定化方案更有效。
10. A practical introduction to constraint programming using CP-SAT and Python (pganalyze.com)

约束编程实践入门:基于CP-SAT与Python

核心概念

约束编程(CP)是一种用于解决离散优化问题的声明式编程范式。与命令式编程(逐步描述操作)不同,CP通过定义变量变量域(变量可取的值范围)和变量间的约束来描述问题的解,然后由求解器寻找满足所有约束的解。

简单示例:糖果购买

三人(Alice, Bob, Carol)各有20美元,需共同购买50美元的糖果。约束包括:

  • Alice出资 ≥ Bob
  • Carol出资为5的倍数
  • 各人出资不同 通过定义变量(每人出资额)及其域(0-20),并添加上述约束,求解器返回一个有效解。若添加目标(最小化最大出资额),可获得更公平的解(三人出资分别为18、17、15美元)。

实践案例:员工排班问题

使用Google的开源CP求解器CP-SAT(通过Python的ortools库)为小型商店制定每周排班表。

问题背景

  • 商店每天开放12小时(8AM-8PM),分为早、午、晚三个班次(每班4小时)。
  • 两种角色:收银员(必须每班次有1人)、补货员(每天仅需1人,但不能安排在连续两天的相邻班次,如周二晚班后不能安排周三早班)。
  • 员工资质不同(有人只能担任收银员或补货员,有人两者皆可)。
  • 附加约束:员工每天最多工作2班(8小时),且若上两班不能有空闲间隔(如不能同时上早班和晚班)。

建模步骤

  1. 定义变量:为每位员工、角色、日期、班次创建布尔变量schedule[员工][角色][日期][班次](1表示安排,0表示不安排)。
  2. 添加约束
    • 每班次有且仅有一名收银员。
    • 每天有且仅有一名补货员,且补货班次不能在相邻日的连续班次(如晚班后次日早班)。
    • 每人每天每个班次只能担任一种角色。
    • 根据员工资质,禁用其不胜任的角色。
    • 限制每人每天最多2班,且避免早班与晚班同日(防止空闲间隔)。
  3. 求解与验证:使用CP-SAT求解器,输出排班表并检查约束满足情况。

添加更多现实约束

  • 工时上限:每人每周最多10班(40小时)。
  • 特定员工需求:Phil每周固定上4班,且工作日白天不能上班;Emma要求周一至周五休息。
  • 公平性约束:周末班次平均分配(每人2班);Phil与Emma不能同班。
  • 优化目标:最小化Emma、David、Rebecca三人班次数量的最大差值,实现更公平的班次分配。

求解器状态

求解器可能返回以下状态:

  • OPTIMAL:找到最优解。
  • INFEASIBLE:问题无解(约束矛盾,如Emma全休导致无法排班)。
  • FEASIBLE:找到可行解但未证明最优。
  • UNKNOWN:求解器中断,未找到解也不确定是否有解。

总结

通过CP-SAT,可以直观地将现实约束转化为数学模型,并利用求解器高效生成满足所有要求的排班表。该方法适用于各类离散优化问题(如仓库选址、物流路线规划、航班调度),核心优势在于其声明式特性——只需描述“解应满足什么条件”,而非“如何找到解”。

(注:代码示例与完整排班表输出见原文GitHub仓库。下一篇文章将介绍如何将约束编程用于Postgres数据库索引选择。)

11. Analyzing my electricity consumption (zdimension.fr)

法国电费分析与优化

背景
法国电费近年来持续上涨,特别是自俄乌冲突以来涨幅明显。这促使作者分析自身电力消耗,并寻求优化方法。

硬件与数据获取

  • 智能电表:法国Enedis从2015年起推广Linky智能电表,取代传统电表。它可通过通信端口实时读取数据(如瞬时功率和总消耗),但作者主要依赖Enedis网站提供的每日消费数据(每30分钟一个切片)。
  • 消费数据:Enedis提供API,但访问限制严格。作者使用第三方包装API MyElectricalData 自动获取JSON格式数据。每个切片的值单位为“瓦特半小时”,需除以2转换为瓦时(Wh)以便定价计算。
  • 价格数据:从公共数据平台 data.gouv.fr 下载政府监管的电价(CSV格式)。电价由固定订阅费和可变消耗费组成,消耗费以€/kWh计算。

电价结构
法国电价计划分为三种:

  1. Base计划:全天统一电价。
  2. Peak Hours计划:分高峰时段(通常06:00-22:00)和非高峰时段(通常22:00-06:00),高峰电价较高。
  3. Tempo计划:结合时段和季节,将一年分为红(高价)、白(中价)、蓝(低价)日,每日再分高峰和非高峰时段。例如,2024年数据显示,红日高峰电价远高于其他计划,但蓝日非高峰电价极低。对使用燃气或木材供暖或居住在南部的用户,Tempo计划可能更经济。

应用开发与数据处理
作者用Python开发了一个web应用:

  • 数据获取:通过MyElectricalData API自动获取消费数据,每日夜间更新。
  • 数据存储:使用SQLite数据库,表结构包括消费表(存储每30分钟消耗值)和计划表(存储各计划的电价参数)。
  • 数据处理与显示:应用生成热图可视化消耗,并比较所有计划以识别最经济选项。用户可交互筛选数据。
  • 结果:作者使用Tempo计划,在过去十个月节省超过300欧元。即使在冬季红日较多的月份,蓝日和白日的低价仍能补偿红日的高成本。

结论

  • 工具推荐:NiceGUI适合快速构建Python web应用;SQLite便于存储结构化数据。
  • 开源工具:法国开源工具 comparateur-abonnements-electricite 可用于比较所有电价计划,Tempo计划通常最便宜。
  • 核心目标:通过自动化数据获取和分析,帮助用户优化电力消耗并选择最经济电价计划。
12. The Cheapest NAS (sigwait.org)

最廉价NAS的构建尝试

本文作者旨在用SBC(单板计算机)加硬盘组合,替换旧路由器改装的网络存储设备,以提升性能并支持Samba、Git、rsyncd和dnf仓库等服务。经过比较,选择了Libre Computer的AML-S805X-AC板,因其价格低廉且具备所需基本接口。

硬件选择与成本

作者选择的SBC具备四核ARM Cortex-A53处理器、1GB内存、百兆有线网口和USB 2.0接口。认为百兆网速对于同步约20万个小文件足够,因瓶颈不在带宽。额外购买了3.5英寸硬盘盒、3A电源和Micro-USB线,总成本约43欧元(不含硬盘)。

系统部署与问题

  1. 系统启动:通过U-Boot引导,显示内存为1GB。使用官方基于Debian 12的镜像,其分区结构为MBR格式,含EFI和Btrfs分区,首次启动时会自动扩展分区以占用剩余空间。
  2. 体验不佳:作者指出,官方镜像构建系统为私有,且首次扩展分区过程在USB设备上不稳定,导致速度缓慢甚至失败。
  3. 硬盘盒兼容性:硬盘盒使用JMS578芯片,引发内核错误(uas_eh_abort_handler)。需通过内核参数usb-storage.quirks=152d:0578:u禁用UAS模式才可解决延迟问题。

性能测试

禁用UAS后,USB 2.0模式下的硬盘写入速度测试结果约为23.95 MB/s,表现并不理想。

结论

作者不推荐此方案,主要因硬件兼容性问题多、性能提升有限。若非为严格控制功耗,选择更主流的微型ITX方案会更省心。整个构建过程突出了廉价SBC在稳定性和性能上的局限性。

13. Ask HN: Vision Pro owners, are you still using it?

本文档汇总了 Hacker News 用户关于 Apple Vision Pro 长期使用情况 的讨论。用户的评价呈现明显两极化,主要围绕媒体消费、工作效率、舒适度、软件生态和价格展开。

一、持续使用的用户(正面评价)

  • 核心用途:媒体与影视体验
    • 多数积极用户将其视为家庭影院的顶级替代品。他们认为,Vision Pro 提供了目前最佳的观影体验,尤其是播放 3D HDR 高帧率(HFR) 内容时,立体感和画质远超传统3D眼镜,被比作“宗教体验”。
    • 设备提供的沉浸式巨幕效果,显著提升了观影和追剧的吸引力。
  • 生产力与多任务处理
    • 许多用户将其用作 Mac 的扩展或镜像显示器,从而实现在沙发、床上等非传统位置舒适工作。
    • 多窗口多任务(如同时运行浏览器、文档和AI助手)被视为一种高效的工作模式。
    • 部分用户认为,透视和眼神感知功能让佩戴者能在使用设备的同时与家人互动,减轻了孤立感。
  • 使用频率与满意度
    • 活跃用户每周使用时间从10小时以上到不等,主要用于观影、浏览、写作和编码。
    • 他们认为尽管初始版本存在bug,但软件更新(如 VisionOS 2 的超宽屏模式、更低延迟的镜像)表明苹果正将其定位为生产力工具

二、减少使用或已放弃的用户(负面评价)

  • 舒适度与实用性质疑
    • 重量和佩戴舒适度是主要抱怨点,长时间佩戴会导致面部压迫感。
    • 视野限制和可能的视觉模糊感(尤其镜像Mac屏幕时)影响了部分用户的体验。
    • 对于飞行等移动场景,其实用性被一些用户否定。
  • 生态与功能限制
    • 原生应用匮乏是核心问题。用户指出缺乏像 Pages、Logic Pro 等苹果核心生产力应用,以及许多常用第三方应用的适配。
    • 与Mac的集成体验不佳曾是重大痛点(如无法用Mac键盘鼠标控制Vision Pro界面),虽后续更新有所改善,但仍存在连接繁琐等问题。
    • 有人认为它本质上是“可以绑在脸上的高级显示器”,因基于iPadOS而功能受限。
  • 价值与定位争议
    • 高昂售价(约3500美元) 被普遍认为在当前经济环境下不具性价比,特别是当功能与更便宜的竞品(如Quest 3)重叠时。
    • 有评论尖锐指出,设备缺乏杀手级应用,技术尚未成熟,类似于早期笨重的电脑。也有人将其与Meta Ray-Ban智能眼镜对比,认为后者以更低成本提供了实用功能。
    • 部分用户购买后因实用性不足而选择退货

三、关键讨论与背景

  • 关于高帧率电影的技术讨论
    • 有用户指出,公众几乎无法获得4K 3D HDR HFR的电影内容。
    • 电影制作从业者解释,帧率是艺术和商业选择。高帧率会极大改变拍摄的照明需求、增加成本和后期工作量,且观众对非24fps的“电影感”普遍不买账。因此,这类内容稀少。
  • 市场与未来展望
    • 设备目前仅在美国限量发售,用户基数很小。
    • 支持者常将其类比为第一代iPhone,认为需要等待后续迭代。反对者则指出VR/AR技术已发展多年,并非新概念。
    • 多数意见认为,更轻便的外形(如眼镜形态) 是此类设备普及的关键。
14. Voice Isolator: Strip background noise for film, podcast, interview production (elevenlabs.io)

Voice Isolator 摘要

产品概述:
Voice Isolator 是一款基于人工智能的音频处理工具,专为电影、播客、访谈等后期制作场景设计,能够从任何录音中去除背景噪音,提取清晰、专业的人声。

核心功能:

  • AI 驱动降噪:使用先进神经网络,可移除环境杂音、麦克风反馈、街道声、背景交谈、音乐及其他干扰,仅保留纯净语音。
  • 高精度人声分离:针对人类语音优化,实现录音棚级别的人声隔离,且音频失真极小。
  • 多格式支持:兼容 WAV、MP3、FLAC、OGG、AAC 等常见音频输入格式。
  • 简便操作流程:无需手动编辑或专业经验,只需三步:上传/录制音频 → 一键分离人声 → 下载处理后的音频。

适用场景:

  • 录制清晰的访谈或会议音频。
  • 为视频内容隔离人声
  • 移除受版权保护的背景音乐。
  • 提取人声用于混音或采样

技术基础:
基于 ElevenLabs 自主研发的深度学习模型与 AI 语音技术,提供企业级安全基础设施,并支持通过网页、API 或 SDK 集成使用。

总结:
Voice Isolator 通过智能化音频处理,简化后期制作流程,提升音频内容质量,适用于多种专业与日常场景。

15. Sans-IO: The secret to effective Rust for network services (www.firezone.dev)

Sans-IO:Rust在网络服务中高效应用的秘诀

Sans-IO 是一种网络协议的设计范式,其核心是将协议实现为纯状态机,不进行任何实际的I/O操作(如读写套接字、等待时间)。所有与I/O相关的操作都被抽象并移交给外部的事件循环。在Rust生态中,这种模式被quinnquichestr0m等库采用。

传统I/O方式的问题

传统网络服务代码通常将协议逻辑与I/O操作紧密耦合。在Rust中,这会导致函数着色问题:深度调用栈中的一个async函数会迫使所有调用链都变为async。这限制了代码的复用性,因为依赖库可能会强制你的代码采用特定的I/O模式(阻塞或非阻塞)。

Sans-IO 的解决方案

Sans-IO 遵循依赖倒置原则

  • 策略(协议逻辑) 不依赖于 实现(I/O细节)
  • 协议代码通过抽象(如Transmit结构体)与事件循环通信。
  • 时间也被抽象,函数接收Instant参数而非调用Instant::now

一个Sans-IO的状态机通常提供如下的核心API:

  • handle_input:处理传入的数据。
  • poll_transmit:输出待发送的数据。
  • handle_timeout:处理定时器事件。
  • poll_timeout:查询下一个需要唤醒的定时器时间。

事件循环(例如使用tokio或标准库阻塞I/O)负责驱动这个状态机,执行实际的套接字读写和定时器管理。

主要优势

  1. 高度可组合性:基于统一API,不同的协议状态机可以轻松组合。例如,Firezone的snownet库组合了ICE和WireGuard的状态机。
  2. API灵活性:事件循环由应用实现,可以自由优化,如使用sendmmsg批量发送,或复用单个套接字进行多路复用。
  3. 极速测试:状态机没有副作用,测试时可以轻易模拟时间快进、数据包丢失等场景,无需网络交互。这支持了基于属性的高级测试(如使用proptest)。
  4. 健壮的错误处理:将I/O失败和边缘情况(如数据包丢失、畸形响应)视为普通的输入,强制在状态机设计中就考虑这些问题,使代码更健壮。
  5. 与Rust语言特性完美契合
    • 纯状态机是同步的,可以自由使用&mut self来修改状态,充分发挥Rust借用检查器的优势。
    • 避免了在async任务中因需要'static而不得不使用Arc<Mutex<T>>或通道带来的运行时开销和复杂性。

缺点

  1. 需要编写事件循环:虽然提供了控制力,但也增加了工作量,并且可能引入如忙循环之类的bug。
  2. 对于复杂顺序流程代码量大:相比async/await提供的顺序语法,手动将复杂流程建模为状态机可能更繁琐。
  3. 生态尚不普及:遵循Sans-IO模式的库相对较少,大多数库仍采用传统的内置I/O方式。

总结

Sans-IO 通过将网络协议的核心逻辑与I/O副作用分离,带来了更高的可测试性、灵活性和代码健壮性。Rust的所有权模型和类型系统使其成为实现Sans-IO状态机的理想语言。尽管存在一些实践上的挑战,但对于需要高性能、高可靠性和深度定制的网络服务而言,Sans-IO是一个值得深入考虑的强大设计模式。

16. The Origins of DS_store (2006) (www.arno.org)

DS_Store 文件的起源

DS_Store 文件是 Mac 系统中的常见隐藏文件,其全称是 Desktop Services Store。这一命名源自 1999 年 Mac OS X Finder 的重写计划。

当时,Finder 代码已老化,因此团队决定完全重写。开发过程中,Finder 被拆分为前端(Finder_FE)和后端(Finder_BE)两个独立组件。后端负责文件枚举、文件系统监控、图标位置和文件夹设置等元数据管理。

由于 Finder 后端有望作为公共 API 复用,团队计划将其命名为“Desktop Services”(当时还考虑将 Finder 改名为“Desktop”)。因此,存储其设置的文件被命名为 .DS_Store,即“Desktop Services Store”。文件名前的“.”使其在 Unix 类系统(包括 Mac OS)中默认隐藏。

作者个人认为此名称不够理想,但已无法更改。

此外,文章提到一个长期存在的 Bug:DS_Store 文件被过度创建。按设计,仅当用户手动调整视图设置或设定图标位置时才应生成该文件,但实际上,访问文件夹就很可能触发其创建

最终,Desktop Services(即 Finder_BE)不仅被 Finder 使用,后来也被 Navigation Services(如打开/保存对话框)等程序采用。然而,该 API 至今仍未完全公开。

17. Artificial LIfe ENvironment (ALIEN) is an artificial life simulation tool (alien-project.gitbook.io)

ALIEN (Artificial LIfe ENvironment) 人工生命模拟工具概述

ALIEN 是一个基于CUDA的2D粒子引擎的专用人工生命模拟工具,主要用于模拟软体和流体媒介。其最新主要版本4对模型进行了重大更新,当前文档已过时,最新说明可在程序帮助中找到。

核心架构与特性:

  1. 双层粒子引擎

    • 底层:模拟软体及其周围流体的热力学行为。
    • 上层:负责信息处理和动作执行,为粒子网络赋予高级功能,如信息处理、传感器、肌肉、武器、构造器等。执行过程由信号系统协调。
  2. 矢量图形引擎

    • 渲染与模拟完全解耦。
    • 使用矢量图形和着色器后期处理来渲染模拟世界的各个部分。
    • 细节层次随缩放级别动态调整:缩小时仅显示节点,放大时可显示边缘、信息流及可选的内部状态。
  3. 强大的编辑功能

    • 粒子编辑器:可修改每个粒子的属性和功能,支持在运行时为多个粒子固定并实时更新编辑窗口,并为计算型粒子提供嵌入式编程环境。
    • 世界编辑器:可通过鼠标轻松拆卸、重组和连接现有生命体部件;可通过几何图形或手绘创建新生命体的结构图;支持批量操作以构建大型世界。
  4. 灵活的模拟参数控制

    • 可在不同空间区域定义不同的模拟参数,并支持参数随时间波动。

主要设计目标

  • 利用CUDA和OpenGL进行模拟与渲染,以支持拥有数百万粒子的大规模世界。
  • 无硬编码行为模式,所有行为均由粒子间的相互作用自然涌现。
  • 尽管模拟模型复杂且调整选项众多,仍力求提供友好的用户界面。
  • 对渲染的模拟数据进行视觉上吸引人的后期处理。
18. Building a data compression utility in Haskell using Huffman codes (lazamar.github.io)

这篇文章介绍了使用Haskell语言实现一个基于霍夫曼编码的数据压缩工具,能够在约150行代码内完成任意二进制文件的压缩和解压,并利用惰性求值特性实现恒定内存使用。

核心原理:霍夫曼编码

  • 一种无损数据压缩方法,通过为每个字符分配一个唯一的二进制码字来实现压缩。
  • 核心思想:为高频字符分配较短的码字,为低频字符分配较长的码字。
  • 必须使用前缀码(任何码字都不是其他码字的前缀),以确保解码的唯一性。
  • 编码树的构建算法:从权重最低的字符开始,逐步合并,确保频率高的字符更接近根节点,从而获得更短的码字。

Haskell实现概要

  1. 数据结构定义

    • 定义了Bit(One/Zero)、Code(位列表)、FreqMap(字符频率映射)和HTree(霍夫曼树,包含叶子节点和分支节点,并附加权重信息)。
    • HTree实现了Ord实例,按权重比较,便于构建有序列表。
  2. 编码过程

    • countFrequency:统计输入字符串的字符频率。
    • buildTree:根据频率表构建霍夫曼树。算法是将字符节点排序,反复合并权重最小的两个子树。
    • buildCodes:遍历霍夫曼树生成字符到码字的映射。左分支为1,右分支为0。
    • encode:使用生成的码表将字符串转换为比特流。利用惰性求值,通过concatMap流式处理,避免一次性生成整个中间列表,节省内存。
  3. 解码过程

    • decode:使用相同的频率表重建霍夫曼树,然后根据输入的比特流在树中遍历(1走左子树,0走右子树),每到达一个叶子节点即输出一个字符,并重新从根开始解码下一个字符。同样利用惰性求值实现流式解码。
  4. 序列化与反序列化(将压缩数据存入文件):

    • 序列化 (serialize):
      • 先将频率表写入文件:首先写入映射条目数(Map.size - 1),然后逐个写入字符(Word8)和对应的频率(64位整数)。
      • 再将比特流写入文件:将比特流按8位一组打包成字节写入,最后一个字节若不足8位则用0填充。
    • 反序列化 (deserialize):
      • 读取频率表:先读取映射条目数,然后依次读取字符和频率,重建频率表。
      • 读取剩余字节流,并将其逐个字节展开为比特列表。注意此步骤返回的[Bit]列表是惰性的,仅在需要时才计算,避免一次性加载整个文件到内存。
  5. 文件处理与CLI

    • compress函数:读取源文件两次(第一次统计频率,第二次编码),利用serialize写入压缩文件。
    • decompress函数:读取压缩文件,通过deserialize获取频率表和比特流,用decode解码后写入目标文件。
    • 命令行接口支持compressdecompress两个操作。

关键特性与优势

  • 惰性求值:整个处理过程(编码、解码、序列化)充分利用Haskell的惰性特性,实现流式处理。数据以“生产者-消费者”模式流动,处理一小部分后即可释放内存,从而保持恒定内存占用(压缩频率表本身的大小是常数)。
  • 模块化:代码分离了频率统计、树构建、编码/解码、序列化等步骤,结构清晰。
  • 二进制文件支持:通过Data.ByteString.Char8模块将字节视为字符处理,使得同一套文本编码逻辑可直接用于二进制文件。

测试结果

  • 文本文件(《战争与和平》):压缩后大小约为原始文件的60%。
  • 二进制文件(ghcup,106MB):压缩后约84MB,解压后与原文件一致,整个压缩/解压过程内存占用低于300KB。

潜在改进方向 文章最后提及了几种可提升效率的复杂方案,如多线程解码、单遍编码(边编码边更新频率表)、规范霍夫曼编码以及更快的码表生成算法。

总结:本文展示了一个简洁、高效、内存友好且可扩展的Haskell数据压缩实现,很好地体现了函数式编程在处理流式数据和管理资源方面的优势。

19. The sad state of property-based testing libraries (stevana.github.io)

这篇文章探讨了属性测试库当前令人遗憾的状态。作者通过历史回顾、现状调查和分析,指出尽管十五年前已出现先进的状态和并行测试技术,但当今大多数开源属性测试库仍缺失这些关键功能。文章提出了解决方案,并通过具体示例展示了如何以约400行代码简洁实现这些高级功能,同时倡导使用“假对象”代替状态机规范以降低使用门槛。

历史背景

属性测试源于90年代末的学术研究。John Hughes与Koen Claessen在查尔姆斯理工大学开发了开创性的QuickCheck库,其核心思想是“不写测试,生成测试”。该库最初只能测试纯函数。后续的商业化版本(Quviq QuickCheck)引入了两大突破性功能:

  1. 状态测试:基于状态机模型测试有状态系统。
  2. 并行测试:通过复用顺序状态机模型,结合线性一致性来检测并发系统中的竞态条件。 这些技术通过2006年至2009年间的一系列论文得以确立,但核心实现代码从未公开。

现状调查

作者对主流属性测试库(截至2024年7月)进行了调查,发现:

  • 状态测试:虽然不少库提供了实验性或有限的支持,但实现质量参差不齐。
  • 并行测试:支持的库寥寥无几,且多数实现存在问题或与经典方法不同。 许多库中用户请求添加这些特性的issue已开放多年,但进展缓慢。

现状分析

作者认为这种“悲伤”现状主要源于三个原因:

  1. 实用性认知:观点认为测试纯函数片段已能获得大部分收益,状态和并行测试的边际效益不高。
  2. 培训需求:编写状态机模型需要不同的思维方式,需要专门培训,而开源项目通常缺乏配套的培训资源。
  3. 商业模式:Quviq采取闭源并配套培训咨询服务的商业模式,被认为比单纯开源更利于技术在工业界的落地和持续改进。

作者对此提出了反驳:状态和并行测试对许多工业系统至关重要;纯属性测试同样需要培训;闭源模式虽可能助力商业采纳,却阻碍了技术在开源社区的广泛传播和复现。

解决方案与实现

作者提出两个方向:

  1. 提供精简的开源实现:旨在打破技术壁垒,促进普及。
  2. 简化规范:用程序员更熟悉的“假对象”替代形式化的状态机规范,降低学习成本。

文章的核心部分展示了一个约400行代码的库实现,其关键设计包括:

  • 核心接口:用户通过实现StateModel类型类来定义待测系统的状态、命令、响应以及一个纯函数的“假对象”实现(runFake)和一个执行真实系统操作的runReal
  • 生成与收缩:自动生成命令序列,并在测试失败时智能收缩以找到最小反例。
  • 执行与断言:执行命令序列,对比真实系统与“假对象”在相同输入下的输出是否一致。
  • 并行扩展ParallelModel接口复用顺序模型,通过生成并行命令树(Fork)并检查执行历史的线性一致性来发现竞态条件。

示例演示

作者通过一系列示例验证该方法:

  1. 纯函数与状态测试:计数器、环形缓冲器(修复了其C实现的多处错误)、《虎胆龙威3》水壶谜题(将状态测试用作路径探索模型检查器)。
  2. 并行测试:并发计数器(发现了竞态条件)和进程注册表(模拟Erlang进程注册表,发现了复杂的竞态条件)。演示中通过引入微小延迟来改善反例收缩效果。
  3. 集成测试:展示了如何将经过契约测试的“假对象”用于快速、确定性的集成测试。以队列和文件系统为例,说明了如何定义接口、实现真实与假对象版本,并利用假对象进行组件测试。这种方法可扩展至更复杂的系统,其中每个组件的假对象都经过自身的状态/并行属性测试来保证其正确性。

结论

作者总结,通过借鉴原始QuickCheck的简洁实现精神,并结合更易理解的“假对象”规范,完全有可能在开源世界中复兴高级属性测试技术。文章提供了完整的实现思路和代码示例,旨在激发社区在不同编程语言中进行实践和探索。

21. The magic of small engineering teams (newsletter.posthog.com)

小型工程团队的魔力

核心观点: PostHog 公司通过采用“小型团队”结构,在规模化的同时,保留了初创企业般的敏捷、创新和影响力。

小型团队的定义与结构

  • 规模: 每个团队2至6人,形成“单个披萨”团队(比亚马逊的“两个披萨”团队更小)。
  • 组成: 主要由“产品工程师”组成,他们与用户沟通并主导产品决策。
  • 目标: 拥有产品或公司的某个特定领域,并像早期初创公司一样运作。
  • 数量与范围: 目前公司47人分布在全球10个国家,分为15个小团队。团队负责特定产品(如数据仓库、产品分析)或职能(如人员运营、市场营销)。

运作模式与规则

  • 自主权高: 团队可决定功能发布、自行安排每周迭代和回顾,并将笔记公开于GitHub。
  • 目标设定: 每季度设定以“交付物”为导向的目标(而非抽象指标),并向管理层汇报。
  • 职责全面: 每个团队负责其领域内的路线图规划、用户沟通、指标监控、bug修复、支持协作等全部事务。
  • 组织扁平化: 最小化管理层级。每个团队设一名“团队领导”(通常是最适合该产品的人,通常由工程师担任),其职责聚焦于产品与团队表现。团队领导不等同于经理。经理则更关注员工幸福感、上下文设置及绩效问题。
  • 明确使命: 每个团队都有自己的使命,并支持公司整体使命(为每位开发者提供构建成功产品的工具)。团队需公开其长期目标、负责的功能/流程以及目标客户。

人员管理与协作

  • 人员流动: 优先通过招聘填补空缺,而非频繁内部调动。人员调动通常每3-9个月发生一次,由经理决定。
  • 单一归属: 每位成员同一时间只能属于一个团队,以保障所有权清晰。若需跨团队工作,表明需要招聘。
  • 跨团队协作: 鼓励跨团队项目合作和会议参与,以解决共有问题。

优缺点权衡(Tradeoffs)

  • 优势: 实现快速交付、扁平结构、保持初创公司文化、高度自主。
  • 缺点及应对:
    • 职责重叠: 通过激进的透明化和明确的职责清单来缓解。
    • 所有权模糊: 设有“模糊所有权”流程鼓励解决问题,必要时组建临时团队。
    • 集成问题: 为追求速度,容忍一定程度的产品集成不够完美(类似AWS)。
  • 人才要求: 要求员工具备极端责任感、主动、真诚且不自负。这种文化并不适合所有人。
22. High-altitude cave used by Tibetan Buddhists yields a Denisovan fossil (arstechnica.com)

丹尼索瓦人高海拔洞穴化石及生存特征研究总结

动物骨骼与狩猎行为分析 洞穴中发现的动物骨骼大多带有人工切割肌肉、砸骨取髓及加工成工具的痕迹,而啮齿动物和捕食者造成的损伤仅占1%。这表明洞穴居住者(丹尼索瓦人)并非单纯食腐,而是具备主动狩猎能力。此外,较新地层中羊骨数量的增加,说明其狩猎技能正逐渐向专业化发展。

丹尼索瓦人化石新发现 研究还发现了一块5厘米长的肋骨碎片,经胶原蛋白测序确认属于丹尼索瓦人,这是迄今获得的较大骨骼样本之一。值得注意的是,该化石出土于环境DNA未显示丹尼索瓦人存在的地层(原因可能是访问频率降低或DNA保存问题)。这一发现证实,丹尼索瓦人至少在3万年前仍活跃于青藏高原。

生存能力与基因遗传 尽管受限于化石保存状况,研究尚未揭示丹尼索瓦人的外貌特征及植物性饮食习惯,但现有发现充分表明:丹尼索瓦人能够在严酷的高海拔气候中生存,并成功度过了两个不同的冰河时期,展现出卓越的生存适应能力。此外,他们似乎将至少一种有助于适应高海拔环境的基因遗传给了现代青藏高原居民。

文献来源:《Nature》, 2024 (DOI: 10.1038/s41586-024-07612-9)

23. Luakit: A fast, extensible, and customizable web browser (luakit.github.io)

Luakit: 快速、可扩展、可定制的网络浏览器

概述

Luakit 是一个高度可配置的浏览器框架,基于 WebKit 内容引擎和 GTK+ 工具包。它速度快,可通过 Lua 扩展,并采用 GNU GPLv3 许可证。主要面向高级用户、开发者以及需要精细控制浏览器行为和界面的用户。

主要特性

  • 高性能:基于 WebKit 引擎,加载和渲染速度快。
  • 可扩展性:支持通过 Lua 脚本进行功能扩展和自定义。
  • 可定制化:用户可以调整界面和行为,如主题和标签布局。
  • 开源许可:遵循 GNU GPLv3 许可证。

最新版本

  • 当前版本为 Luakit 2.4.0,提供旧版本列表供参考。

功能示例

通过截图展示:

  • 普通模式:浏览网页。
  • 跟随模式:显示链接提示。
  • 广告拦截设置:管理过滤列表。
  • 自定义主题和垂直标签:支持界面个性化。

支持的操作系统

  • Linux:通过包管理器(如 Arch Linux 的社区包)或从源代码构建。
  • BSD:FreeBSD 和 OpenBSD 支持安装包;OpenBSD 用户需使用 clang 构建。
  • Windows 10:通过 Windows Subsystem for Linux(WSL)运行,不原生支持。

安装方法

从源代码安装

  1. 依赖项
    • GTK 3
    • WebKitGTK+(webkit2gtk)
    • Lua 5.1 或 LuaJIT
    • lfs(Lua File System)
    • SQLite 3
  2. 获取代码
    • 下载最新开发版本(zip 或 tar)。
    • 或通过 Git 克隆:git clone git://github.com/luakit/luakit
  3. 构建与安装
    • 进入目录,运行 make install,可自定义安装前缀(默认 /usr/local)。
    • 详细说明见 README.md 文件。
    • 构建过程快速,因代码量约 9000 行。

其他安装方式

  • Linux:Arch Linux 用户可安装 luakitluakit-git 包。
  • BSD:FreeBSD 和 OpenBSD 用户可直接安装 luakit 包。
  • Windows 10:先安装 WSL,然后从源代码构建。

安全提示

  • Luakit 使用 WebKit 2 API 以提高安全性。
  • 用户需确保发行版包提供最新版 WebKitGTK+,避免漏洞(如 OpenSUSE 稳定版可能过时)。
  • 推荐使用 Arch、Debian、Fedora、Gentoo 或 Ubuntu 等已更新版本的系统。

贡献与支持

  • 提供文档、帮助与支持、贡献指南,并托管在 GitHub 上。
24. Wcurl: a curl wrapper to download files (samueloph.dev)

wcurl 是一个轻量级的命令行工具,作为 curl 的包装器,旨在简化通过终端下载文件的过程。它专为那些只想快速下载文件,而不必记忆 curl 复杂参数的用户设计。

主要功能与特点

  • 简单易用:核心命令为 wcurl <URL>,例如 wcurl example.com/file.txt
  • 智能默认行为
    • 自动文件命名:根据 URL 自动确定输出文件名,若 URL 中无文件名则默认使用 index.html
    • 并行下载:支持同时下载多个 URL(需 curl 版本 ≥ 7.66.0)。
    • 其他优化:自动跟随重定向、禁止覆盖已存在文件(需 curl 版本 ≥ 7.83.0)、进行重试、设置服务器提供的文件时间戳、处理 URL 中的空白字符等。
  • 灵活扩展:通过 --curl-options 参数可以向底层 curl 传递自定义选项,以应对特殊需求。
  • 实现方式:本质上是一个 POSIX 兼容的 shell 脚本,调用系统已安装的 curl 命令来完成工作。

创建背景与目的

作者及许多用户都经常忘记 curl 下载文件时所需的参数(如 -L -O -C 等),而转而使用 wget。2024 年 curl 项目的用户调查也反映出大量用户希望拥有类似 wget 的、更简单的文件下载体验。因此,作者开发了 wcurl,旨在提供一个专注于文件下载、默认行为合理的独立工具,弥补 curl 在此特定场景下的易用性缺口。

可用性与安装

  • 在 Debian 系统:作为 curl 包的一部分提供,已包含在 Debian unstable、testing 及 bookworm-backports 中,并将在 Debian 13/trixie 中作为标准组件。大多数 Debian 衍生版(如 Kali Linux)也会自动获得。
  • 手动安装:用户也可以自行下载脚本并放置到 /usr/bin 目录下。
  • 项目归属:wcurl 已正式加入 curl 官方项目组织。

项目现状与展望

目前,wcurl 作为一个独立的包装器脚本存在。作者希望未来可能有人将其功能以更原生的形式(例如使用 libcurl)集成到上游 curl 项目中。在现阶段,它主要作为解决文件下载易用性问题的一个实用方案。

项目主页与反馈https://curl.se/wcurl/ ,代码托管在 GitHub。

25. The Math of Card Shuffling (fredhohman.com)

洗牌数学原理:从有序到随机所需次数

文章探讨了两种洗牌方式所需的数学次数:

1. 标准Riffle洗牌(将牌均分两半并交叉洗)

  • 一副52张牌的所有可能排列数为52!,是一个极其巨大的数字。
  • 研究表明,仅需7次标准riffle洗牌,即可使牌序达到充分随机,出现此前从未有过的排列顺序的可能性极高。

2. 单张插入式洗牌(每次只将一张牌随机插入牌堆)

  • 过程模拟:从一副有序牌中,每次将顶部一张牌随机插入牌堆任意位置。以黑桃A(A♠)开始,不断操作直至最初的底牌方块K(K♦)升至顶部。
  • 数学原理:计算K♦上升到顶部的平均洗牌次数。每次洗牌时,K♦不动或上升一位,随着其位置上升,被新插入牌超越的概率增加。
  • 关键公式:所需平均洗牌次数为 [ \sum_{i=1}^{52} \frac{52}{i} = \frac{52}{1} + \frac{52}{2} + \cdots + \frac{52}{52} \approx 236 ] 因此,平均需要236次单张插入式洗牌才能彻底随机化牌序。

3. 可视化演示

文章提供交互工具,可模拟单张洗牌过程,追踪底牌(如方块K)的移动轨迹。实际演示中,该牌在约236次洗牌后升至顶部,符合理论计算。

结论

  • 标准riffle洗牌效率高,仅需7次即可随机化。
  • 单张插入式洗牌效率低,需约236次。
  • 数学表明,一副牌的随机排列数量极大,几乎不可能出现两次相同的洗牌结果。

来源

内容基于2015年Numberphile视频及相关数学论文,附有Github源码与Idyll工具制作的可视化演示。

26. Region-specific Machines pricing (community.fly.io)

Region-specific Machines pricing 总结

主要变更: 自2024年7月1日起,Fly.io 对其 Machines 服务的定价进行了重大调整。此前,无论 Machines 部署在哪个区域(如圣保罗、伦敦、东京),其价格都是统一的。现在,定价已改为按区域区分CPU 和 RAM 等资源的价格因地理位置而异。这意味着用户在不同区域部署或运行相同的 Machine 配置,将产生不同的费用。

用户反馈与讨论要点:

  1. 价格上涨与担忧:

    • 许多用户计算后发现,部分区域的价格有显著上涨。例如,有用户指出悉尼区域的 CPU 和 RAM 价格上涨约25%,而圣保罗区域对于高性能配置的涨幅可能高达约61%。
    • 此次涨价引发了社区对 Fly.io 公司状态和财务健康的担忧。有用户提及此前 Hobby 计划的取消、Kubernetes 服务定价较高(每月75美元)、免费额度政策变化等一系列举措,并希望公司能更透明地说明其运营状况和资金消耗情况。
  2. 定价页面问题与改进建议:

    • 技术显示问题:新定价页面存在显示错误,例如某些区域的每秒、每小时和每月价格计算不一致,后经官方确认为舍入显示问题并已修复。
    • 用户体验不佳
      • 用户希望能同时比较多个区域的价格,以便轻松选择成本最低的部署位置。
      • 希望定价页面的“工作示例”中的区域选择器能按字母顺序排序,并支持搜索(包含城市和国家全名)。
      • 强烈建议在账单页面新增功能,直观显示旧统一价格与新的区域价格对当前使用量所产生的成本差异,帮助用户评估影响。
  3. 竞争对手提及:

    • 有用户提到了 Akamai Linode 预计将于当年晚些时候推出全球负载均衡器,其价格具有竞争力,可能成为 Fly.io 的替代品。
  4. 官方回应:

    • Fly.io 工作人员 (jfent) 回应了部分问题,确认了显示问题的修复,并表示将改进区域选择器的显示(添加完整名称)和计划增加账单页面的价格比较功能。
    • 对于“是否提供承诺折扣”的询问,官方未给出明确答复,建议通过支持邮箱沟通。

核心结论: Fly.io 正在转向基于成本的区域差异化定价模型。这一变化虽然符合云计算行业的常见做法,但已对部分用户造成成本压力,并引发了关于公司战略和透明度的社区讨论。用户普遍希望平台能提供更清晰的定价信息和更便捷的成本管理工具。