Let's Encrypt 想要停掉 OCSP 服務

看到 Let's Encrypt 貼出來的文章,想要停掉 OCSP 服務:「Intent to End OCSP Service」,而打算以 CRLs 為主。

OCSP 是拿來驗證 certificate 是否有效的機制,由 CA 提供服務讓瀏覽器查詢,但這會有效能與 privacy issue。

前者比較容易理解,因為熱門網站所使用的 HTTPS certificate 會導致很多瀏覽器跑去 OCSP 服務查詢;後者則是因為 OCSP 服務就會知道哪個 IP 存取哪個網站。

不過這兩個應該都可以用 OCSP stapling 解決才對,也就是 web server 去 OCSP 服務拿有效的簽名 (證明你手上的是有效的),然後在瀏覽器連上來的時候一起送出去,這樣瀏覽器就不用跑去煩 OCSP 服務,而且 OCSP 服務也不知道誰看了什麼網站。

不過跟 CRLs 相比還是不小的負擔就是了,尤其像是 Let's Encrypt 這種等級的量,光是 web server 固定時間去要 OCSP stapling 的簽名 (這又是個數位簽章的動作) 不容易 cache;反過來 CRLs 容易 cache 多了?

另外一方面,CA/Browser 在 2023 年的時候已經投票通過,將 OCSP 列為選擇性項目,而 CRLs 則變成必要項目:「Ballot SC-063 v4: Make OCSP Optional, Require CRLs, and Incentivize Automation

看文章的語氣,應該是先放個風向?尤其故意不提到 OCSP stapling 這點...

最近 Linux Kernel 對 Raspberry Pi 效率的提升

在「NUMA Emulation speeds up Pi 5 (and other improvements)」這邊看到的,最近 Linux kernel 有些新的 patch 對 Raspberry Pi 的效率有不少提升。

其中 NUMA Emulation 這包對於 Raspberry Pi 5 的效能提升頗多:

[I]t can bring a significant performance uplift on Raspberry Pi 5.

照他的說法,Geekbench 6 的提升部分,單核 6% 多核 18%:

In more conrete numbers, testing with Geekbench 6 shows that splitting into four emulated NUMA nodes can uplift the single core score of the benchmark by around 6%, and the multi-core by around 18%.

Jeff Geerling 測試的結果則是 6% & 12%,沒有宣稱那麼多,但仍然是不小的提升。

話說我還在想要不要弄一台 Raspberry Pi 5,目前手上有幾台 1B、一台 3B+ 以及一台 4,除了跑 SmokePing 以外還有什麼值得跑的...

離跟 GIL 說再見更進一步的 Free-threaded CPython

在「Free-threaded CPython is ready to experiment with (quansight.org)」這邊看到 PythonGIL 的進度,從原文「Free-threaded CPython is ready to experiment with!」這邊可以看到有些需要套件一起配合的,像是 NumPy 這邊的「BUG: error Python 3.13 free-threaded RuntimeError: Identity cache already includes the item.」。

看起來用到 C 的實作 (大多數應該是為了加速,或是需要底層的 syscall) 都會需要注意一下。

另外值得一提的是目前拔掉 GIL 的版本在 single threading 的情況下會比標準版的 Python 3 慢很多,會需要後續再改進,所以一開始的版本就算穩定下來也可能沒有經濟上的效益,參考 id=40949628 這邊提到的:

Right now there is a significant single-threaded performance cost. Somewhere from 30-50%. Part of what my colleague Ken Jin and others are working on is getting back some of that lost performance by applying some optimizations. Expect single-threaded performance to improve for Python 3.14 next year.

另外有看到一些有趣的討論,像是為什麼不 bump 版本號碼到 Python 4 (因為語法沒有大改變?)。

lite-youtube-embed

繼續清 tab,在「YouTube embeds are heavy and it’s fixable (frontendmasters.com)」這邊看到的是提出改善 YouTube 的外嵌功能 (embed),因為 loading 太肥了。原文在「YouTube Embeds are Bananas Heavy and it’s Fixable」,裡面提到一個只有 YouTube 的 embed (iframe) 頁面就抓了 1.3MB 的資料:

On a page with literally nothing at all on it other than a YouTube Embed, we’re looking at:

32 requests
1.3 MB of data transfer
2.76s to load the page on my current WiFi connection

而「One YouTube Embed weighs almost 1.2 MB」這邊更提到了這邊的 resource 會線性疊加不會共用的:

The weight also grows linearly with every embed—resources are not shared: two embeds weigh 2.4 MB; three embeds weigh 3.6 MB (you get the idea).

測了一下 https://home.gslin.org/tmp/ytembed.html 這個,是 1.2MB transferred:

如果放兩個一樣的影片,也就是 https://home.gslin.org/tmp/ytembed2.html 的話,變成 2.4MB transferred:

所以不共用的部分的確超大,懷疑 iframe 之間不共用資源是不是跟 cache partition 的實作有關:「Google Chrome 要藉由拆開 HTTP Cache 提昇隱私」。

Anyway,所以作者提案用 lite-youtube-embed 這個套件改善:

Provide videos with a supercharged focus on visual performance. This custom element renders just like the real thing but approximately 224× faster.

不過這種事情你想得到,Google 也一定想得到,全篇只講 lite-youtube-embed 的好處一定哪邊有問題。

所以翻一下 Hacker News 上,在 id=40897582 這邊就有人提到缺點了,很明顯 lite-youtube-embed 的載入速度比較慢:

The author says they don't believe that a lighter version has been shown to reduce engagement.

I, on the other hand, fully believe that.

The recommended lite-youtube-embed project page has a demo of both lite and regular players [0], and the lite version takes noticeably longer to start playing the video.

Every additional millisecond of load time will reduce engagement, and here the difference is more on the order of hundreds of milliseconds or more.

[0] https://paulirish.github.io/lite-youtube-embed/

yeah,這樣就合理了。

即使 embed 吃超多資源,但因為 YouTube 是影音網站,主要的流量還是影音的部分,利用這個方法增加載入速度,在成本結構上面可以接受,而且還可以拿到更多瀏覽資料?

但對於網站端以及使用者端就不是什麼愉快的事情,所以網站端要不要用這個套件就是看各自的取捨了。

C++ 實作高頻交易程式的技巧

看到「C++ patterns for low-latency applications including high-frequency trading (arxiv.org)」這篇,原文是 2023 年九月上傳到 arXiv 的 paper:「C++ Design Patterns for Low-latency Applications Including High-frequency Trading」。

有點 LLM 的文字感,在 Hacker News 上有人有提到這點,另外有一些圖表的錯誤,像是這兩份資料可以發現對不上,label 有標錯:

主要還是看列出的方法在自家專案上嘗試,不能直接把他們的數據拿來參考,在自家專案還是得在自家專案上面 benchmark 才知道有多少效益。

不過裡面提到蠻多有趣的作法,很多都是「知道」但沒有放在心上的...

OpenBSD 提供了關閉 Nagle's algorithm 的 sysctl 選項

看到「Demise of Nagle's algorithm (RFC 896 - Congestion Control) predicted via sysctl」這篇,OpenBSD 提供 sysctl 的選項直接關閉 Nagle's algorithm

The below changeset introduces sysctl net.inet.tcp.nodelay, which if set to 1 will simply cause TCP_NODELAY to be set on all TCP sockets.

不過裡面提到了 John Nagle 在 2015 年的時候有在 Hacker News 上面回覆 (id=10608356),大概介紹了一下背景,以及提出了他的看法:

That still irks me. The real problem is not tinygram prevention. It's ACK delays, and that stupid fixed timer. They both went into TCP around the same time, but independently. I did tinygram prevention (the Nagle algorithm) and Berkeley did delayed ACKs, both in the early 1980s. The combination of the two is awful. Unfortunately by the time I found about delayed ACKs, I had changed jobs, was out of networking, and doing a product for Autodesk on non-networked PCs.

然後翻了一下 John Nagle 的 Hacker News 帳號,看起來還蠻活躍的?常常 comment 一些東西...

Nagle's algorithm + TCP delayed acknowledgment

Hacker News 上看到「It's always TCP_NODELAY (brooker.co.za)」,在講常遇到的 TCP 效能問題,原文在「It’s always TCP_NODELAY. Every damn time.」這邊。

這邊提到了兩個 TCP 上的演算法,Nagle's algorithm 是把小封包積著,等到收到 ack 後再集中丟出去,這樣可以降低 TCP overhead;而 TCP delayed acknowledgment 則是在收到封包後要傳回的 ack 累積起來縮成一個 ack 丟出去 (或是等到 timeout),也是為了降低 TCP overhead。

可以看到這兩者的邏輯上雖然都是想要降低 TCP overhead,但方法剛好會打架。而且這兩個在 Linux 下系統預設都會啟用,所以成立條件不算少見,只要發送方的每個封包都比較小就容易觸發 (大封包的情況則是因為把 buffer 塞滿後就會丟出去,所以就不會延遲)。

這時候遇到 application protocol 很吃 latency 的設計時 (像是 ping-pong 類型的溝通),就容易撞到效能問題。

也因為很常見,所以 Hacker News 上也有好幾個人都有提到他們在工作上解過好幾次。

技術上的解決方案是關掉其中一個就可以了,但可以看到通常都是關掉 Nagle's algorithm (也就是設定 TCP_NODELAY),一方面因為大多數伺服器端的軟體都提供這個選項,改起來比較方便 (因為會被回報);另外一方面是是「趕快把封包送出去」會比「趕快收到 ack」來的有效率...

算是因為網路發展後產生的問題,以前只有 64kbps 專線 (8KB/sec) 的年代會斤斤計較這些東西:一個 IPv4 header 要 20 bytes,TCP header 也要 20 bytes,只傳 1 byte 的資料的確很傷頻寬。

但現在網路環境不太一樣了,尤其是文章裡面提到的環境通常是機房,1Gbps 與 10Gbps 算是常態,遇到 bandwidth 不會吃滿,但很需要 rps (request per second) 數量時,拿之前的演算法就容易中獎了...

關於 Hacker News 上面,「假設 CPU 速度上限只有現在的 1/20」的討論

算是 Hacker News 上面的閒聊文章,如果 CPU 只有現在 1/20 的速度的話,軟體開發會變成什麼樣子:「How might software development have unfolded if CPU speeds were 20x slower?」。

其實也沒那麼難想像,如果是拿 CPU 頻率來算 1/20 的話,上限大約是 250~300MHz?這大概是 Pentium II 的年代,1997 年的 CPU,當年主流的作業系統應該是 Windows 95...

裡面有很多討論,不過在 id=39977430 這邊看到:

No electron apps.

幹。

Reddit 當初對 Google 搜尋引擎的客製化設計

Hacker News 上看到的討論,裡面剛好有 Reddit 第一個雇用的工程師,Jeremy Edberg 的留言:「Reddit is taking over Google (businessinsider.com)」。

id=40068381 這邊提到了不少東西,首先是把 title 放進 url 裡面的作法:

To this day, my most public contribution to reddit is that I wrote the code to put the title of the post in the URL. That was done specifically for SEO purposes.

這個在 Google Webmasters (現在叫做 Google Search Console) 也針對 Reddit 處理,將速率強制設為 Custom,不讓 Reddit 的人改:

It was pretty much the only SEO optimization we ever did (along with a few DOM changes), because shortly after that, Google basically dedicated engineering effort specifically to crawling reddit. So much so that we lost the "crawl rate" button in our SEO admin page on Google, it was just set to "Custom".

後續還要針對 Google 的抓取在 load balancer 上把流量拆開處理,不然 crawling pattern 與一般使用情境很不一樣,會造成 cache 的效率極度低落:

I had to stand up a fleet of app servers and caches and databases, and change the load balancers so that Google basically had their own infrastructure (although we would shunt all crawlers there). Crawler traffic was very different than regular traffic -- it looked at pages more than two days old, something humans rarely did at the time. It would blow out every cache (memory, database, disk, etc.). So we put them on their own infra to keep them from killing the rest of the site.

這些算是頗有趣的經驗?

Java 21 的 ZGC 在 Netflix 的效果

Hacker News 上看到連結「Bending pause times to your will with Generational ZGC (netflixtechblog.com)」,發現這篇還沒整理:「Bending pause times to your will with Generational ZGC」,裡面講的東西都有圖有數字 (i.e. Y 軸),作者是 Danny Thomas

在這之前他們就已經知道 GC pause 是延遲的重要來源,會導致 timeout & retry:

In both our GRPC and DGS Framework services, GC pauses are a significant source of tail latencies.

That’s particularly true of our GRPC clients and servers, where request cancellations due to timeouts interact with reliability features such as retries, hedging and fallbacks.

第一張圖拉出來的資料是 error rate,白色是上個禮拜的資料,紫色是這個禮拜的資料,而從 G1GC 切到 ZGC 是在 2023/11/16 發生的:

可以看到很明顯的 error rate 改變:尖峰從 2k 下降到大約 0.3k,大約是原來的 1/6 到 1/7 的下降。

第二張圖是 GC 的時間:

可以看到 G1GC 還是偶而會撞到 2 秒,發生時平均值也都還是會 >100ms,切到 ZGC 後直接降到個位數 ms 等級了。

第三張圖是 memory overhead 的部分:

從圖上可以看到上週與本週的對比,導入 ZGC 後記憶體的使用量下降了,不過文裡面倒是沒解釋這點,反而提到 ZGC 比起 G1GC 有個固定的 3% overhead:

ZGC has a fixed overhead 3% of the heap size, requiring more native memory than G1. Except in a couple of cases, there’s been no need to lower the maximum heap size to allow for more headroom, and those were services with greater than average native memory needs.

第四張則是 Huge Pages 的差異,這邊要注意這張圖的 Y 軸不是從 0 計算:

可以看到在開 Huge Pages 後,在 RPS (request per second) 不變的情況下 CPU 使用率是有下降的,大約從 50% 降到 45% 左右,不過這張圖的時間跨度有點少,應該是要拉長一點的圖... 不過既然被提出來了,就假設 Netflix 內看起來應該是有這個趨勢,只是抓圖的時候懶了點?

整體算是大成功?