歌曲與專輯名稱的各種變化

Hacker News 上看到「Horrible edge cases to consider when dealing with music (2022) (dustri.org)」這篇,講音樂產業各種奇怪種奇怪的 case,2022 年的原文在這邊:「Horrible edge cases to consider when dealing with music」,裡面有蠻大的篇幅都在講名稱的問題...。

這讓我想到這則推:

基本上會遇到各種 escaping 與 UTF-8 的處理,另外文章裡面提到會遇到超長名稱,也就是 VARCHAR(255) 的剋星... 不確定之前在 K 社大量取得授權的時候有沒有遇到這張 1999 年的專輯 (下面這是一張專輯的名字):

When the Pawn Hits the Conflicts He Thinks Like a King What He Knows Throws the Blows When He Goes to the Fight and He'll Win the Whole Thing 'Fore He Enters the Ring There's No Body to Batter When Your Mind Is Your Might So When You Go Solo, You Hold Your Own Hand and Remember That Depth Is the Greatest of Heights and If You Know Where You Stand, Then You Know Where to Land and If You Fall It Won't Matter, Cuz You'll Know That You're Right.

其他文章裡面提到的應該都算是見怪不怪的情境,像是單曲七個小時... 這種在 server side 還拼的過去,但在行動平台上面比較苦命,直接把整曲都放進 memory 裡面的話有可能會炸。

320kbps 七個小時差不多是 1GB,如果沒注意這點,直接處理 DRM 的話瞬間就會吃到 2GB RAM;如果拉到 CD quality 的資料量就更明顯了。

然後你會發現,把音樂創作人的任何資料都當作 untrusted input 的態度來設計系統 (但你不能 reject),問題通常就不會太大 XD

修好 Trac 1.6 上的 SlackIntegration

續上篇「修好 Trac 1.6 上的 TracSubtickets」提到的,反正 Trac 這個 community 的東西如果爛掉的話,自己修會比較快...

SlackIntegration 從字面上的意思就知道,是把 Trac 這邊的更新同步到 Slack 上的工具。

這包主要的問題是 Python 2 語法,所以在修的過程中間就不斷的在想起「啊,這是當初 Python 3 的 break-BC 改動」。

從「Comparing 72bec82..master · gslin/trac-slack-plugin」這邊可以可以到修正的東西,主要修正的都是跟 unicode 有關的程式碼。

一塊是 2to3 修正的,把 u'...' 這種字串直接變成 '...',不需要額外指定,另外是 unicode(...) 變成 str(...)

另外一個也還是 unicode 相關的,但因為是邏輯上的部分,2to3 沒有抓出來的,是 encode('utf-8') 的部分看起來就用不到了,這在 Python 3 裡面 requests 會自動處理掉,只要丟標準的 string (unicode string) 進去就可以了。

這樣又弄好一個套件了...

提議 OpenJDK 的程式碼 UTF-8 化

Hacker News 上看到提議把 OpenJDK 的程式碼 UTF-8 化:「Make JDK source code UTF-8 (openjdk.org)」,原始的 jira ticket 在「Make JDK source code UTF-8」這邊。

主要是現在的 source code 沒有統一標準:

Currently, the source code in the JDK is in an ill-defined encoding. There is no official declaration of the encoding used. It is "mostly ASCII", but the relatively few non-ASCII characters used are not well-defined. In many cases, it is latin-1, but I am pretty certain other encodings are used for e.g. Asian translations.

而 mailing list 上看起來還是有想要維持 ASCII 的討論:「Making the source code utf-8」,不過他提出來的理由我覺得不太行,在 console 跑 vi 或是 emacs 我覺得不太是個好理由...

疾管署的 COVID-19 每日送檢數的 Open Data

記者會上有提到現在疾管署的網站上有公開每日送檢數的資料,花了些時間找,在「台灣COVID-19冠狀病毒檢測每日送驗數」這邊可以看到,網站提供的 preview 的界面沒辦法看到最新的資料,但下載後可以看到檔案格式是 UTF-8 的 CSV 檔,應該還算能處理...

找到這個資料花了一些功夫 (因為用 DuckDuckGoGoogle 都沒直接找到),後來是靠這樣的步驟找到的:

本來點選熱門資料那邊的「COVID-19台灣最新病例、檢驗統計」結果發現只有一筆資料,而且看起來最後更新時間是 2020/04/24,所以得往其他地方翻。

首先點了上面的「最新消息」發現是個系統公告區,不是我要的,接下來才又找到正確的路線...

這時候就會看到最前面提到的「台灣COVID-19冠狀病毒檢測每日送驗數」了。

然後 data.cdc.gov.tw 這個網站看起來是放在 Microsoft Azure 的日本區?

Ptt 公告使用安全連線

Ptt 官方公告,建議使用安全連線:「[公告] 請使用安全的連線方式連線本站」。

目前 Ptt 有三種方式可以連線,第一種是 Telnet,這是最古老,支援度最廣泛,但沒有加密的協定。

第二種是 SSH,算是蠻早就支援的安全協定 (至少是 2006,依照「[問題] SSH連接是否變換方式了﹖」這篇),屬於 Trust on first use 的方式,不過在有 DNSSEC 的情況下可以搭配 SSHFP record 避免第一次連線的信任問題。

最後一種登入方式也是安全協定,透過 2011 年定義出來的 WebSocket 連線,這個方法在 Let's Encrypt 盛行後可以透過瀏覽器內的 CA 驗證連線的安全性。

可以理解 SSH 吃的資源比較多,不過在 Linux command line 下好像還沒有什麼比較堪用的 WebSocket 指令可以連線... 而且我記得 Ptt 的 WebSockets 還是使用 BIG5 吧?當時在寫小工具的時候發現的...

新出的 RFC 8259:The JavaScript Object Notation (JSON) Data Interchange Format

JSON 的規格書又被更新了 XD

在「The Last JSON Spec」這邊,Tim Bray 寫了這篇關於新的 RFC 8259 跟之前的差異,以及大家對於雙重標準的顧慮。

最大的差異在於,在 RFC 8259 規定了「如果 JSON 被用在非封閉的系統交換資料,必須使用 UTF-8」:

8259 con­tains one new sen­tence: “JSON text ex­changed be­tween sys­tems that are not part of a closed ecosys­tem MUST be en­cod­ed us­ing UTF-8 [RFC3629].” Giv­en that, by 2017, an at­tempt to ex­change JSON en­cod­ed in any­thing but UTF-8 would be ir­ra­tional, this hard­ly needs say­ing; but its ab­sence felt like an omis­sion.

而關於 ECMA-404 與 RFC 8259 都定義了 JSON 的問題他也說明了,因為很多人花了很多力氣在確保這兩份文件的正確性上,所以應該不會有問題 (i.e. 衝突):

The rea­son 8259 ex­ists is that the ECMAScript gang went and wrote their own ex­treme­ly min­i­mal spec, Stan­dard ECMA-404: The JSON Da­ta In­ter­change Syn­tax, and there was rea­son for con­cern over du­el­ing stan­dard­s. But, af­ter a cer­tain amount of standards-org elephant-gavotte, each of ECMA 404 and RFC 8259 nor­ma­tive­ly ref­er­ences the oth­er and con­tains a com­mit­ment to keep them con­sis­tent in case any er­rors turn up. Which is a good thing, but this text has been re-examined and re-polished so many times that I doubt ei­ther side will ev­er re­vis­it the ter­ri­to­ry, thank good­ness.

另外他也提到了對於不同情境下可以看不同的文件。像是要了解 JSON 的話,可以看當初發明 JSON 的 Doug Crockford 所設立的網站 (在「JSON」這邊);而在交換時應該參考 I-JSON (Internet JSON,RFC 7493):

Which spec should you use? · If you want to un­der­stand JSON syn­tax, you still can’t beat Doug Crockford’s orig­i­nal for­mu­la­tion at JSON.org. If you want to use an RFC as foun­da­tion for a REST API or some oth­er In­ter­net pro­to­col, I ac­tu­al­ly don’t rec­om­mend 8259, I rec­om­mend I-JSON, RFC 7493, which de­scribes ex­act­ly the same syn­tax as all the oth­er specs (by ref­er­enc­ing 7159), but ex­plic­it­ly rules out some legal-but-dumbass things you could do that might break your pro­to­col, for ex­am­ple us­ing any­thing but UTF-8 or hav­ing du­pli­cate mem­ber names in your ob­ject­s.

I-JSON 是 JSON 的子集合,比較重要的:

  • (MUST) 使用 UTF-8。
  • (SHOULD NOT) 浮點數的部份,不得超過 IEEE 754-2008 binary64 (double precision) 的範圍。
  • (SHOULD NOT) 整數的部份,不得超過 [-(2**53)+1, (2**53)-1]) 的範圍。
  • (RECOMMEND) 有超過的需求使用字串表示。
  • (MUST NOT) JSON object 內不得有重複的 name。
  • (SHOULD NOT) 最上層的型態不得使用字串,只能使用 object 或是 array。
  • (MUST NOT) 遇到先前沒有定義過的元素不得視為錯誤。(像是新版 API 內會在 object 裡增加元素)
  • (RECOMMEND) 時間使用 ISO 8601 表示 (在 RFC 3339 有提到),英文字的部份全部使用大寫,一定要標上時區,而秒數的 0 一定要加上去 (也就是 00 秒)。
  • (RECOMMEND) 時間長度也建議依照 RFC 3339 處理。
  • (RECOMMEND) Binary 資料用 base64url 傳 (RFC 4648)。

Branchless UTF-8 解碼器

看到「A Branchless UTF-8 Decoder」這篇,先來回憶一下「非常經典的 UTF-8...」這篇,以及裡面提到的 encoding:

因為當初在設計 UTF-8 時就有考慮到,所以 decoding 很容易用 DFA 解決,也就是寫成一堆 if-then-else 的條件。但現代 CPU 因為 out-of-order execution 以及 pipeline 的設計,遇到 random branch 會有很高的效能損失,所以作者就想要試著寫看看 branchless 的版本。

成效其實還好,尤其是 Clang 上說不定在誤差內:

With GCC 6.3.0 on an i7-6700, my decoder is about 20% faster than the DFA decoder in the benchmark. With Clang 3.8.1 it’s just 1% faster.

而後來的更新則是大幅改善,在 Clang 上 DFA 版本比 branchless 的快:

Update: Björn pointed out that his site includes a faster variant of his DFA decoder. It is only 10% slower than the branchless decoder with GCC, and it’s 20% faster than the branchless decoder with Clang. So, in a sense, it’s still faster on average, even on a benchmark that favors a branchless decoder.

所以作者最後也有說這是個嘗試而已 XD:

It’s just a different approach. In practice I’d prefer Björn’s DFA decoder.

MySQL 8.0 對 4 bytes UTF-8 的效能改善

在「MySQL 8.0: When to use utf8mb3 over utf8mb4?」這邊提到了 MySQLutf8 以及 utf8mb4 的故事,以及在 MySQL 8.0 預期的效能提昇:

可以看到 Oracle 的團隊花了不少力氣提昇 utf8mb4 的效能。另外提到了在 5.7 的時候將 row format 的預設值轉成 DYNAMIC

MySQL 5.7 (2015) added some optimizations such as a variable length sort buffer, and also changed InnoDB’s default row format to DYNAMIC. This allows for indexes on VARCHAR(255) with utf8mb4; something that made migrations more difficult prior.

依照「14.11.3 DYNAMIC and COMPRESSED Row Formats」這邊的敘述,看起來 COMPRESSED 也應該支援一樣的特性,不過不確定... (因為通常不會完整 index 整個 VARCHAR(255),只會 index 某個 prefix length):

The COMPRESSED row format uses similar internal details for off-page storage as the DYNAMIC row format, with additional storage and performance considerations from the table and index data being compressed and using smaller page sizes.

將 latin1 的表格轉換成 UTF-8 表格...

Percona 的人寫了一篇「utf8 data on latin1 tables: converting to utf8 without downtime or double encoding」,告訴你怎麼將 latin1 的 TEXT 欄位轉成 UTF-8,文章內有提到利用 BLOB 轉。

不確定同樣方式能不能做在 VARCHAR 上面 (用 BINARY 轉?),但不知道會不會有 UNIQUE + prefix support 的問題?有遇到再來測試看看...

MySQL 的 Unicode 支援程度

MySQL 5.5 之前的版本只支援 Unicode 3.0 (1999 年 9 月發表),但自從 MySQL 5.5 版開始支援 Unicode 5.0 (2006 年 7 月發表),對於常用的 utf8 encoding 就有一些變化要注意...

參考維基百科上對 Unicode 版本的說明:「Unicode#Versions」,以及 MySQL 5.5 的文件:「MySQL :: MySQL 5.5 Reference Manual :: 10.1.10 Unicode Support」。

在 MySQL 5.5 之前,UTF-8 的設計最多吃 3bytes,因為 1byte 有 128 種組合 (7bits),2bytes 有 2048 種組合 (11bits),3bytes 有 65536 種組合 (16bits),共 67712 個空間可以用,但 Unicode 3.0 只用掉 49259 個。

而從 MySQL 5.5 開始支援的 Unicode 5.0 需要 99089 個空間,所以需要用到 4bytes 的版本,也就是增加 4bytes 的 2097152 種組合 (21bits),共 2164864 個空間。

但為了相容性,MySQL 5.5 的 utf8 encoding 還是使用 Unicode 3.0 版本。只有當特別指定 utf8mb4 encoding 時才會用到 Unicode 5.0 版本。使用 utf8mb4 encoding 時,要注意 client 端也要支援,不然會讀不到東西...