HackerURLs

一次又一次被重新发现的经典。

同一个链接,相隔一年以上,一次又一次被人重新发现、再次冲上 Hacker News 首页。能经受住这种时间检验的,大多是值得一读再读的文章。每篇附中文标题,讨论最热的那些再加上中文导读和高赞评论翻译。

从名人堂开始
  • 4,700+篇经过时间检验的经典

Hall of fame

名人堂

在经典库里看全部精选

上首页次数最多、而且有中文导读的 30 篇。时间轴上每个黑点是一次上首页,空心点是一次没冲上去的投稿。

  1. 正在载入经典…

Archive

经典库

按第一次上首页的年份分布,点柱子筛选。

排序

    About

    这些经典是怎么挑出来的

    1. 01

      合并同一个链接

      读取 Hacker News 自 2006 年以来的全部链接投稿,把 http/https、www、跟踪参数等写法不同的同一篇文章合并成一条。

    2. 02

      只留经得起时间的

      同一链接至少两次拿到 50 分以上(约等于上首页),而且两次相隔一年以上;再由 AI 剔除状态页、产品首页和新闻事件。

    3. 03

      写导读、译评论

      上首页次数最多的 2,000 篇配上中文导读、"为什么经久不衰",并精选翻译 HN 高赞评论。导读由 AI 生成,可能有误。

    编程与软件工程atastypixel.com

    音频开发中的四个常见错误

    Four common mistakes in audio development

    2次上首页
    3年跨度
    695累计得分
    351条评论

    2016 — 2019,它一次次回到首页

    黑点是上首页(≥ 50 分)的那次投稿,空心点是没冲上去的投稿,点越大分数越高。

    导读

    这篇博文总结了音频开发中的四个常见错误,重点围绕实时音频回调不能阻塞、不能随意加锁或分配内存等约束展开。作者结合自己在 iOS 和实时音频方面的经验,说明如何让核心音频线程保持快速、可预测。

    为什么经久不衰:实时音频的线程与性能约束不会随框架过时,文中列出的坑以及评论里关于原子操作、优先级反转的讨论,至今仍是低延迟音频系统的必修课。

    关键词 实时音频音频开发并发性能优化

    HN 评论精选

    实时合成应使用 C/C++,核心循环要快且不受干扰,少分配、少拷贝、预计算并注意 denormal。

    这些错误基本上可以归结为:不要用慢速脚本语言,并让核心缓冲区循环跑得快且不受干扰。实时合成请用 C 或 C++,尽早优化;在 -π 到 π 范围内使用三角函数近似;不要用查找表,它们会无谓地占用缓存,CPU 已经够快;核心循环写成无分支形式,围绕缓存优化,使用向量化和函数指针。不要用花哨的东西,简单的 int32_t、float 和 vector/array 就够了(有些滤波器需要双精度)。不要拷贝数据,用指针指向它;能预计算的先算好,比如不要做 x / samplerate,而做 x * samplerate_inverse;还要检查非规格化数。

    iammyIP查看英文原文

    These mistakes basically boil down to not using slow scripting languages and making the core buffer loop run fast and undisturbed. For realtime synthesis use c or c++, optimise early, use trigonometry approximations in range -pi / pi, do not use lookup tables, they unnecessarily fill the cache, cpus are fast enough, write the core loop branchless, write for cache, use vectorisation and function pointers. Do not use anything fancy, simple int32_t, float and vector/array is enough (some filters need double precision though). Do not copy stuff, point to it. Precalculate what can be precalculated, e.g. dont do x / samplerate, do x * samplerate_inverse. Check for denormals.

    跨线程无锁读写还要考虑编译器重排和内存屏障,应使用原子操作而不是依赖 volatile。

    文中说“在所有现代处理器上,可以在一个线程给 int、double、float、bool、BOOL 或指针变量赋值,再在另一个线程读取而不用担心撕裂”,这在 CPU 层面(某些 CPU)成立,但编译器优化呢?用 volatile 可以让读写发生在代码写的位置,但多线程场景能依赖它吗?它被普遍反对是有原因的,也许只针对有限范围的 CPU(文章似乎只关注 iOS 和 ARM)可以接受。更稳妥的是用 __atomic_load 和 __atomic_store,或平台支持的 C11 原子操作;它们为所有 CPU 架构提供安全的加载/存储,并为需要缓存一致性的架构提供合适的内存屏障。

    exDM69查看英文原文

    > It can be helpful to know that, on all modern processors, you can safety assign a value to a int, double, float, bool, BOOL or pointer variable on one thread, and read it on a different thread without worrying about tearing This is true on the CPU side (for some CPUs) but what about compiler optimizations? Using "volatile" should make stores and loads happen where they are written in the code, but can it be relied on in multi threaded use cases? It's generally frowned upon for a good reason, but perhaps it's acceptable if you're targetting a limited range of CPUs (the article seems to be focused on iOS and ARM only). A safer bet would be to use __atomic_load and __atomic_store (from [0] or [1]) or C11 atomics if you have the appropriate headers for your platform. They provide safe loads and stores for all CPU architectures, and provide the appropriate memory barriers for cache coherency (for architectures that do care). [0] https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html#g_t_005f_005fatomic-Builtins [1] http://clang.llvm.org/docs/LanguageExtensions.html#langext-c11-atomic

    对“优先级反转”的常见解释提出疑问:等待锁时实时线程已让出 CPU,为什么还会阻碍其他线程?

    假设 GUI 线程持有共享锁时音频回调运行。音频回调要按时返回缓冲区,就得先等 GUI 线程释放锁。GUI 线程优先级远低于音频线程,可能被系统里几乎任何其他进程打断,于是回调要先等那个进程,再等 GUI 线程释放锁,才能算完缓冲区——即使音频线程可能是系统里优先级最高的。这叫优先级反转。我大概从根本上没理解优先级反转。我做过不少实时编程,但从未直面这个术语。如果我的实时优先级 I/O 完成例程试图获取一个可能被空闲优先级 GUI 线程持有的锁,为什么这是问题?如果我在等锁,那么按定义我在等待时就不是以实时优先级运行。线程优先级应该只适用于真正在干活的线程。内核在我等待别的线程释放锁时反而不调度其他线程,那才荒唐。我的实时线程在等待期间实际上被挂起了,所以它不能阻止任何其他线程运行。是的,我可能得等其他线程甚至其他进程被调度,那也没办法……

    CamperBob2查看英文原文

    Let’s say your GUI thread is holding a shared lock when the audio callback runs. In order for your audio callback to return the buffer on time it first needs to wait for your GUI thread to release the lock. Your GUI thread will be running with a much lower priority than the audio thread, so it could be interrupted by pretty much any other process on the system, and the callback will have to first wait for this other process, and then the GUI thread to finish and release the lock before the audio callback can finish computing the buffer — even though the audio thread may have the highest priority on the system. This is called priority inversion. I guess I fundamentally don't understand priority inversion. I've done a lot of realtime programming but have never had to confront that particular buzzword. If my realtime-priority I/O completion routine tries to take a lock that might be held by an idle-priority GUI thread, why is that a problem? If I'm waiting on a lock, then by definition I'm not running at realtime priority while I'm doing so. Thread priorities should apply only to threads that are actually doing stuff. It would be crazy for the kernel to fail to schedule any other threads while I'm waiting for one of them to release the lock I need. My realtime thread is effectively suspended during that wait, so it can't keep any others from running. Yes, I might have to wait for other threads and even other processes to be scheduled. Too bad. If I didn't want that to happen, I shouldn't have tried to take a lock in a realtime thread. What exactly should I have expected to happen?

    实时/资源受限环境迫使工程师舍弃花哨技术,只写必要代码,反而能提升工程能力。

    我真的很喜欢有时间限制的环境,我认为它们真正解放了程序员:不用再纠结选哪种语言/库/技术/模式,而是突然意识到“哦,我们没时间搞那个”。要 GC 吗?没时间。要分配内存吗?没时间。要搞企业级、上万个源码文件的 OOP 继承体系吗?没时间。实时性迫使人们少写代码,只写真正重要的东西,我认为这在某种程度上能让人成为更好的工程师。我只是希望它对人们更有吸引力——在时间和资源受限的系统(比如 MCU)里折腾,可以和写 HTML/JS 让网站按你想的方式运行一样有趣。

    dmytroi查看英文原文

    I really love time restricted environments, in my opinion they truly liberate programmers: instead of using language/library/tech/pattern/etc-of-choice they suddenly realize "oh, we don't have time for that". Do we need GC? We don't have time for that. Do we need to allocate memory? We don't have time for that. Can we maybe do this enterprise-like tens thousands source code files OOP hierarchy thing? We don't have time for that. Realtime forces people write less, writing only what actually matters, and all this in my opinion helps people to be better engineers (in-a-way). I just wish it looked more attractable for people - hacking your way out in time/resources constrained systems (like MCU's for example) can be as fun as hacking html/js to make your site behave as you want.

    历次讨论

    同类还值得读

    1. 开源应用架构

      The Architecture of Open Source Applications

      《开源软件架构》(AOSA)是一本在线免费书,邀请知名开源项目的作者亲自剖析其内部设计,涵盖 SQLAlchemy、LLVM、Audacity、Apache、Bash 等系统。

      编程与软件工程上首页 9 次 · 2011–2024aosabook.org编辑精选
    2. 编程语言简史:简短、不完整且多半错误

      A Brief, Incomplete, and Mostly Wrong History of Programming Languages

      一篇以戏谑、故意不准确的方式回顾编程语言史的博客文章,用夸张轶事和讽刺定义串起 Lisp、C、C++、Java、JavaScript、PHP 等语言。

      编程与软件工程上首页 8 次 · 2009–2021james-iry.blogspot.com
    3. SQLite 是如何测试的

      How SQLite is tested

      SQLite 官方文档页,系统介绍 SQLite 的测试体系:多种测试方法(TCL 测试、模糊测试、回归测试、静态分析等)和海量测试用例,展示了这个小型开源项目如何靠极致测试获得…

      编程与软件工程上首页 8 次 · 2009–2025sqlite.org编辑精选
    4. 高级编程语言(2009)

      Advanced programming languages (2009)

      Matt Might 的经典文章,按用途推荐“高级编程语言”:如果追求就业就选主流语言,如果追求表达力、学术研究或创业,则推荐 Haskell、OCaml、Scala 等函数式语…

      编程与软件工程上首页 8 次 · 2009–2022matt.might.net
    5. 我的 Forth 与栈机器经历

      Yosefk - My history with Forth & stack machines

      作者以亲身经历回顾了使用 Forth 语言和栈式机器的历程:既赞叹其简洁优雅、代码量小、可自举的优点,也坦率指出栈操作在实际编程中的痛苦,以及 Forth 社区文化中的问题。

      编程与软件工程上首页 8 次 · 2010–2024yosefk.com编辑精选

    打赏支持

    打赏二维码

    觉得有用,请作者喝杯咖啡。

    WeChat

    关注向阳乔木

    微信公众号「向阳乔木推荐看」

    微信公众号「向阳乔木推荐看」二维码

    微信扫一扫;在微信里打开本页时,长按二维码识别。