C++でCプリプロセッサを作ったり速くしたりしたお話

Photo by Markus Spiske · CC-License: CC BY
www.temporausch.com
C++でCプリプロセッサを
作ったり速くしたりしたお話
Ladies++meetup#1
@kinu/KinukoYasuda
やすだ きぬこ (@kinu)
WhoamI
普段は C++ でブラウザ (Chrome) を作ってます
ときどきルンバをハックしたり家庭運用の
ための趣味アプリを作ったりしている
C++11 勉強中
C++ の話…と見せかけて 概ね
CPP (C Preprocessor・プリプロセッサ)
のお話をしたいと思います
1. C Preprocessor を使ってみよう!
2. C Preprocessor を (C++で) 作った話
3. C Preprocessor を高速化した話
今日のお話!
Part1:CPreprocessor を
使ってみよう!
❄ #include とか #define とかを解釈するアレ
❄ C や C++ とはまったく関係ない独立した文法/処理
○ コメント処理 (削除)・’¥’ で終わる行の連結
○ 外部ファイル読み込み (#include, #include_next)
○ 条件分岐 (#ifdef / #if / #else / #elif / #endif)
○ 単語置換・マクロ展開 (#define)
○ 文字列化 (#google → “google”)
○ 結合 (a##b → ab)
❄ 頑張れば割といろいろできる
○ でもマクロ展開の仕様が謎で使いこなすのはけっこう難しい
○ というか使いこなす必要は特にない…
CPreprocessorのキホン
❄ ファイルを include する。以上!
❄ その他の使い方は特に C++ ではあまり推奨されない
○ C で型共通のツールを書く (リンクリストとか)
○ template では面倒なちょっとしたマクロ
○ デバッグ用や個人用コードでの手抜き
○ 任意個引数 template の繰り返し記述を手抜きする
(可変長 template で出番がなくなった気がする)
CPreprocessor何に使う?
❄ # による文字列化 (べんり)
に展開
❄ ## による結合 (べんり)
❄ マクロ名でもなんでも結合できる (なかなかキモい)
33 に展開される
CPPのややマイナー機能を使う
これは “fooVER.h” を include してしまう!
❄ 以下のように書き換えれば動く…
まず base と v を展開させる
これは “foo1.h” を include!
CPPの悩ましい展開例 (1)
・・・!?
❄ 再帰呼び出しはできない
になる; 再帰しない
❄ こんな風に擬似的に回避するのが普通
❄ (もっとトリッキーにちゃんと再帰する方法もある)
CPPの悩ましい展開例 (2)
・・・
❄ 少し一般化するとやや汎用的に (boost 風味)
❄ 使い方例
CPPのマクロ展開で繰り返しを頑張る
なかなか便利。
とはいっても…
C++11, C++14 で C++ 本体が
大幅パワーアップ!
range for や可変長テンプレートなどで
オワコン化が進む
基本機能以外は FizzBuzz を書いたり
謎マクロ展開を楽しむための趣味言語になった… (私感)
…気にせず次のパートへ
Part2:CPreprocessor を
C++で作ってみた
❄ 背景:クラウドコンパイラ
○ Chromium のコンパイルが遅い!
○ Google インフラを使って大量のファイルを高速コンパイルするた
めのシステムが ukai, shinh らにより開発される (参照)
■ このシステムのためにコンパイルに必要な include ファイルを
検知してクラウドに送りつける部分が必要に
● → #include 行を適当に処理すればいいじゃん?
● → 適当に作ったら問題たくさん発覚
● → マジメな C Pre Processor を作ることに
❄ ということで 20% タイムで作ってみた (5年くらい前)
なぜ CPP を作ったのか?
❄ C++ で 2500 行くらい
❄ 基本構造
○ シンプルな手書き再帰下降パーサ
■ # ではじまる行を探して
■ define ならマクロ定義部分を記録
■ include や include_next ならファイルを読み込む
■ if, ifdef, else, elif, endif なら条件分岐
○ include ファイルリストを求める機能に特化
■ C や C++ のプログラム部分はパースしなくてよい
● でも include のためにマクロ展開と演算評価は必要
❄ そこそこ高速
○ gcc -E の 6倍くらい (単純比較はできないけど)
お手製 CPP パーサの概要
❄ CPP のマクロ展開は謎が多い
○ → なぜなら仕様が謎だった!
■ 仕様通り実装しても書かれてない部分があって完全に実装
できない・現在知られてる挙動にならない
○ ANSI C Standard Committee の Dave Prosser とい
う人によるアルゴリズムが公開されている
■ http://www.spinellis.gr/blog/20060626/
CPP のマクロ展開を実装する
これなかったら実装できなかった…
CPP のマクロ展開アルゴリズム (1)
CPP のマクロ展開アルゴリズム (2)
CPP のマクロ展開アルゴリズム (3)
❄ …とにかくアルゴリズム通りに書けば動く
❄ なんとなくの概要:
○ 各トークンに “hide set” (HS)というのが結びついている
○ マクロを展開するたびに展開結果のトークンの HS にそのマクロ
が足される
○ 展開は再帰的に行われるが、”hide set” に入っているマクロはそ
のスキャン中はもう展開されない (再帰の限定的禁止)
○ ## はマクロ展開より先に起こる (遅延させて回避可能)
。。。。。
CPP を作る・完成
❄ その他
○ __LINE__ や __DATE__ もちまちま作る
○ 条件分岐のために数式のパースと整数演算評価もする
❄ 少しずつ複雑そうなソースを使ってテストしながら修正・テ
ストケースに足していく
○ Chromium, WebKit, elfutils, Linux Kernel, boost, ...
❄ だいたい正しく動くように (∩´∀`)∩
Part3:CPreprocessor を
高速化してみた
マジメに作ってみたのはいいが…
❄ 最初に作られた単純な実装 (string::find + substr + いろ
んなハック) に比べると半分くらいの速度
❄ コンパイル速度を速くするのがクラウドコンパイラの目標
なので、高速に動かないと意味がない…
→ 高速化しよう!
なんか遅い。。
❄ まずは細かい部分を端から修正
○ switch などはできるだけテーブルに
○ locale 依存の ctype.h の関数 (isalnum など) は使わない
○ 再帰的なアルゴリズムを再帰を使わない形で再実装
○ ホットな場所での深いポインタ参照は避ける
○ stringstream は激重なので (例えエラー出力でも) 避ける
○ トークンのサイズをなるべく小さく・頻度の高いトークンに最
適化 (ちなみに小さくし過ぎたら遅くなった)
1文字の記号など用
2文字の演算子用 (“==” など)
CPP の高速化 (1)
❄ 一旦処理したファイルはなるべくもう読まない
○ マクロを再定義して自分を再帰的に include するファイルもある
ので単純にはできない
■ → ファイル毎に評価されたマクロと変更したマクロを覚えておき、
評価されたマクロが変更されない限り二度は読まない
■ → 全マクロIDの評価と変更を記録するとメモリを食いすぎて逆に遅
くなるので、bloomfilter っぽく false positive は許す
→ 20% 高速化!
❄ #endif やコメント終端までできるだけ速くジャンプ
○ ‘if/ifdef’ 毎に対応する endif の位置を憶えておく
→ ~15% 高速化! (でも後に削除)
CPP の高速化 (2)
❄ ‘#’ ディレクティブマッチに Double-Array Trie を使う
○ 大した種類はないけど頻繁に呼ばれる・テーブルは静的なので
更新の心配はなし
→ 5% 高速化!
❄ 読み飛ばし処理に SSE を使う
○ 次の ‘#’ まで読み飛ばす、次の ‘*/’ まで読み飛ばす、次の改行ま
で読み飛ばすなど、最頻出処理
○ SSE2 で16文字一度に compare し、popcount で改行も数える
(__LINE__ のために行カウントが必要なため)
→ 25% 高速化!
CPP の高速化 (3)
❄ 最終的には最初の単純実装より2倍くらい速くなった
○ (現在は社内で引き継がれてさらに高速化されたようです)
❄ 雑な知見
○ ctype.h, stringstream は速度が気になるなら使わない
SSE は意外と普通に速くなる
○ 大幅高速化は大体「速くする」より「処理しない」
めでたしめでたし!
CPP の高速化まとめ
おしまい
HappyC++(andCPP)Life!
1 of 28

Recommended

TensorFlow Lite Delegateとは? by
TensorFlow Lite Delegateとは?TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?Mr. Vengineer
9.1K views32 slides
ARM CPUにおけるSIMDを用いた高速計算入門 by
ARM CPUにおけるSIMDを用いた高速計算入門ARM CPUにおけるSIMDを用いた高速計算入門
ARM CPUにおけるSIMDを用いた高速計算入門Fixstars Corporation
7K views114 slides
Docker Compose 徹底解説 by
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説Masahito Zembutsu
61.1K views123 slides
20分くらいでわかった気分になれるC++20コルーチン by
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
13K views31 slides
Pythonによる黒魔術入門 by
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門大樹 小倉
44.4K views35 slides
C++ マルチスレッド 入門 by
C++ マルチスレッド 入門C++ マルチスレッド 入門
C++ マルチスレッド 入門京大 マイコンクラブ
57.8K views53 slides

More Related Content

What's hot

C# ゲームプログラミングはホントにメモリのことに無頓着でいいの? by
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?京大 マイコンクラブ
22.7K views47 slides
FPGAのトレンドをまとめてみた by
FPGAのトレンドをまとめてみたFPGAのトレンドをまとめてみた
FPGAのトレンドをまとめてみたTakefumi MIYOSHI
18.1K views18 slides
組み込み関数(intrinsic)によるSIMD入門 by
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門Norishige Fukushima
47.5K views122 slides
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜 by
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Preferred Networks
14.6K views30 slides
暗号技術の実装と数学 by
暗号技術の実装と数学暗号技術の実装と数学
暗号技術の実装と数学MITSUNARI Shigeo
9.6K views35 slides
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編 by
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編Fixstars Corporation
1.6K views57 slides

What's hot(20)

C# ゲームプログラミングはホントにメモリのことに無頓着でいいの? by 京大 マイコンクラブ
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
C# ゲームプログラミングはホントにメモリのことに無頓着でいいの?
FPGAのトレンドをまとめてみた by Takefumi MIYOSHI
FPGAのトレンドをまとめてみたFPGAのトレンドをまとめてみた
FPGAのトレンドをまとめてみた
Takefumi MIYOSHI18.1K views
組み込み関数(intrinsic)によるSIMD入門 by Norishige Fukushima
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
Norishige Fukushima47.5K views
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜 by Preferred Networks
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Preferred Networks14.6K views
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編 by Fixstars Corporation
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ. by kiki utagawa
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
kiki utagawa19.7K views
DockerコンテナでGitを使う by Kazuhiro Suga
DockerコンテナでGitを使うDockerコンテナでGitを使う
DockerコンテナでGitを使う
Kazuhiro Suga18.8K views
A quick tour of the Cysharp OSS by Yoshifumi Kawai
A quick tour of the Cysharp OSSA quick tour of the Cysharp OSS
A quick tour of the Cysharp OSS
Yoshifumi Kawai60.3K views
分散システムについて語らせてくれ by Kumazaki Hiroki
分散システムについて語らせてくれ分散システムについて語らせてくれ
分散システムについて語らせてくれ
Kumazaki Hiroki119.4K views
Intro to SVE 富岳のA64FXを触ってみた by MITSUNARI Shigeo
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
MITSUNARI Shigeo11.6K views
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編 by Fixstars Corporation
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
CPU / GPU高速化セミナー!性能モデルの理論と実践:実践編
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ by Genya Murakami
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami52.4K views
CXL_説明_公開用.pdf by Yasunori Goto
CXL_説明_公開用.pdfCXL_説明_公開用.pdf
CXL_説明_公開用.pdf
Yasunori Goto3.9K views
20180729 Preferred Networksの機械学習クラスタを支える技術 by Preferred Networks
20180729 Preferred Networksの機械学習クラスタを支える技術20180729 Preferred Networksの機械学習クラスタを支える技術
20180729 Preferred Networksの機械学習クラスタを支える技術
Preferred Networks32.8K views
Dockerからcontainerdへの移行 by Kohei Tokunaga
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
Kohei Tokunaga16.6K views

Similar to C++でCプリプロセッサを作ったり速くしたりしたお話

dwangocpp1-lt by
dwangocpp1-ltdwangocpp1-lt
dwangocpp1-ltkarupanerura
1.7K views20 slides
C++ Now 2012 report by
C++ Now 2012 reportC++ Now 2012 report
C++ Now 2012 reportAkira Takahashi
1.1K views29 slides
Runtime c++editing by
Runtime c++editingRuntime c++editing
Runtime c++editingSeiya Ishibashi
2.4K views39 slides
ゆるかわPhp by
ゆるかわPhpゆるかわPhp
ゆるかわPhpRyota Mochizuki
1.1K views83 slides
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる! by
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!Masaki Muranaka
12.2K views36 slides

Similar to C++でCプリプロセッサを作ったり速くしたりしたお話(20)

オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる! by Masaki Muranaka
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!
オープン・ソースで構築するARMマイコン開発環境 ―― GCC,Eclipse,OpenOCDで統合開発環境,JTAGデバッグもできる!
Masaki Muranaka12.2K views
PHPからC#のライブラリを呼べるようにしたdotnet_ffiを趣味でつくってみた by johgus johgus
PHPからC#のライブラリを呼べるようにしたdotnet_ffiを趣味でつくってみたPHPからC#のライブラリを呼べるようにしたdotnet_ffiを趣味でつくってみた
PHPからC#のライブラリを呼べるようにしたdotnet_ffiを趣味でつくってみた
johgus johgus23 views
runC概要と使い方 by Yuji Oshima
runC概要と使い方runC概要と使い方
runC概要と使い方
Yuji Oshima4.4K views
High performance python computing for data science by Takami Sato
High performance python computing for data scienceHigh performance python computing for data science
High performance python computing for data science
Takami Sato20K views
やさしいGitの内部構造 - yapcasia2013 by DQNEO
やさしいGitの内部構造 - yapcasia2013やさしいGitの内部構造 - yapcasia2013
やさしいGitの内部構造 - yapcasia2013
DQNEO15.6K views
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~ by infinite_loop
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
infinite_loop67.3K views
Emscriptenと不思議のダンジョン by 兎 伊藤
Emscriptenと不思議のダンジョンEmscriptenと不思議のダンジョン
Emscriptenと不思議のダンジョン
兎 伊藤2.5K views
密着!わたしのコンソールアプリ開発環境 by Fumihito Yokoyama
密着!わたしのコンソールアプリ開発環境密着!わたしのコンソールアプリ開発環境
密着!わたしのコンソールアプリ開発環境
Fumihito Yokoyama3.6K views
Define and expansion of cpp macro by digitalghost
Define and expansion of cpp macroDefine and expansion of cpp macro
Define and expansion of cpp macro
digitalghost4.2K views
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015) by Kotaro Nakayama
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)
Deep Learning Implementations: pylearn2 and torch7 (JNNS 2015)
Kotaro Nakayama2.9K views
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011 by Hiroh Satoh
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011
Hiroh Satoh49.2K views
ニコニコを支える Erlang / Elixir by kojingharang
ニコニコを支える Erlang / Elixirニコニコを支える Erlang / Elixir
ニコニコを支える Erlang / Elixir
kojingharang 2.2K views
Lisp Tutorial for Pythonista Day 6 by Ransui Iso
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
Ransui Iso1.7K views
Tensor flow勉強会3 by tak9029
Tensor flow勉強会3Tensor flow勉強会3
Tensor flow勉強会3
tak90294.4K views

Recently uploaded

さくらのひやおろし2023 by
さくらのひやおろし2023さくらのひやおろし2023
さくらのひやおろし2023法林浩之
91 views58 slides
01Booster Studio ご紹介資料 by
01Booster Studio ご紹介資料01Booster Studio ご紹介資料
01Booster Studio ご紹介資料ssusere7a2172
300 views19 slides
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料) by
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)NTT DATA Technology & Innovation
13 views38 slides
JJUG CCC.pptx by
JJUG CCC.pptxJJUG CCC.pptx
JJUG CCC.pptxKanta Sasaki
6 views14 slides
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料) by
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)NTT DATA Technology & Innovation
233 views63 slides
The Things Stack説明資料 by The Things Industries by
The Things Stack説明資料 by The Things IndustriesThe Things Stack説明資料 by The Things Industries
The Things Stack説明資料 by The Things IndustriesCRI Japan, Inc.
41 views29 slides

Recently uploaded(12)

さくらのひやおろし2023 by 法林浩之
さくらのひやおろし2023さくらのひやおろし2023
さくらのひやおろし2023
法林浩之91 views
01Booster Studio ご紹介資料 by ssusere7a2172
01Booster Studio ご紹介資料01Booster Studio ご紹介資料
01Booster Studio ご紹介資料
ssusere7a2172300 views
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料) by NTT DATA Technology & Innovation
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)
速習! PostgreSQL専用HAソフトウェア: Patroni(PostgreSQL Conference Japan 2023 発表資料)
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料) by NTT DATA Technology & Innovation
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)
pgvectorを使ってChatGPTとPostgreSQLを連携してみよう!(PostgreSQL Conference Japan 2023 発表資料)
The Things Stack説明資料 by The Things Industries by CRI Japan, Inc.
The Things Stack説明資料 by The Things IndustriesThe Things Stack説明資料 by The Things Industries
The Things Stack説明資料 by The Things Industries
CRI Japan, Inc.41 views
SNMPセキュリティ超入門 by mkoda
SNMPセキュリティ超入門SNMPセキュリティ超入門
SNMPセキュリティ超入門
mkoda175 views
Web3 Career_クレデン資料 .pdf by nanamatsuo
Web3 Career_クレデン資料 .pdfWeb3 Career_クレデン資料 .pdf
Web3 Career_クレデン資料 .pdf
nanamatsuo14 views
SSH応用編_20231129.pdf by icebreaker4
SSH応用編_20231129.pdfSSH応用編_20231129.pdf
SSH応用編_20231129.pdf
icebreaker4172 views
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20... by NTT DATA Technology & Innovation
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...
今、改めて考えるPostgreSQLプラットフォーム - マルチクラウドとポータビリティ -(PostgreSQL Conference Japan 20...
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化 by Knowledge & Experience
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化
「概念モデリング自動化に向けた第一歩」 ~ ChatGPT・Open AI 活用による開発対象のモデル化
Windows 11 information that can be used at the development site by Atomu Hidaka
Windows 11 information that can be used at the development siteWindows 11 information that can be used at the development site
Windows 11 information that can be used at the development site
Atomu Hidaka71 views

C++でCプリプロセッサを作ったり速くしたりしたお話

  • 1. Photo by Markus Spiske · CC-License: CC BY www.temporausch.com C++でCプリプロセッサを 作ったり速くしたりしたお話 Ladies++meetup#1 @kinu/KinukoYasuda
  • 2. やすだ きぬこ (@kinu) WhoamI 普段は C++ でブラウザ (Chrome) を作ってます ときどきルンバをハックしたり家庭運用の ための趣味アプリを作ったりしている C++11 勉強中
  • 3. C++ の話…と見せかけて 概ね CPP (C Preprocessor・プリプロセッサ) のお話をしたいと思います 1. C Preprocessor を使ってみよう! 2. C Preprocessor を (C++で) 作った話 3. C Preprocessor を高速化した話 今日のお話!
  • 5. ❄ #include とか #define とかを解釈するアレ ❄ C や C++ とはまったく関係ない独立した文法/処理 ○ コメント処理 (削除)・’¥’ で終わる行の連結 ○ 外部ファイル読み込み (#include, #include_next) ○ 条件分岐 (#ifdef / #if / #else / #elif / #endif) ○ 単語置換・マクロ展開 (#define) ○ 文字列化 (#google → “google”) ○ 結合 (a##b → ab) ❄ 頑張れば割といろいろできる ○ でもマクロ展開の仕様が謎で使いこなすのはけっこう難しい ○ というか使いこなす必要は特にない… CPreprocessorのキホン
  • 6. ❄ ファイルを include する。以上! ❄ その他の使い方は特に C++ ではあまり推奨されない ○ C で型共通のツールを書く (リンクリストとか) ○ template では面倒なちょっとしたマクロ ○ デバッグ用や個人用コードでの手抜き ○ 任意個引数 template の繰り返し記述を手抜きする (可変長 template で出番がなくなった気がする) CPreprocessor何に使う?
  • 7. ❄ # による文字列化 (べんり) に展開 ❄ ## による結合 (べんり) ❄ マクロ名でもなんでも結合できる (なかなかキモい) 33 に展開される CPPのややマイナー機能を使う
  • 8. これは “fooVER.h” を include してしまう! ❄ 以下のように書き換えれば動く… まず base と v を展開させる これは “foo1.h” を include! CPPの悩ましい展開例 (1) ・・・!?
  • 9. ❄ 再帰呼び出しはできない になる; 再帰しない ❄ こんな風に擬似的に回避するのが普通 ❄ (もっとトリッキーにちゃんと再帰する方法もある) CPPの悩ましい展開例 (2) ・・・
  • 10. ❄ 少し一般化するとやや汎用的に (boost 風味) ❄ 使い方例 CPPのマクロ展開で繰り返しを頑張る
  • 12. C++11, C++14 で C++ 本体が 大幅パワーアップ! range for や可変長テンプレートなどで オワコン化が進む 基本機能以外は FizzBuzz を書いたり 謎マクロ展開を楽しむための趣味言語になった… (私感)
  • 15. ❄ 背景:クラウドコンパイラ ○ Chromium のコンパイルが遅い! ○ Google インフラを使って大量のファイルを高速コンパイルするた めのシステムが ukai, shinh らにより開発される (参照) ■ このシステムのためにコンパイルに必要な include ファイルを 検知してクラウドに送りつける部分が必要に ● → #include 行を適当に処理すればいいじゃん? ● → 適当に作ったら問題たくさん発覚 ● → マジメな C Pre Processor を作ることに ❄ ということで 20% タイムで作ってみた (5年くらい前) なぜ CPP を作ったのか?
  • 16. ❄ C++ で 2500 行くらい ❄ 基本構造 ○ シンプルな手書き再帰下降パーサ ■ # ではじまる行を探して ■ define ならマクロ定義部分を記録 ■ include や include_next ならファイルを読み込む ■ if, ifdef, else, elif, endif なら条件分岐 ○ include ファイルリストを求める機能に特化 ■ C や C++ のプログラム部分はパースしなくてよい ● でも include のためにマクロ展開と演算評価は必要 ❄ そこそこ高速 ○ gcc -E の 6倍くらい (単純比較はできないけど) お手製 CPP パーサの概要
  • 17. ❄ CPP のマクロ展開は謎が多い ○ → なぜなら仕様が謎だった! ■ 仕様通り実装しても書かれてない部分があって完全に実装 できない・現在知られてる挙動にならない ○ ANSI C Standard Committee の Dave Prosser とい う人によるアルゴリズムが公開されている ■ http://www.spinellis.gr/blog/20060626/ CPP のマクロ展開を実装する これなかったら実装できなかった…
  • 20. CPP のマクロ展開アルゴリズム (3) ❄ …とにかくアルゴリズム通りに書けば動く ❄ なんとなくの概要: ○ 各トークンに “hide set” (HS)というのが結びついている ○ マクロを展開するたびに展開結果のトークンの HS にそのマクロ が足される ○ 展開は再帰的に行われるが、”hide set” に入っているマクロはそ のスキャン中はもう展開されない (再帰の限定的禁止) ○ ## はマクロ展開より先に起こる (遅延させて回避可能) 。。。。。
  • 21. CPP を作る・完成 ❄ その他 ○ __LINE__ や __DATE__ もちまちま作る ○ 条件分岐のために数式のパースと整数演算評価もする ❄ 少しずつ複雑そうなソースを使ってテストしながら修正・テ ストケースに足していく ○ Chromium, WebKit, elfutils, Linux Kernel, boost, ... ❄ だいたい正しく動くように (∩´∀`)∩
  • 23. マジメに作ってみたのはいいが… ❄ 最初に作られた単純な実装 (string::find + substr + いろ んなハック) に比べると半分くらいの速度 ❄ コンパイル速度を速くするのがクラウドコンパイラの目標 なので、高速に動かないと意味がない… → 高速化しよう! なんか遅い。。
  • 24. ❄ まずは細かい部分を端から修正 ○ switch などはできるだけテーブルに ○ locale 依存の ctype.h の関数 (isalnum など) は使わない ○ 再帰的なアルゴリズムを再帰を使わない形で再実装 ○ ホットな場所での深いポインタ参照は避ける ○ stringstream は激重なので (例えエラー出力でも) 避ける ○ トークンのサイズをなるべく小さく・頻度の高いトークンに最 適化 (ちなみに小さくし過ぎたら遅くなった) 1文字の記号など用 2文字の演算子用 (“==” など) CPP の高速化 (1)
  • 25. ❄ 一旦処理したファイルはなるべくもう読まない ○ マクロを再定義して自分を再帰的に include するファイルもある ので単純にはできない ■ → ファイル毎に評価されたマクロと変更したマクロを覚えておき、 評価されたマクロが変更されない限り二度は読まない ■ → 全マクロIDの評価と変更を記録するとメモリを食いすぎて逆に遅 くなるので、bloomfilter っぽく false positive は許す → 20% 高速化! ❄ #endif やコメント終端までできるだけ速くジャンプ ○ ‘if/ifdef’ 毎に対応する endif の位置を憶えておく → ~15% 高速化! (でも後に削除) CPP の高速化 (2)
  • 26. ❄ ‘#’ ディレクティブマッチに Double-Array Trie を使う ○ 大した種類はないけど頻繁に呼ばれる・テーブルは静的なので 更新の心配はなし → 5% 高速化! ❄ 読み飛ばし処理に SSE を使う ○ 次の ‘#’ まで読み飛ばす、次の ‘*/’ まで読み飛ばす、次の改行ま で読み飛ばすなど、最頻出処理 ○ SSE2 で16文字一度に compare し、popcount で改行も数える (__LINE__ のために行カウントが必要なため) → 25% 高速化! CPP の高速化 (3)
  • 27. ❄ 最終的には最初の単純実装より2倍くらい速くなった ○ (現在は社内で引き継がれてさらに高速化されたようです) ❄ 雑な知見 ○ ctype.h, stringstream は速度が気になるなら使わない SSE は意外と普通に速くなる ○ 大幅高速化は大体「速くする」より「処理しない」 めでたしめでたし! CPP の高速化まとめ