使用SIMD指令校验UTF-8
翻看postgresql email list,发现有对SIMD指令应用到PG的讨论,很有价值。记录下来以作分析使用。
从 b80e10638e3开始,有一个用于校验字符串编码的新API,使得我们有更多算法选择。对于UTF-8来说,已证明在解码[1]和校验[2]方面,使用SIMD比标准方法快得多。出于多方面原因,从UTF-8的ascii子集开始是有意义的。首先,ascii在数据库内容中非常普遍,尤其是在批量加载中。其次,ascii可以使用任何x64-64芯片使用简单的SSE2内在函数进行严重,我猜我们可以在编译时检测到,而不会与运行时检测混淆。使用SSE的通用案例比较复杂并且涉及SSE4.2或AVX。
这是我电脑上的一些数字。测试和Heikki的[3]一样,但我添加了一个案例,包含95%的汉字,只是为了展示与混合ascii/多字节案例对比情况。
master:
chinese | mixed | ascii
--------- ------- -------
1081 | 761 | 366
patch:
chinese | mixed | ascii
--------- ------- -------
1103 | 498 | 51
纯ascii情况下的加速效果还是很不错的。
在随附的POC中,仅有一个形式上可以移植的案例,完整性的以后再用。快速路径内联在pg_utf8_verifystr()中。ascii快速路径可以抽象成一个单独函数,该函数传递一个函数指针用于进行完整的编码验证。这将允许具有严格的ascii子集的其他编码也可以使用它。但对这种抽象进行编码可能有点混乱,并且b80e10638e3已经比PG13有更好性能了。
我还尝试使用DFA进行完整的UTF-8识别,但到目前位置,这只能使性能更糟。如果我在这方面取得成功,我会将其添加到Patch中。
[1] https://woboq.com/blog/utf-8-processing-using-simd.html
[2]https://lemire.me/blog/2020/10/20/ridiculously-fast-unicode-utf-8-validation/
[3]https://www.postgresql.org/message-id/06d45421-61b8-86dd-e765-f1ce527a5a2f@iki.fi
Attachment | Content-Type | Size |
---|---|---|
v1-verify-utf8-sse-ascii.patch | application/x-patch | 2.3 KB |
原文
https://www.postgresql.org/message-id/CAFBsxsEV_SzH+OLyCiyon=iwggSyMh_eF6A3LU2tiWf3Cy2ZQg@mail.gmail.com