弄清楚 >/dev/null 2>&1 與 2>&1 >/dev/null 的差異

以前都是硬背起來的,如果要把所有的輸出都丟到 /dev/null,要用前面的方式才會是對的,但其實在 bash 的 manpage 裡面有提到:

Note that the order of redirections is significant. For example, the command

    ls > dirlist 2>&1

directs both standard output and standard error to the file dirlist, while the command

    ls 2>&1 > dirlist

directs only the standard output to file dirlist, because the standard error was duplicated from the standard output before the standard output was redirected to dirlist.

這是因為照順序跑 dup2() 的關係 (參考 bash 的 redir.c)。

前者會先把 dirlist 開起來後透過 dup2() 複製到 fd=1,再用一次 dup2() 把 fd=1 複製到 fd=2,達到我們要的效果。

後者則是先把 fd=1 複製到 fd=2 (於是大家都丟到 stdout 了),接下來再把 dirlist 開起來,丟到 fd=1。這樣變成 ls 寫到 stderr 的東西變成到 stdout 了,而本來寫到 stdout 的東西進到 dirlist 這個檔案裡。

剛剛寫 code 時想找一下有沒有官方文件或是 source code 有描述 ordering 或是有定義行為,結果發現 bash 的 manpage 裡面就有提到了...

分散式系統的 clock

前幾天在 Hacker News 上看到「Clocks and Causality – Ordering Events in Distributed Systems (2022) (exhypothesi.com)」這篇,講分散式系統上 clock 的設計,作者也有跑出來在 Hacker News 上面跟大家聊一下 (帳號是 thoughtlede),原文在「Clocks and Causality - Ordering Events in Distributed Systems」這邊。

文章裡面主要講空間是 O(1)Lamport timestamp 與空間是 O(n)Vector clock (這邊的 n 相對於節點數量),以及這兩個對應的擴充版本:

作者會整理這些資料的原因是因為在研究 CRDT 的時候看到演算法中常常會需要處理分散式系統裡面事件的順序,所以花了一些時間整理常見的方式:

Author here. Pleasantly surprised to see the article here.

Some context behind the article. I studied CRDTs for a few months, and noticed that different CRDT designs use logical clocks in different and clever ways. And I haven't seen anyone narrate all those ways of use in one article. My attempt with this article was to dredge up those flavors of logical clocks into one article and give them names for future reference.

(To respond to a couple of other comments, I ignored atomic (and gps-based) clocks in this discussion, as indicated in my footnote 3).

我記得還有一個 Interval Tree Clocks 可以參考 (在「Interval Tree Clocks」這邊講的比較清楚),是針對節點的動態增刪而改善的演算法,但不確定有什麼比較有名的系統有用。

大多數應該都是用 Vector clock,畢竟是在 2007 年的「Dynamo: Amazon’s Highly Available Key-value Store」被發揚光大,而且也算是還不錯的演算法?

Apple M1 的效能與省電原因

Hacker News Daily 上看到 Apple M1 為什麼這麼快又省電的解釋,可以當作一種看法:

可以在 Thread reader 上面讀:「Thread by @ErrataRob on Thread Reader App – Thread Reader App」。

看起來 Apple 在規劃的時候就有考慮 x86 模擬問題,所以在記憶體架構上直接實做了對應的模式,大幅降低了當年 MicrosoftSurface 上遇到的問題:

3/ The biggest hurdle was "memory-ordering", the order in which two CPUs see modifications in memory by each other. It's the biggest problem affecting Microsoft's emulation of x86 on their Arm-based "Surface" laptops.

4/ So Apple simply cheated. They added Intel's memory-ordering to their CPU. When running translated x86 code, they switch the mode of the CPU to conform to Intel's memory ordering.

另外一個比較有趣的架構是,Apple M1 上面的兩個 core 有不同的架構,一顆對效能最佳化,另外一顆對效率最佳化:

13/ Apple's strategy is to use two processors: one designed to run fast above 3 GHz, and the other to run slow below 2 GHz. Apple calls this their "performance" and "efficiency" processors. Each optimized to be their best at their goal.

在 wikipedia 上的介紹也有提到這兩個 core 的不同,像是 L1 cache 的差異 (128KB 與 192KB),以及功耗的差異:

The M1 has four high-performance "Firestorm" and four energy-efficient "Icestorm" cores, providing a configuration similar to ARM big.LITTLE and Intel's Lakefield processors. This combination allows power-use optimizations not possible with Apple–Intel architecture devices. Apple claims the energy-efficient cores use one tenth the power of the high-performance ones. The high-performance cores have 192 KB of instruction cache and 128 KB of data cache and share a 12 MB L2 cache; the energy-efficient cores have a 128 KB instruction cache, 64 KB data cache, and a shared 4 MB L2 cache. The Icestorm "E cluster" has a frequency of 0.6–2.064 GHz and a maximum power consumption of 1.3 W. The Firestorm "P cluster" has a frequency of 0.6–3.204 GHz and a maximum power consumption of 13.8 W.

再加上其他架構上的改善 (像是針對 JavaScript 的指令集、L1 的提昇,以及用 TSMC 最新製程),累積起來就變成把 Intel 版本壓在地上磨蹭的結果了...