要求參數名稱要加上單位的請願

Hacker News 上看到「Please put units in names (ruudvanasseldonk.com)」這邊的討論,看到的時候已經超過 900 點了 (好像還在急遽成長),算是爆紅狀態,可以感覺到超多 developer 們的怒氣 XDDD

原文在「Please put units in names」這篇,在講參數的命名要加上單位,尤其是時間相關的參數。

時間相關的參數根本沒有共識,你不查資料不會知道是 ns、ms 還是 seconds,所以就會出現象在這三個程式語言跑出來的時間是不一樣的:

然後你就翻桌了 XDDD

Amazon EFS 的效能提昇

AWS 宣佈他們將 Amazon EFS 的 latency 大幅降低以提昇效能:「Amazon Elastic File System Update – Sub-Millisecond Read Latency」。

Linux 上一般是用 NFS 掛 EFS,個位數的 ms 的確對於效能影響超大,現在宣稱讀取的部份降到 0.6ms,應該會有蠻明顯的感覺:

Up until today, EFS latency for read operations (both data and metadata) was typically in the low single-digit milliseconds. Effective today, new and existing EFS file systems now provide average latency as low as 600 microseconds for the majority of read operations on data and metadata.

然後不另外收費:

This performance boost applies to One Zone and Standard General Purpose EFS file systems. New or old, you will still get the same availability, durability, scalability, and strong read-after-write consistency that you have come to expect from EFS, at no additional cost and with no configuration changes.

另外就是過去幾個禮拜他們把現有的 EFS 都轉移過去了:

We “flipped the switch” and enabled this performance boost for all existing EFS General Purpose mode file systems over the course of the last few weeks, so you may already have noticed the improvement. Of course, any new file systems that you create will also benefit.

不過 EFS 另外一個問題就是貴炸,用錢換方便...

QTE 小遊戲 Looptap

Hacker News 首頁上看到這個小遊戲:「Show HN: Looptap – A minimal game to waste your time (vasanthv.com)」,如同他的標題寫的,浪費時間的小遊戲 XDDD

標題講的 QTE 是「快速反應事件」這個東西,在現在的遊戲裡面算是蠻常見的機制,是一種需要在事件有效區間反應的設計 (太早反應或是太晚反應都不行)。

Ingo Molnár 提出讓 Linux Kernel 編譯速度提昇的 mega patch

Hacker News 首頁上看到「Massive ~2.3k Patch Series Would Improve Linux Build Times 50~80% & Fix "Dependency Hell"」這個,對應到 mailing list 上的信件是「* [PATCH 0000/2297] [ANNOUNCE, RFC] "Fast Kernel Headers" Tree -v1: Eliminate the Linux kernel's "Dependency Hell"」這個,看到「0000/2297」這個 prefix XDDD

他主要是想要改善 Linux Kernel 的 compile 時間 (從 project 的名稱「Fast Kernel Headers」可以看到),只是沒想到會縮短這麼多。另外一方面也順便處理了 dependency hell 的問題 (改善維護性)。

測試出來的結果相當驚人,從 231.34 +- 0.60 secs (15.5 builds/hour) 到 129.97 +- 0.51 secs (27.7 builds/hour),以編譯次數來看的話是 78% 的改善。如果以 CPU time 來看的話,從 11,474,982.05 msec cpu-clock 降到 7,100,730.37 msec cpu-clock,也是以編譯次數來算的話,有 61.6% 的改善...

這是花了一年多的時間嘗試才達成的目標,嘗試不同的方法,前幾次雖然都有改善,但改善幅度太小,變動卻太大,他覺得不值得丟出來,直到第三次才達成這樣的目標...

第一次:

When I started this project, late 2020, I expected there to be maybe 50-100 patches. I did a few crude measurements that suggested that about 20% build speed improvement could be gained by reducing header dependencies, without having a substantial runtime effect on the kernel. Seemed substantial enough to justify 50-100 commits.

第二次:

But as the number of patches increased, I saw only limited performance increases. By mid-2021 I got to over 500 commits in this tree and had to throw away my second attempt (!), the first two approaches simply didn't scale, weren't maintainable and barely offered a 4% build speedup, not worth the churn of 500 patches and not worth even announcing.

第三次:

With the third attempt I introduced the per_task() machinery which brought the necessary flexibility to reduce dependencies drastically, and it was a type-clean approach that improved maintainability. But even at 1,000 commits I barely got to a 10% build speed improvement. Again this was not something I felt comfortable pushing upstream, or even announcing. :-/

然後基於第三次的成果覺得有望,意外的發現後續的速度改善比想像中的多非常多:

But the numbers were pretty clear: 20% performance gains were very much possible. So I kept developing this tree, and most of the speedups started arriving after over 1,500 commits, in the fall of 2021. I was very surprised when it went beyond 20% speedup and more, then arrived at the current 78% with my reference config. There's a clear super-linear improvement property of kernel build overhead, once the number of dependencies is reduced to the bare minimum.

這次的 patch 雖然超大包,但看起來對於 compile 時間改善非常多,應該會有不少討論... 消息還蠻新的 (台灣時間今天早上五點的信),晚點可以看一下其他大老出來回什麼...

列出 curl 連線的內部時間資訊

Twitter 上看到一個很久前的討論:

裡面提到了「Timing Details With cURL」,可以給一個 template 進去輸出內部資訊:

time_namelookup: %{time_namelookup}
time_connect: %{time_connect}
time_appconnect: %{time_appconnect}
time_pretransfer: %{time_pretransfer}
time_redirect: %{time_redirect}
time_starttransfer: %{time_starttransfer}
———
time_total: %{time_total}

不過我實際測試發現現在的 curl 版本要加上 \n 才會換行,之後可以拿來 debug 看看...

QOI 圖片無損壓縮演算法

Hacker News Daily 上看到「Lossless Image Compression in O(n) Time」這篇,作者丟出了一個圖片的無損壓縮演算法,壓縮與解壓縮的速度超快,但壓縮率又不輸 PNG 太多,在 Hacker News 上的討論也可以看一下:「QOI: Lossless Image Compression in O(n) Time (phoboslab.org)」。

裡面有提到在遊戲產業常用到的 stb_image.h

Yes, stb_image saved us all from the pains of dealing with libpng and is therefore used in countless games and apps. A while ago I aimed to do the same for video with pl_mpeg, with some success.

作者的簡介也可以看到他的主業也在遊戲這塊:

My name is Dominic Szablewski. I build games, experiment with JavaScript and occasionally tinker with low-level C.

圖片的無損壓縮與解壓縮算是遊戲創作者蠻常用到的功能,所以他想要看看這塊有沒有機會有更好的工具,於是他就用了四個很簡單的演算法幹完了 QOI (然後發現效果很讚):

  • A run of the previous pixel
  • An index into a previously seen pixel
  • The difference to the previous pixel
  • Full rgba values

其實從 Hacker News 的討論也可以看到這組演算法也常被拿出來在現代的壓縮演算法使用,所以雖然作者自稱不是 compression guy,但他用的演算法其實蠻專業的...

然後挑 single thread 主要是可以避免 threading 的複雜度以及 overhead,在「QOI Benchmark Results」這頁可以看到,無論是什麼類型的檔案,壓縮與解壓縮的速度都相當漂亮,而且壓縮率又沒有差 libpng 太多。

而且作者自己有提到,還沒用到 SIMD 指令集加速,這樣猜測應該還有不少空間...

Fork 自微軟的 Pyjion 專案的 Python 3.10 + JIT 方案

Hacker News 上看到「Pyjion – A Python JIT Compiler (trypyjion.com)」這個專案,也是一個想要透過 JIT 加速 Python 的專案:

Pyjion is a drop-in JIT Compiler for Python 3.10. It can be pip installed into a CPython 3.10 installation on Linux, Mac OS X, or Windows.

看了一下是從微軟的 Pyjion 專案 fork 出來的,原來的專案最後一次 commit 是一年前,而且專案也已經標示為 archived (read-only mode),但有留下轉移的說明,也就是上面提到的專案:

Development has moved to https://github.com/tonybaloney/Pyjion

可以看到大部分的效能都已經進入改善階段 (很多導入 JIT 的專案在初期時會先變慢):

跟其他的 JIT 方案相比,Pyjion 的目標是高度相容現有 Python 的程式,包括各種 extension,這點的確是在用 PyPy 這些軟體時的痛點沒錯...

看起來透過 pip 裝好後就可以直接 import 進來用,後續就會生效:

import pyjion; pyjion.enable()

另外提一下,翻 Hacker News 留言的時候翻到這個害我笑出來,有夠新 XD

zatarc 3 days ago | unvote | prev | next [–]

Pyjion requires: CPython 3.10 and .NET 6

.NET 6 Release: 19 hours ago (https://github.com/dotnet/core/blob/main/release-notes/6.0/6...)

... ok.

用 PostgreSQL 的 int4range 與 GiST

發現自己根本還不熟悉 PostgreSQL 的特性,寫一下記錄起來。

產品上常常會有 coupon 與 voucher 之類的設計,這時候通常都會設定 coupon 或 voucher 的有效期間,在 MySQL 的環境下可能會這樣設計:

CREATE TABLE coupon (
  id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  code VARCHAR(255) NOT NULL,
  started_at INT UNSIGNED NOT NULL,
  ended_at INT UNSIGNED NOT NULL
);

另外是設計 index 的部份,在產品推出夠久後,通常是過期的 coupon 或 voucher 會比目前還有效的多,而還沒生效的 coupon 與 voucher 通常都不多,所以會設計成對 ended_at 放一組 B-tree index:

CREATE INDEX ON t1 (ended_at);

這個設計不算差,不過用了一些假設。

如果不想要用這些假設,可以改用 Spatial 的資料型態去模擬並且加上 index (使用到 LineString Class),這樣就直接對 a < x < b 這類查詢更有效率,不過缺點就是可讀性會比較差。

在 PostgreSQL 這邊就有更清晰的資料結構來處理這些事情,主要是有一般性的 int4rangeint8range 以及時間類的 tsrangetstzrangedaterange (參考「Range Types」這邊有更多資料型態),所以會變成:

CREATE TABLE coupon (
  id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  code VARCHAR NOT NULL,
  active_at INT4RANGE NOT NULL
);

然後用 GIST 建立 index:

CREATE INDEX ON t1 USING GIST(active_at);

後續的 query 語法就用 <@ 的語法:

SELECT COUNT(*) FROM coupon WHERE 10000 <@ active_at;

塞了 10M 筆資料後的 table 可以看到本來需要的時間是:

Time: 779.542 ms

變成:

Time: 5.510 ms

不過缺點就是 SQLite 沒支援這些資料型態,對於 test case 就一定得跑個 PostgreSQL 起來測...

RFC 3339 與 ISO 8601 用範例的比較

Hacker News 首頁上看到「RFC 3339 vs. ISO 8601 (ijmacd.github.io)」這個連結,原始網站是「RFC 3339 vs ISO 8601」。

兩個都是試著定義日期與時間的表達方式,其中 ISO 8601 是在 1988 年定義出來的,被廣泛應用在很多 spec 裡,但最大的問題就是 ISO 8601 沒辦法公開免費取得,這點在前幾個月也在 Hacker News 上被討論過:「ISO-8601 date format reference not publicly available (twitter.com/isostandards)」。

RFC 3339 是在 2002 年訂出來,其中一個目標就是試著解決 ISO 8601 不公開的問題 (沒講明就是了):

This document includes an Internet profile of the ISO 8601 [ISO8601] standard for representation of dates and times using the Gregorian calendar.

這份 RFC 3339 與 ISO 8601 的比較可以讓設計 spec 的人可以看一下,在大多數的情況下,RFC 3339 應該是夠用的...

YJIT 帶給 Ruby 大量的效能提昇

Hacker News 首頁上看到的消息,由 Shopify 贊助的 YJIT 被 Ruby 官方接受了:「Merge YJIT: an in-process JIT compiler (github.com/ruby)」。

YJIT currently provides average speedups of 23% over the CRuby interpreter on realistic benchmarks, and near-instant warm-up time.

實做 YJIT 的 Maxime Chevalier-Boisvert 在他自己的 blog 上有提到這次的實做:「YJIT: Building a New JIT Compiler Inside CRuby」,裡面選擇的方法是他的 PhD 論文:「Simple and Effective Type Check Removal through Lazy Basic Block Versioning」。

可以看到在六月寫文章的時候,改善其實還沒這麼大,而且作者提到有不少可以再提昇的空間:

That being said, according to our benchmarks, we’ve been able to achieve speedups over the CRuby interpreter of 7% on railsbench, 19% on liquid template rendering, and 19% on activerecord.

Currently, only about 50% of instructions in railsbench are executed by YJIT, and the rest run in the interpreter, meaning that there is still a lot we can do to improve upon our current results.

本來的 MJIT 看起來會慢慢淡出...