Slide 1

Slide 1 text

PHP 8.3のmbstring の進化を見てください - コントリビューターとしてのかかわり - PHP 8.3のmbstring の進化を見てください

Slide 2

Slide 2 text

自己紹介 てきめん ● https://tekitoh-memdhoi.info ● X(twitter): @youkidearitai ● https://github.com/youkidearit ai ● サイボウズ株式会社の契約社員 – コントリビュートしまくったら入 社した ● オレはオレ オレ

Slide 3

Slide 3 text

アジェンダ ● PHP 8.3のmbstringをリアルタイムで見てました ● GitHubでContributorフラグをもらえました ● コントリビュートのお手伝いができるようになりました ● php-src上で誰に何をお願いすればいいのかわかっ てきました

Slide 4

Slide 4 text

このスライドで出てくるみなさん ● @illuuu1994 Ilija Toviloさん – Coreが強い、Dmitry(@dstogov)さんともやり取りしてる印象 ● @Girgias George Peter Banyardさん – Coreからextまで広くコントリビュートしてくれてる、docもメンテしてくれてる ● @alexdowad Alex Dowadさん – mbstringでお世話になってる ● @nielsdos Niels Dosscheさん – Coreも強い

Slide 5

Slide 5 text

このスライドで出てくるみなさん ● @youkidearitai てきめんさん – 私てきめん、mbstringとか見てる ● @pakutoma ぱくとまさん – 後に同僚になる、コントリビュートに協力した ● @SakiTakamachi さきちさん – コントリビュートに協力した ● @mumumuさん – docのコントリビューター。最近のPHPのドキュメントが早いのはこの方のおかげ

Slide 6

Slide 6 text

皆さんは覚えてますか ● 非公式 PHP 8.1 mbstringアップグレードガイド – https://tekitoh-memdhoi.info/views/864 – 皆さんのお陰でかなりの反響をいただき、ありがたい ● これをAlex Dowadさんに見せたところ、FYA(For Your Action)をもらうようになった – 2022年の12月から。まだ8.3というバージョン名が付く前 ● ていうか、世間ではPHP 8.2がリリースされたっていうタイミング

Slide 7

Slide 7 text

PHP 8.3のmbstringの面倒を見てました ● PHP 8.3のmbstringの面倒を見てました ● 2022年12月から始まりました – 2023年7月のFeature Freezeを見届けました

Slide 8

Slide 8 text

何があったかリスト ● Major overhaul of mbstring (part 27) #10048 ● Major overhaul of mbstring (part 28) #10099 ● Performance optimization for mb_stripos an d mitigation for GH-9613 #10107 ● Allow 'h' and 'k' flags to be combined for mb_ convert_kana #10178

Slide 9

Slide 9 text

何があったかリスト ● Performance optimizations for mb_strlen and encodi ng conversion of SJIS, UHC, CP936, BIG5 text #10211 ● Fix entries in SJIS multi-byte character length tables for bytes which do not start any valid 2-byte characte r #10230 ● Update SJIS-mac mappings to use Unicode codepoi nts which were added after Unicode 1.0 #10264

Slide 10

Slide 10 text

何があったかリスト ● More performance increases for mbstring fun ctions on UTF-8 text ● Tweak up SIMD-accelerated version of mb_check_encoding for more speed ● Major overhaul of mbstring (part 30)

Slide 11

Slide 11 text

何があったかリスト ● More performance increases for mbstring functions on UTF-8 text ● Tweak up SIMD-accelerated version of mb_check_encoding for more speed ● Major overhaul of mbstring (part 30) ● mb_scrub does not attempt to scrub known-valid UT F-8 strings

Slide 12

Slide 12 text

Tweak up SIMD-accelerated version of mb_check_encoding for more speed #10360 ● UTF-8をSIMDでバリデーションするというプルリクエスト ● ここでこれの存在を知る Validating UTF-8 In Less Than One Instruction Per Byte – SIMDを利用してUTF-8のバリデーションを速くするという論文、すごいね – 日本語だと https://qiita.com/saka1_p/items/9719d71e702aed92a07c が 詳しい ● 論文の著者の方によるリファレンス実装(JSONのパースができる) https://github.com/simdjson/simdjson

Slide 13

Slide 13 text

SIMDとは ● 1つの命令で複数のデータに対して並列に演算できる – ベクトルとして扱うため、ベクトル演算なんて言ったりもする – CPUだと1つの命令で1つだけ(スカラー演算) ● その特性からマルチメディアに使われやすい – ゲームプログラミングとか画像・音声処理とか ● 普段は触らないが、コンパイラーによって最適化されるときに使われることも ある ● デメリットとしては、CPUアーキテクチャごとに違うこと

Slide 14

Slide 14 text

UTF-8のおさらい Code Points 1st Byte 2nd byte 3rd byte 4th byte U+0000..U+007F 00..7F U+0080..U+07FF C2..DF 80..BF U+0800..U+0FFF E0 A0..BF 80..BF U+1000..U+CFFF E1..EC 80..BF 80..BF U+D000..U+D7FF ED..EC 80..9F 80..BF U+E000..U+FFFF EE..EF 80..BF 80..BF U+10000..U+3FFFF F0 90..BF 80..BF 80..BF U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF U+100000..U+10FFFF F4 80..BF 80..BF 80..BF

Slide 15

Slide 15 text

UTF-8の特徴(一部分) ● いずれのバイトも0xF4を超えることはない ● 最大4バイト ● 2バイト以上の場合、最初のバイトの上位4ビットは文字のバイト数を示す – 1バイトはASCIIの範囲内(0x00-0x7F) ● 2番めのバイトは0xA0始まりだったり0x9F終わりなどの特徴的な部分が ある ● 3バイト目以降は0x80-0xBFだけ

Slide 16

Slide 16 text

SIMDでUTF-8を扱う上で使うテクニック ● 「ニブル(nibble)」という単位 → バイトの半分の4ビット – 上位ニブル、下位ニブルなどと呼ぶ ● 飽和減算 – PHPでいう、 if ($i < 0) $i = 0; などとして、非0を抽出したりする ● オーバーフローを利用した減算 – 飽和減算の逆(普通の減算ともいえる)で、ピッタリ0のときにテーブル参照させたいとかで使っ たりする – ここで参照する論文では使いませんがこういうのを使ってるテクニックもあります ● バイトシフト – 複数のSIMDレジスタにまたがるときとかに使う ● テーブル参照 – テーブルを引くとか言う

Slide 17

Slide 17 text

SIMDでの「あ」のチェック例(正常系) ● UTF-8では0xE3 0x81 0x82の3バイト ● 0xF4を超えたバイトのチェック → 0xF4を飽和減算 ● 0xE3の上位ニブル → 0xE → 0b1110 = 3byte – テーブルを引き、0b1110のときに3を指定する ● 0xCのときは0b1100となるので2になる ● 0xFのときは0b1111となるので4になる

Slide 18

Slide 18 text

「あ」の例(正常系) ● 2〜3バイト目、0x81 0x82 – テーブルを次のように引き、ベクトルを定義すると、 3 0 0 となる ● 0〜7を1 (ASCII) ● 8〜11を0 ● 12、13を2 ● 14を3 ● 15を4 – 3を1バイト右にずらし1減らす → 3, 2 – 3を2バイト右にずらし2減らす → 3, 2, 1 – 結果、3 2 1という値が得られる、ここに0があったり、順番になってないと不正なUTF-8

Slide 19

Slide 19 text

「あ」の例 ● 長い文字列のとき、例えば16バイト以上のときに前のバイト列を引っ張ってく る必要がある ● 0xEDと0x9Fおよび0xF4と0x8Fのチェックが必要 – 0xF4はU+100000-U+10FFFFの最初のバイトにのみ出てくる ● 2バイト目が0x8Fが最大値 ● 1バイト目の上位ニブルが0xEのときの0xA0、0xEDのときの0x9Fのチェック ● SIMDレジスタがまたがる場合に備えて1バイト右シフト ● これによって、すべてのSIMDレジスタが非0であればvalidなUTF-8

Slide 20

Slide 20 text

SIMDでUTF-8のバリデーションの参照元 ● 元論文: https://arxiv.org/abs/1902.08318v6 ● 日本語で書かれている解説 https://qiita.com/saka1_p/items/9719d71e70 2aed92a07c ● 結構端折ったので参照してください。 – 「あ」一文字だとスカラー演算したほうがいいし – 理解してないともいえる

Slide 21

Slide 21 text

Add fast AVX2-based implementation of mb_check_encoding for UTF-8 #10436 ● https://github.com/php/php-src/pull/10436 ● ついにAVX2によるUTF-8のバリデーションを行うプ ルリクエストが作成される – PHP 8.3でx86_64アーキテクチャでAVX2が載ってると 速くなる…!

Slide 22

Slide 22 text

UTF-8 Validation optimization for NEON using mb_check_encoding #11076 ● https://github.com/php/php-src/pull/11076 ● てきめんが挑戦したプルリクエスト – ARMのNEONでUTF-8のバリデーションを高速化できない かというもの – 参考元: https://github.com/cyb70289/utf8 – 性能がサチったのでペンディング状態になってる😭 – 書いたブログ:https://tekitoh-memdhoi.info/views/872

Slide 23

Slide 23 text

Add specialized UTF-8 validation function for hosts with no SSE2/AVX2 support #10452 ● https://github.com/php/php-src/pull/10452 ● SSE2/AVX2をサポートしていないCPUでなるべく 高速にmb_check_encodingを行えるようにする – preg_match(‘//u’, $str) と同じ ● Raspberry Piを引っ提げて正常に動作することを 確認しました

Slide 24

Slide 24 text

Check UTF-8 validity for all constant strings on compile time #10853 ● https://github.com/php/php-src/issues/10853 ● 未解決なんだけど、valid UTF-8フラグをつけられるようにしたい よねっていうIssue – IS_STR_VALID_UTF8フラグをmb_check_encodingで立てられるよう にできないかなー?っていうもの – IS_STR_VALID_UTF8フラグとは、元はPCREで使っていたzval構造体に 格納されるフラグ。UTF-8として正しいという意味 ● それをZend Engine内部でも使うようになったのがPHP 8.3 ● GH-10409のmb_scrubの件関係ある?って聞いたら、「ある」って 返事もらえて、プルリクエスト作ってもらえたけどペンディング

Slide 25

Slide 25 text

Add AVX2-accelerated UTF-16 decoding/encoding routines #10488 ● https://github.com/php/php-src/pull/10488 ● 簡単に言えば、UTF-16のencoding/decodingで もAVX2を使えるようになったぞということ ● それ以外はわからん…

Slide 26

Slide 26 text

mb_detect_encoding is more accurate on strings with UTF-8/16 BOM #10373 ● https://github.com/php/php-src/pull/10373 ● mb_detect_encodingの検出アルゴリズムを変え たというもの – mb_detect_encodingは色々変えてるので使ってる方 は気をつけてください – そもそも文字コードは自動検出するべきではない

Slide 27

Slide 27 text

mb_convert_encoding() returns inconsistent output before and after 0x0e 0x0f when converting ISO-2022-JP #10651 ● https://github.com/php/php-src/issues/1065 1 ● mb_check_encodingのISO-2022-JP周りの処理 でのIssue ● 半角カタカナをISO-2022-JPで無理やりねじ込む テクニックがあることを発見したので展開した

Slide 28

Slide 28 text

Fix GH-10648: add check function pointer into mbfl_encoding #10828 ● https://github.com/php/php-src/pull/10828 ● @pakutomaさんのPull Request ● @alexdowadさんとfuzzingしまくってバグつぶしをひたす ら行うという地味に大変なタスクだったと思う ● 僕はJIS関連の指摘しかしてない ● なお、fuzzerのやり方も教えてくれてる

Slide 29

Slide 29 text

Implement NEON-accelerated version of BLOCKCONV for lowercasing and uppercasing strings #11161 ● https://github.com/php/php-src/pull/11161 ● mbstring関係なしに、NEONというARMのSIMDをいじっ てたからレビューに加わりました。 ● 内容としてはstrtolowerやstrtoupperなどで速くなる (ほかも速くなってるかも) ● ちょっと質問をして大丈夫だと理解したのでLGTM

Slide 30

Slide 30 text

Fix UKRAINIAN LETTERS I in CP866 #11213 ● https://github.com/php/php-src/pull/11213 – CP866からUnicodeへの変換に「ウクライナ語の小文字i( ї)」を入れてくれというプル リクエスト – (当時)Twitterで調べて頂いたところ、CP866というのは、ウクライナ語・ロシア語・ベラ ルーシ語・ブルガリア語をサポートするというものだそう(ただ、すべてをサポートできる はずもなく中途半端な文字コードとなってる模様) – 残念ながら、ウクライナ語の小文字iはラテン文字のiを代用するものとして使っており、 「 ї」は収録されていなかった – なるべく丁寧に説明、納得いただいたようでcloseしていただきました。 ● 勉強になりました。

Slide 31

Slide 31 text

More refactoring/fixes/optimizations for CJK text handling via mbstring #11259 ● https://github.com/php/php-src/pull/11259 ● mbfilter_cjkにまとめるというのが主なプルリクエス ト ● ここで、CP932のテーブルが統合されたことにより挙 動が違うことをてきめんが発見、PHP 8.1へバック ポートをすることに

Slide 32

Slide 32 text

mb_str_pad causes access violation ( 0xc0000005) in mbstring.dll #11567 ● https://github.com/php/php-src/issues/1156 7 ● @nielsdos さん提案のmb_str_padでのバグ ● ちょっとNULLチェックで「こうするとバグらない ね」って指摘したけど、RFC読んだら間違ってた – Interned stringを使って解決してた

Slide 33

Slide 33 text

After php8.1, when PDO::ATTR_EMULATE_PREPARES is true and PDO::ATTR_STRINGIFY_FETCHES is true, decimal zeros are no longer filled. #11587 ● https://github.com/php/php-src/issues/11587 ● @SakiTakamachiさんのIssue。pdo/mysql という、知らない部分の問題の 切り分け – プルリクエスト書けるよというので、テストコードを書いて協力しました ● https://github.com/php/php-src/pull/11622 – こちらで @Girgiasさんと@illuuu1994さんを呼んだ – @Girgiasさんが見てくれて、マージしてもらえた ● さきちさんはこのあとアクティブにphp-srcを見てくださっています

Slide 34

Slide 34 text

Fix warning crc32.c on function declaration without a prototype. #11742 ● https://github.com/php/php-src/pull/11742 ● ext/standard/crc32.cのコンパイル時の問題 – コンパイル時にWarning(PHPのじゃないよ!)が出てた – @illuuu1994さんがマージしてくれました。

Slide 35

Slide 35 text

Fix '++nothing+crc' is not a recognized feature for target when compiling M1 / M2 macOS #11796 ● https://github.com/php/php-src/pull/11742 ● ext/standard/crc32.cのコンパイル時の問題 – GCCだと意味のあるおまじないが、macOSのclangでは 意味がないので外すプルリクエスト – @Girgiasさんにマージしてもらいました。

Slide 36

Slide 36 text

SQLite3 callback functions cause a memory leak with a callable array #11878 ● https://github.com/php/php-src/issues/1187 8 – http://doc.php.net/tutorial/local-setup.php を— enable-debugをつけた状態でコンパイルしたバイナリ で動かしたらmemory leakが発生したのを報告 – @nielsdosさんが修正してくれた

Slide 37

Slide 37 text

PHP 8.2でのmb_convert_kanaのdoc ● https://github.com/php/doc-en/pull/2647 ● 実はPHP 8.2からできない組み合わせのときに ValueErrorをthrowするようになったというプルリク エスト ● @mumumuさんに助けてもらいました&マージして もらいました。thanks

Slide 38

Slide 38 text

Fix typos discovered by codespell #12228 ● 所謂 “fix typo” https://github.com/php/php-src/pull/12228 – Unicode Consortiumのデータにtypoがあった – せっかくだから修正頼んでみればということで頼んでみた ● なんとKen Whistlerさんという中の人が直々にコメントをくださった – どのくらいすごい人かはユニコード戦記読んでみてください ● https://unicode.org/consortium/staff.html ● まとめると、「OBSOLETEとなっているものはたとえtypoだろうと修正しません」というもの – Fix typoでこんなドラマがあるんですね ● Fix typoやっていきましょう

Slide 39

Slide 39 text

mb_str_padの追加 $ ~/php_master/bin/php -r 'var_dump(mb_str_pad( 🎉 " ", 3, "祝", STR_PAD_LEFT));' string(10) "祝祝🎉" str_pad関数のmbstring版。 https://wiki.php.net/rfc/mb_str_pad mb_str_pad( string $string, int $length, string $pad_string = “ “, int $pad_type = STR_PAD_RIGHT, ?string $encoding = null // nullだった場合にはmb_internal_encoding() ): string

Slide 40

Slide 40 text

mbstringまとめ ● UTF-8への強化がものすごい – 世界中で使われている文字コードは世界中で研究されている ● 文字をベクトルとして読むとか考えもしなかった ● 論文まで読むことになるとはなあ… – 文字化けの心配だとするとUnicodeのバージョンくらい – UTF-8使おうぜ!! ● mb_str_pad関数が増えました ● mb_send_mailの挙動もちょっと変わってるかも ● mb_detect_encodingは更に変わってます(文字コードは指定するものです) ● ほかはほとんど内部的な変化・改善です

Slide 41

Slide 41 text

まとめ ● 2022年12月から始まったこのゆるい関係でのコントリビュート、めっちゃ長かった ● コントリビュートでわかんないことあったらてきめん宛にXにでも連絡ください(ただしXだけでやりとりすると GitHubだけで見てる人が困惑するので共有はします) – 全部監視してるので「オッ」って思ったものはサポートしていく次第です – @SakiTakamachiさんとはそうしてました – phpusers-ja slackでもやりとりできます (@mumumuさんとはそうしてました) ● PHP Foundation所属のお二人(@Illuuu1994さん、@Girgiasさん)はさすが頼もしい – これ以外にもたくさんほとんど毎日やっておられます – 寄付のご検討を何卒よろしくお願いいたします! ● PHP 8.3のリリースマネージャーのうち、Jakub Zelenka (@bukka)さんもPHP Foundationのパートタイマーです ● 他にもコントリビュートしてる人たくさんいます!! ● PHP 8.3をお楽しみに