calloc() 與 malloc() 的差異

前陣子在 Hacker News Daily 上看到的,原文是 2016 的文章:「Why does calloc exist?」,裡面講的東西包括了 implementation dependent 的項目,所以要注意一下他的結論未必適用於所有的平台與情境。

malloc()calloc() 的用法是這樣,其中 calloc() 會申請 countsize 的空間:

void* buffer1 = malloc(size);
void* buffer2 = calloc(count, size);

第一個差異是,count * size 可能會 overflow (而 integer overflow 在 C 裡面是 undefined behavior),這點除非你在乘法時有檢查,不然大多數的行為都還是會生一個值出來。

calloc() 則是會幫你檢查,如果會發生 overflow 的時候就不會真的去要一塊記憶體用。

第二個差異是 calloc() 保證會將內容都設定為 0,這點在 POSIX 的標準裡面是這樣寫的:

The calloc() function shall allocate unused space for an array of nelem elements each of whose size in bytes is elsize. The space shall be initialized to all bits 0.

但作者就發現 malloc() + memset() + free() 還是比 calloc() + free() 慢很多:

~$ gcc calloc-1GiB-demo.c -o calloc-1GiB-demo
~$ ./calloc-1GiB-demo
calloc+free 1 GiB: 3.44 ms
malloc+memset+free 1 GiB: 365.00 ms

研究發現是 calloc() 用了 copy-on-write 的技巧,先把所有的 page 都指到同一塊完全被塞 0 的記憶體,只有在真的寫到該段記憶體時,系統才會要一塊空間來用:

Instead, it fakes it, using virtual memory: it takes a single 4 KiB page of memory that is already full of zeros (which it keeps around for just this purpose), and maps 1 GiB / 4 KiB = 262144 copy-on-write copies of it into our process's address space. So the first time we actually write to each of those 262144 pages, then at that point the kernel has to go and find a real page of RAM, write zeros to it, and then quickly swap it in place of the "virtual" page that was there before. But this happens lazily, on a page-by-page basis.

但畢竟這是 implementation dependent,看看有個印象就好。

用 reprepro 建立 APT repository

在「用 fpm 這個工具包 .deb 安裝」這篇題到了 fpm,另外在同一篇文章裡面 (「Using Cloudflare R2 as an apt/yum repository」這篇) 也有提到要怎麼生出一個有簽名過的 APT repository,裡面就提到了 reprepro 這個工具。

Debian Wiki 上面的「SetupWithReprepro」就有一步一步告訴你設定的方式,另外 Wikimedia 的技術 wiki 上也有提到常用的操作:「Reprepro」。

然後可以丟到很多不同的地方,最常見的 apache 或是 nginx 外,S3 或是其他可以吐 HTTP/HTTPS 的 object storage 服務都可以。

也是先記錄起來,等要用的時候可以回來 blog 上翻到...

在 Ubuntu (Xfce) 上改用 Albert Launcher

在噗浪上的這篇看到的工具,讓我想起來之前有想要在 Ubuntu + Xfce 上找類似的工具:

macOS 上我最常用的就是計算機與匯率換算,另外就是開應用程式。

但是因為沒辦法直接用 super key 啟動 (也稱作 meta key,或是大家更熟悉的微軟鍵),所以得迂迴設定,先透過 xcape 把左邊的 super key 對應到 Ctrl-Esc 上:

xcape -e 'Super_L=Control_L|Escape'

然後把本來的 Ctrl-Esc 拔掉:

然後這時候用 super key 時就會改抓到 Ctrl-Esc 了:

接下來就可以勾選 extensions 了,這邊勾了幾個:

然後 Python 這邊把 Currency convert 的部份勾起來:

用法是 1 usd to twd 這樣的句子:

這兩天用起來還不錯,之後遇到問題再來調整...

Netflix 單機 800Gbps 伺服器所使用的最佳化技巧

Hacker News 上看到 Netflix 的人丟出來的投影片,試著了解 Netflix 的 Open Connect Appliances 裡與 FreeBSD 相關的最佳化技巧對於效能的影響:「The “other” FreeBSD optimizations used by Netflix to serve video at 800Gb/s from a single server」。

看起來這邊的分析是先基於 400Gbps 的版本,可以跑到 375Gbps (53% CPU),接著在上面拔掉各種最佳化的設定,看看會掉多少流量。這邊可以參考先前在「Netflix 在單機服務 400Gbps 的影音流量」提到的資料。

投影片上的第一章是 sendfile 與 kTLS 相關的最佳化,這邊可以看出來都是重要的項目,隨便關掉一個就會掉很多 capacity:

  • Disable kTLS (and async sendfile) + nginx aio:40Gbps (100% CPU)
  • Disable kTLS (and async sendfile) + nginx thread pools:90Gbps (90% CPU)
  • Disable sendfile (but use kTLS):75Gbps (80% CPU)
  • Disable sendfile (but use NIC kTLS):95Gbps (80% CPU)
  • Enable Sendfile & kTLS, but disable ISA-L crypto:180Gbps (80% CPU)
  • Enable Sendfile & kTLS:240Gbps (80% CPU)

第二章是 virtual memory,UMA VM Page Cache 這邊看起來最明顯,SF_NOCACHE 也是個重要的項目:

  • Disable UMA VM Page Cache:60Gbps (95% CPU)
  • Disable VM Batch Queues:280Gbps (95% CPU)
  • Disable SF_NOCACHE:120Gbps (55% CPU)

另外第二章特別提到了一個之前沒有用到的 optimization,是把 arm64 上面的 4KB Pages 變成 16KB Pages,這帶動了些許的效能提昇,並且降低了 CPU 使用率:

345Gb/s @ 80% CPU -> 368Gb/s @ 66% CPU

第三章是 network stack,看起來 TSO 帶來的效益也是很高:

  • Disable TCP Large Receive Offload:330Gbps (65% CPU)
  • Disable RSS accelerated LRO:365Gbps (70% CPU)
  • TSO Disabled:180Gbps (85% CPU)
  • Disable TSO and LRO:170Gbps (85% CPU)

最後面則是有提到從 400Gbps 到 800Gbps 還多做了那些事情,最後是達到 731Gbps。

用的機器是 Dell PowerEdge R7525,這是一台 2U 的機器啊...

FreeBSD 的 Firecracker 支援

Colin PercivalFreeBSD 能夠支援 Firecrack:「Announcing the FreeBSD/Firecracker platform」,成為 LinuxOSv 以外的第三個支援的作業系統。對應的 patch 在「amd64: Add FIRECRACKER kernel configuration」這邊可以看到。

接下來是反過來,要送一些 patch 進去 Firecracker,讓他支援 FreeBSD:

Now that FreeBSD supported Firecracker, there was one more thing to do: Make Firecracker support FreeBSD.

看起來是基於之前在 2020 年的 patch (但當時沒被整進去) 再修改:

Alejandro Jimenez contributed patches two years ago, but they were never merged. Some of his code ended up in the linux-loader project (which Firecracker uses); but I spent a few weeks digging through his thousand lines of changes to figure out which went into linux-loader, which still applied cleanly to Firecracker, and which I had to rewrite from scratch — a task made more difficult by the fact that Firecracker is written in Rust, and I had never used Rust before! Nevertheless, I was eventually successful, and opened a PR with updated patches which I hope to see merged into mainline Firecracker in the upcoming weeks.

看起來兩邊都有 patch 要做才能支援,目前看起來 Firecracker 這邊沒動作了,大概是沒什麼動力...

VirtualBox 7.0.0 出了

LWN 看到 VirtualBox 7.0.0 出了:「VirtualBox 7.0.0 released」,其中 Changelog 可以在「Changelog-7.0」這邊翻到。

Ubuntu 下的更新還算方便,先把 VM 都關掉,移除 virtualbox-6.1 後再裝 virtualbox-7.0,然後把 VM 開起來看看有沒有什麼問題。

在 Changelog 裡面看到這個,這些 3D support 不知道有支援到什麼程度:

Devices: Implemented new 3D support based on DirectX 11 (and DXVK on non Windows hosts)

我把 Enable 3D Acceleration 的選項打開後變成只能跑 1600x1200,本來 1920x1200 不能跑,所以只好又關掉...

另外是支援了 virtual TPM 可以掛進去:

Devices: Added virtual TPM 1.2 and 2.0 devices

然後以前 USB 裝置的支援是 proprietary software,現在放到 open source 版本裡面了:

Devices: The EHCI and XHCI USB controller devices are now part of the open source base package

目前用起來沒什麼大問題,繼續觀察看看。

Linux 無線網路的 RCE 洞

Hacker News 首頁上看到 Linux 無線網路的 RCE 漏洞:「Some remotely exploitable kernel WiFi vulnerabilities」,mailing list 的信件是這邊:「[oss-security] Various Linux Kernel WLAN security issues (RCE/DOS) found」。

裡面題到了五個漏洞,其中屬於 RCE 的是這三個:

  • CVE-2022-41674: fix u8 overflow in cfg80211_update_notlisted_nontrans (max 256 byte overwrite) (RCE)
  • CVE-2022-42719: wifi: mac80211: fix MBSSID parsing use-after-free use after free condition (RCE)
  • CVE-2022-42720: wifi: cfg80211: fix BSS refcounting bugs ref counting use-after-free possibilities (RCE)

第一個只寫「An issue was discovered in the Linux kernel through 5.19.11.」,但討論上看到說應該是 5.1+,第二個在 CVE 裡面有提到是 5.2+,第三個是 5.1+。然後已經有看到 PoC code 了...

對於用 Linux 筆電的人得等各家 distribution 緊急出更新;但有些無線網路設備不知道怎麼辦...

Canonical 推出 Ubuntu Pro

Canonical 推出了 Ubuntu Pro,個人用戶以及小型商業用戶可以免費安裝在五台機器上使用:「Canonical launches free personal Ubuntu Pro subscriptions for up to five machines」。

這次是 public beta,這代表進到正式版本的時候也許還會有變化:

Ubuntu Pro, the expanded security maintenance and compliance subscription, is now offered in public beta for data centres and workstations.

這次推出的 Ubuntu Pro 看起來包括了 ESM (但這邊沒有提到 ESM,而是提到了十年的安全更新);除了 ESM 以外,包括了更多 package 的安全更新,一併提供十年:

Ubuntu Pro (currently in public beta) expands our famous ten-year security coverage to an additional 23,000 packages beyond the main operating system.

Including Ansible, Apache Tomcat, Apache Zookeeper, Docker, Drupal, Nagios, Node.js, phpMyAdmin, Puppet, PowerDNS, Python 2, Redis, Rust, WordPress, and many more...

不過看起來的確就是將 ESM 擴大,這點在 Ubuntu Pro 的價錢的頁面上「Ubuntu Pro | plans and pricing」可以看到有提到 ESM。

但要注意 14.04 雖然有 ESM (照時程表算的話會支援到 2024 年),卻不在這次 Ubuntu Pro 提供的範圍,這次推出的 Ubuntu Pro 是 16.04 以及之後的版本才有:

Ubuntu Pro is available for every Ubuntu LTS from 16.04 LTS. It is already in production for large-scale customers offering global services.

然後本來的 Ubuntu Advantage for Infrastructure 這條產品線改名為 Ubuntu Pro (Infra-only):

Ubuntu Advantage for Infrastructure is now rebranded to Ubuntu Pro (Infra-only). The features and price have not changed.

目前手上沒有 16.04 的機器,等明年 2023 看看 18.04 的機器有沒有換到 20.04/22.04,如果沒有的話也許可以來玩看看...

Apple M1 上跑 Linux 的 GPU driver 會動了

Hacker News Daily 上看到「Native Linux GPU Driver for Apple M1 (twitter.com/linaasahi)」這個,講 Apple M1 上有 Linux GPU driver 可以用了,原文是 Twitter 上的推:

不過從 YouTube 的影片上可以看到就只是「會動」,還有不少 rendering bug,可以看到有時候會破格,但畢竟是開始支援了,後續如果有修到穩定的話,直接的好處應該就是把瀏覽器的 rendering 丟給 GPU 處理,就像 macOS 或是 Windows 上的情況。

月份傳回值 0 表示一月的考古

Hacker News 上看到「History of Zero-Based Months? (jefftk.com)」這篇,在考古為什麼常常看到 function 在傳回「月份」時是以 0 表示一月。從這篇提到的「Why is day of the month 1-indexed but the month is 0-indexed in C? (twitter.com/hillelogram)」則是 2020 年的討論。

在討論裡面有提到 hillelogram 的 tweet,裡面有個看起來算合理的考古過程...

試著用 Thread Reader 產生單頁 (讀起來會比較好讀),但不知道為什麼一直失敗,結果往 Internet Archive 翻資料,倒是有 2020 年當初生成出來的版本

另外還是列出原來第一則 tweet:

作者在研究這個題目的時候,馬上可以想到的是 C 語言裡面的月份就是 0-indexed,而其他程式語言都很有可能會是因為 C 語言的關係一路把這個特性繼承下去:

直接跳到最後面作者的猜測,他覺得可能是為了讓後續使用起來更方便的關係。

其他的欄位大多都是透過類似 sprintf("%d") 的方式直接輸出數字,所以用 1-indexed 讓人直接讀,而月份則會透過 array 來轉字串,所以用 0-indexes 讓程式轉:

So that's my best guess: the programmers were working with constrained resources and could optimize `asctime` tricky pointer arithmetic on the month and day-of-week, so made them 0-indexed. Day-of-month is just for displaying to the user, so is 1-indexed.

沒辦法確定,但就是一種猜測,看起來還蠻... 合理... 的?