SlideShare a Scribd company logo
TR18015:2006を読む

         2012-08-03
  Aiming 大阪スタジオ
          柏田 知洋
今日話すこと
   TR18015 Chap.5
      Language Features:
          Overheads and Strategies
    •   5.1 Namespaces
    •   5.2 Type Conversion Operators
    •   5.3 Classes and Inheritance
    •   5.4 Exception Handling
    •   5.5 Templates
    •   5.6 Programmer Directed Optimizations
TR18015とは
 ISO C++標準化委員会より発行されている
  C++のパフォーマンスに関する技術レポート
 5章に書いてあること:
    • C++のオーバーヘッドって実際どうなの?
    • Cと比べてどれくらい遅くなってるの?
    • いいぜ、お前がC++を遅いって言うなら(ry
5.1 名前空間
           Namespaces
 実行の際の空間・時間的ペナルティは無い
 名前解決は複雑になる
    • ADLとかADLとかADLとか
    • Namespaceを使わなければ名前解決も気にす
      る必要はない
   シンボル名が長くなる分、オブジェクトファイ
    ルのシンボルテーブルは大きくなる
5.2 型変換演算子
     Type Conversion Operators
 基本的にCスタイルのキャストと全く同様
 可能な限り意図の表現力とgreppability*に
  優れたC++スタイルのキャストを使うべき
 dynamic_cast (Cスタイルではできないキャスト)のみ
  RTTIを使うための追加(時間的・空間的)コス
  トが発生する場合がある

    * greppability: 検索(grep)のしやすさ。
            Cスタイルのキャストはgrepによる検索が不可能
5.3 クラスと継承
      Classes and Inheritance
   「オブジェクト指向」スタイルは、
    継承による抽象化を多用する
    • どの程度遅くなるのか?あるいはならないのか?
   表現方法による実行速度の違いを検証する
    • 具体的な環境については不明
    • 特殊なコンパイラを使っているわけではない
5.3.1 表現のオーバーヘッド
     Representation Overheads
   C++の「クラス」は2種類
    1. 仮想関数を持たないクラス
       • Cにおける「struct」と全く同じ
    2. 多態クラス(仮想関数を持つクラス)
     •   オブジェクトごとに一つのポインタ
     •   クラスごとに一つの仮想関数テーブル
         •   仮想関数一つにつきポインタ一つまたは二つ
     •   クラスごとに一つのRTTIオブジェクト
   クラスの主用途は「抽象化」
5.3.1 表現のオーバーヘッド
     Representation Overheads
   抽象化によって、実行時間のオーバーヘッドが
    生じる場合がある
    • 組込型を小さなクラスに入れる
    • スマートポインタを使う
    • 仮想関数を使う
   このような現象は「抽象化コスト(the abstraction
    penalty)」と呼ばれている
   抽象化の種類に依るが、最適化の優れた
    コンパイラ(現存する少なくとも二つの実装)では
    追加コストは3%以下に抑えられている
5.3.2 基本的なクラスの操作
         Basic Class Operations
   クラスの操作にかかるコストを、5種類の
    コンパイラ・実行環境の組み合わせで
    測定・比較する
    •   #1 --- コンパイラA・実行環境A
    •   #2 --- コンパイラB・実行環境A
    •   #3 --- コンパイラC・実行環境A
    •   #4 --- コンパイラD・実行環境B
    •   #5 --- コンパイラE・実行環境B
5.3.2 基本的なクラスの操作
       Basic Class Operations
   メンバ関数とフリー関数の呼び出しコストの違い
    • ポインタ経由      -- px->f(1)   / g(ps, 1)
    • 参照経由        -- x.g(1)     / g(&s, 1)
    • staticメンバ   -- X::h(1)    / h(1)
5.3.2 基本的なクラスの操作
       Basic Class Operations
   #1, #3は感覚に合致した結果
    • X::h(1)とh(1)は引数が一つ少ない
   #2, #5は(inline指定していないにも関わらず)
    インライン化されて呼び出しが消えている
   #4は少々奇妙な結果になっている
    • ただし、インライン化に比べれば些細な差
5.3.3 仮想関数
          Virtual Functions
   仮想関数呼び出しの仕組みとコストは、
    関数ポインタ配列経由の呼び出しと同等
    • 仮想関数     -- pf->f(1)   / x.f(1)
    • ポインタ配列   -- p[1](ps,1) / p[1](&s,1)
5.3.3 仮想関数
          Virtual Functions
   #1,#2,#3,#5は非仮想呼び出しに比べ2割ほど遅い
   #2,#5は仮想関数をインライン化している
    • ただし、インライン化可能な状況は限られている
   #4は仮想呼び出しのほうが速くなってしまっている
    • 「virtualは遅い」はすべての状況で成り立つわけではない
5.3.3.1 クラステンプレートの仮想関数
    Virtual functions of class templates
   クラステンプレート内の仮想関数は、テンプレートが
    実体化される度に(使われていなくても)生成される
    • ライブラリでこれをやってしまうと、100KB単位で
      オブジェクトコードサイズが増加する
   テンプレートにしなくても済む部分は非テンプレート
    の外部クラスに追い出す
    • 状態変数や生ポインタのハンドリングも
    • ios_baseがiosから独立している理由がコレ
   仮想関数が大量にあるクラステンプレートは
    設計を見直したほうがよい
5.3.4 インライン化
               Inlining
   「インライン化」はどの程度効果があるのか?
    • inline無指定   -- px->g(1) / x.g(1)
    • inline指定    -- ps->k(1) / x.k(1)
    • 関数形式マクロ     -- K(ps, 1) / K(&s, 1)
5.3.4 インライン化
           Inlining
 小さい関数では効果は絶大
 賢いコンパイラは勝手にinline化している

 「inlineキーワードは無視される」は、
  賢くないコンパイラには当てはまらない
5.3.5 多重継承
         Multiple Inheritance
 処理系によって内部実装が違う
 例えば、メンバ関数へ渡す
  thisポインタの調整方法
    • 呼び出し側で調整してから渡すか、
    • サンクを作り間接呼び出しにするか
   struct Devied: Base1, Base2 { };
    の時、Base1を左親、Base2を右親とする
5.3.5 多重継承
           Multiple Inheritance
   単一継承・多重継承(左の親/右の親)、
    非仮想・仮想呼び出しで比較
    • 単一継承   -- px->g(1) / px->f(1)
    • 多重(左親) -- pc->g(i) / pa->f(i)
    • 多重(右親) -- pc->gg(i) / pb->ff(i)
5.3.5 多重継承
        Multiple Inheritance
   #1, #4は多重継承すると呼び出しがinline化された
   #1, #2は単一・多重で呼び出しコストに差が無い
   #3, #5は多重継承時に右親の仮想関数を呼ぶと追
    加でコストがかかっている
5.3.6 仮想基底クラス
       Virtual Base Classes
 基底クラスへのアクセスが仮想化される
 非仮想の単一継承と比較
    • 単一継承   -- px->g(1) / px->f(1)
    • 仮想継承   -- pd->gg(i) / pa->f(i)
5.3.6 仮想基底クラス
       Virtual Base Classes
   非仮想呼出で…
    • #3は少しオーバーヘッドがあるように見える
    • #2, #5は明らかに遅くなっている
    • #1, #4は仮想継承のほうがなぜか速い
5.3.6 仮想基底クラス
       Virtual Base Classes
   仮想呼出で…
    • 非仮想呼出の時よりは影響が小さく見える
    • #5のみ明らかにオーバーヘッドがある
    • コンパイラによる最適化の効きが影響大
5.3.7 型情報
             Type Information
   いわゆるRTTI
    •   フリー関数(参考)   -- h(1)
    •   基底クラス       -- typeid(pa)
    •   派生クラス       -- typeid(pc)
    •   仮想基底クラス     -- typeid(pa)
    •   仮想継承        -- typeid(pd)
5.3.7 型情報
         Type Information
   仮想継承かどうかはパフォーマンスには
    影響していない
   基底か派生かは影響を受ける
   どちらにせよ、関数呼び出しよりも明らかに遅い
5.3.8 動的キャスト
               Dynamic Cast
   Vtblの参照、type_infoの比較、thisの調整を
    一度に行うキャスト
    • Down-cast    -- 基底クラスへのキャスト
    • Up-cast      -- 派生クラスへのキャスト
    • Cross-cast   -- 横方向へのキャスト
   「オブジェクト指向言語」のキャストは大体コレ
5.3.8 動的キャスト
           Dynamic Cast
•   仮想関数呼び出し -- px->f(1)
•   左親へのup-cast -- cast(pa, pc)
•   右親へのup-cast -- cast(pb, pc)
•   左親からdown-cast -- cast(pc, pa)
•   右親からdown-cast -- cast(pc, pb)
5.3.8 動的キャスト
            Dynamic Cast
   多段継承もあるが同じ結果なので省略
   Up-castはstatic_castと変わらない
   Down-castは仮想関数呼び出しより遅い
   Cross-castは壊滅的に遅い
    • 本来はUp-cast + Down-castで実現できるはずだが…
5.4 例外処理
       Exception Handling
   詳しく説明すると3時間くらいは語れるので、
    Binary Hacks読んでください。
5.5 テンプレート
             Templates
   Templateの無いC++なんてC++じゃない!!!
    • が、無条件で便利に使えるわけではない
    • 実行時間とコンパイル時間のトレードオフ
5.5.1 テンプレートのオーバーヘッド
     Templates Overheads
 書き方によっては予想外にオブジェクトコード
  が膨張することがある
 T*に対する操作をvoid*に追い出すのは
  常套手段 (thin-wrapper)
    • 例: list<T*>の実装を裏でplist<T>に委譲
      →plist<T>は内部でvoid*にキャストする
    • 賢いコンパイラでは自動でマージするらしい
5.5.2 テンプレート vs. 継承
     Templates vs. Inheritance
   自明でないプログラムには、通常コンテナと
    アルゴリズムが必要
    • C++はTemplateによる実装で用意(STL)
     • .NETのGenericコンテナの中身は継承ベース
    • 他の多くは継承ベースの実装で用意
     • Smalltalk
     • Java
     • 他にもたくさん
5.5.2 テンプレート vs. 継承
        Templates vs. Inheritance
   昔々、C++にテンプレートやRTTIが
    導入される前の話
    •   NIH Class Libraryというライブラリがあった
    •   当然継承ベースでの実装
    •   ほとんどのメンバ関数がvirtual
    •   RTTIも自前で用意
    •   Object型から派生したクラスを操作するよう設計
5.5.2 テンプレート vs. 継承
     Templates vs. Inheritance
   今のtemplateベースの実装に比べると…
    • 継承が深すぎて、テンプレートを使わないのに
      オブジェクトコードの肥大化を起こしていた
    • Object型の派生クラスしか扱えないため、
      int等の組込型は直接扱うことはできなかった
    • 型安全にできなかった
    • 他のライブラリに混ぜて使うことができなかった
   後年、C++にテンプレートベースのクラスライ
    ブラリ(STL)が導入される
5.6 プログラマによる最適化
    Programmer Directed Optimizations
   本節に対する驚くべき解説を思いついたが、
    それを解説するには時間が足りなさすぎる!!!
最後に
 C++のパフォーマンスはコンパイラによって
  激しく上下するので、みんなでGCCを改良し
  ましょう
 より詳しい内容が気になる人が居たら、
  TR18015読書会でもしますか

More Related Content

What's hot

Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
Tomoharu ASAMI
 
Web本文抽出 using crf
Web本文抽出 using crfWeb本文抽出 using crf
Web本文抽出 using crfShuyo Nakatani
 
CRF を使った Web 本文抽出
CRF を使った Web 本文抽出CRF を使った Web 本文抽出
CRF を使った Web 本文抽出
Shuyo Nakatani
 
.NET系開発者から見たJava
.NET系開発者から見たJava.NET系開発者から見たJava
.NET系開発者から見たJava
bleis tift
 
HTMLからの本文抽出
HTMLからの本文抽出HTMLからの本文抽出
HTMLからの本文抽出
Lintaro Ina
 
動的なILの生成と編集
動的なILの生成と編集動的なILの生成と編集
動的なILの生成と編集
terurou
 
Final LINQ Extensions
Final LINQ ExtensionsFinal LINQ Extensions
Final LINQ Extensions
Kouji Matsui
 
Eclipse xtext 紹介
Eclipse xtext 紹介Eclipse xtext 紹介
Eclipse xtext 紹介
Akira Tanaka
 
Kotlinについて学んだコト
Kotlinについて学んだコトKotlinについて学んだコト
Kotlinについて学んだコト
iPride Co., Ltd.
 
Xtext 紹介
Xtext 紹介Xtext 紹介
Xtext 紹介
Akira Tanaka
 

What's hot (11)

Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
Object-Functional Analysis and Design : 次世代モデリングパラダイムへの道標
 
Web本文抽出 using crf
Web本文抽出 using crfWeb本文抽出 using crf
Web本文抽出 using crf
 
CRF を使った Web 本文抽出
CRF を使った Web 本文抽出CRF を使った Web 本文抽出
CRF を使った Web 本文抽出
 
.NET系開発者から見たJava
.NET系開発者から見たJava.NET系開発者から見たJava
.NET系開発者から見たJava
 
HTMLからの本文抽出
HTMLからの本文抽出HTMLからの本文抽出
HTMLからの本文抽出
 
動的なILの生成と編集
動的なILの生成と編集動的なILの生成と編集
動的なILの生成と編集
 
Final LINQ Extensions
Final LINQ ExtensionsFinal LINQ Extensions
Final LINQ Extensions
 
Eclipse xtext 紹介
Eclipse xtext 紹介Eclipse xtext 紹介
Eclipse xtext 紹介
 
ATN No.2 Scala事始め
ATN No.2 Scala事始めATN No.2 Scala事始め
ATN No.2 Scala事始め
 
Kotlinについて学んだコト
Kotlinについて学んだコトKotlinについて学んだコト
Kotlinについて学んだコト
 
Xtext 紹介
Xtext 紹介Xtext 紹介
Xtext 紹介
 

Similar to Tr18015

Mk network programmability-03
Mk network programmability-03Mk network programmability-03
Mk network programmability-03
Miya Kohno
 
「宣言的プログラミング」とSDNのひとつの形態
「宣言的プログラミング」とSDNのひとつの形態「宣言的プログラミング」とSDNのひとつの形態
「宣言的プログラミング」とSDNのひとつの形態
npsg
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成
Akineko Shimizu
 
C#や.NET Frameworkがやっていること
C#や.NET FrameworkがやっていることC#や.NET Frameworkがやっていること
C#や.NET Frameworkがやっていること
信之 岩永
 
Jubatusでマルウェア分類
Jubatusでマルウェア分類Jubatusでマルウェア分類
Jubatusでマルウェア分類
Shuzo Kashihara
 
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
Kei IWASAKI
 
2011 icse-reverse engineering feature models
2011 icse-reverse engineering feature models2011 icse-reverse engineering feature models
2011 icse-reverse engineering feature modelsn-yuki
 
STARC RTL設計スタイルガイドによるVerilog HDL並列記述の補強
STARC RTL設計スタイルガイドによるVerilog HDL並列記述の補強STARC RTL設計スタイルガイドによるVerilog HDL並列記述の補強
STARC RTL設計スタイルガイドによるVerilog HDL並列記述の補強
Kiyoshi Ogawa
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
信之 岩永
 
C# design note sep 2014
C# design note sep 2014C# design note sep 2014
C# design note sep 2014
信之 岩永
 
Drawing Dataflow On Dalvik Bytecodes
Drawing Dataflow On Dalvik Bytecodes Drawing Dataflow On Dalvik Bytecodes
Drawing Dataflow On Dalvik Bytecodes
Takahiro Yoshimura
 
第1回python勉強会
第1回python勉強会第1回python勉強会
第1回python勉強会
Yoshio Shimomura
 
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugjPhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
Hisateru Tanaka
 
T51 jQueryで学ぶJavaScriptでのフロント開発~ASP.NET MVC3もあるよっ!~
T51 jQueryで学ぶJavaScriptでのフロント開発~ASP.NET MVC3もあるよっ!~T51 jQueryで学ぶJavaScriptでのフロント開発~ASP.NET MVC3もあるよっ!~
T51 jQueryで学ぶJavaScriptでのフロント開発~ASP.NET MVC3もあるよっ!~
normalian
 
最速C# 7.x
最速C# 7.x最速C# 7.x
最速C# 7.x
Yamamoto Reki
 
Java EE パフォーマンスTips #glassfish_jp
Java EE パフォーマンスTips #glassfish_jpJava EE パフォーマンスTips #glassfish_jp
Java EE パフォーマンスTips #glassfish_jp
Norito Agetsuma
 
Richard high performance fuzzing ja
Richard  high performance fuzzing jaRichard  high performance fuzzing ja
Richard high performance fuzzing ja
PacSecJP
 
Klab expert camp 成果発表
Klab expert camp 成果発表Klab expert camp 成果発表
Klab expert camp 成果発表
teruyaono1
 
Net fringejp2016
Net fringejp2016Net fringejp2016
Net fringejp2016
Yusuke Fujiwara
 

Similar to Tr18015 (20)

Mk network programmability-03
Mk network programmability-03Mk network programmability-03
Mk network programmability-03
 
「宣言的プログラミング」とSDNのひとつの形態
「宣言的プログラミング」とSDNのひとつの形態「宣言的プログラミング」とSDNのひとつの形態
「宣言的プログラミング」とSDNのひとつの形態
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成
 
C#や.NET Frameworkがやっていること
C#や.NET FrameworkがやっていることC#や.NET Frameworkがやっていること
C#や.NET Frameworkがやっていること
 
Jubatusでマルウェア分類
Jubatusでマルウェア分類Jubatusでマルウェア分類
Jubatusでマルウェア分類
 
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
Cli mini Hack!#1 ~Terminalとの親睦を深めよう~
 
2011 icse-reverse engineering feature models
2011 icse-reverse engineering feature models2011 icse-reverse engineering feature models
2011 icse-reverse engineering feature models
 
STARC RTL設計スタイルガイドによるVerilog HDL並列記述の補強
STARC RTL設計スタイルガイドによるVerilog HDL並列記述の補強STARC RTL設計スタイルガイドによるVerilog HDL並列記述の補強
STARC RTL設計スタイルガイドによるVerilog HDL並列記述の補強
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
 
C# design note sep 2014
C# design note sep 2014C# design note sep 2014
C# design note sep 2014
 
Drawing Dataflow On Dalvik Bytecodes
Drawing Dataflow On Dalvik Bytecodes Drawing Dataflow On Dalvik Bytecodes
Drawing Dataflow On Dalvik Bytecodes
 
第1回python勉強会
第1回python勉強会第1回python勉強会
第1回python勉強会
 
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugjPhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
 
T51 jQueryで学ぶJavaScriptでのフロント開発~ASP.NET MVC3もあるよっ!~
T51 jQueryで学ぶJavaScriptでのフロント開発~ASP.NET MVC3もあるよっ!~T51 jQueryで学ぶJavaScriptでのフロント開発~ASP.NET MVC3もあるよっ!~
T51 jQueryで学ぶJavaScriptでのフロント開発~ASP.NET MVC3もあるよっ!~
 
Clojure
ClojureClojure
Clojure
 
最速C# 7.x
最速C# 7.x最速C# 7.x
最速C# 7.x
 
Java EE パフォーマンスTips #glassfish_jp
Java EE パフォーマンスTips #glassfish_jpJava EE パフォーマンスTips #glassfish_jp
Java EE パフォーマンスTips #glassfish_jp
 
Richard high performance fuzzing ja
Richard  high performance fuzzing jaRichard  high performance fuzzing ja
Richard high performance fuzzing ja
 
Klab expert camp 成果発表
Klab expert camp 成果発表Klab expert camp 成果発表
Klab expert camp 成果発表
 
Net fringejp2016
Net fringejp2016Net fringejp2016
Net fringejp2016
 

Tr18015

  • 1. TR18015:2006を読む 2012-08-03 Aiming 大阪スタジオ 柏田 知洋
  • 2. 今日話すこと  TR18015 Chap.5 Language Features: Overheads and Strategies • 5.1 Namespaces • 5.2 Type Conversion Operators • 5.3 Classes and Inheritance • 5.4 Exception Handling • 5.5 Templates • 5.6 Programmer Directed Optimizations
  • 3. TR18015とは  ISO C++標準化委員会より発行されている C++のパフォーマンスに関する技術レポート  5章に書いてあること: • C++のオーバーヘッドって実際どうなの? • Cと比べてどれくらい遅くなってるの? • いいぜ、お前がC++を遅いって言うなら(ry
  • 4. 5.1 名前空間 Namespaces  実行の際の空間・時間的ペナルティは無い  名前解決は複雑になる • ADLとかADLとかADLとか • Namespaceを使わなければ名前解決も気にす る必要はない  シンボル名が長くなる分、オブジェクトファイ ルのシンボルテーブルは大きくなる
  • 5. 5.2 型変換演算子 Type Conversion Operators  基本的にCスタイルのキャストと全く同様  可能な限り意図の表現力とgreppability*に 優れたC++スタイルのキャストを使うべき  dynamic_cast (Cスタイルではできないキャスト)のみ RTTIを使うための追加(時間的・空間的)コス トが発生する場合がある * greppability: 検索(grep)のしやすさ。 Cスタイルのキャストはgrepによる検索が不可能
  • 6. 5.3 クラスと継承 Classes and Inheritance  「オブジェクト指向」スタイルは、 継承による抽象化を多用する • どの程度遅くなるのか?あるいはならないのか?  表現方法による実行速度の違いを検証する • 具体的な環境については不明 • 特殊なコンパイラを使っているわけではない
  • 7. 5.3.1 表現のオーバーヘッド Representation Overheads  C++の「クラス」は2種類 1. 仮想関数を持たないクラス • Cにおける「struct」と全く同じ 2. 多態クラス(仮想関数を持つクラス) • オブジェクトごとに一つのポインタ • クラスごとに一つの仮想関数テーブル • 仮想関数一つにつきポインタ一つまたは二つ • クラスごとに一つのRTTIオブジェクト  クラスの主用途は「抽象化」
  • 8. 5.3.1 表現のオーバーヘッド Representation Overheads  抽象化によって、実行時間のオーバーヘッドが 生じる場合がある • 組込型を小さなクラスに入れる • スマートポインタを使う • 仮想関数を使う  このような現象は「抽象化コスト(the abstraction penalty)」と呼ばれている  抽象化の種類に依るが、最適化の優れた コンパイラ(現存する少なくとも二つの実装)では 追加コストは3%以下に抑えられている
  • 9. 5.3.2 基本的なクラスの操作 Basic Class Operations  クラスの操作にかかるコストを、5種類の コンパイラ・実行環境の組み合わせで 測定・比較する • #1 --- コンパイラA・実行環境A • #2 --- コンパイラB・実行環境A • #3 --- コンパイラC・実行環境A • #4 --- コンパイラD・実行環境B • #5 --- コンパイラE・実行環境B
  • 10. 5.3.2 基本的なクラスの操作 Basic Class Operations  メンバ関数とフリー関数の呼び出しコストの違い • ポインタ経由 -- px->f(1) / g(ps, 1) • 参照経由 -- x.g(1) / g(&s, 1) • staticメンバ -- X::h(1) / h(1)
  • 11. 5.3.2 基本的なクラスの操作 Basic Class Operations  #1, #3は感覚に合致した結果 • X::h(1)とh(1)は引数が一つ少ない  #2, #5は(inline指定していないにも関わらず) インライン化されて呼び出しが消えている  #4は少々奇妙な結果になっている • ただし、インライン化に比べれば些細な差
  • 12. 5.3.3 仮想関数 Virtual Functions  仮想関数呼び出しの仕組みとコストは、 関数ポインタ配列経由の呼び出しと同等 • 仮想関数 -- pf->f(1) / x.f(1) • ポインタ配列 -- p[1](ps,1) / p[1](&s,1)
  • 13. 5.3.3 仮想関数 Virtual Functions  #1,#2,#3,#5は非仮想呼び出しに比べ2割ほど遅い  #2,#5は仮想関数をインライン化している • ただし、インライン化可能な状況は限られている  #4は仮想呼び出しのほうが速くなってしまっている • 「virtualは遅い」はすべての状況で成り立つわけではない
  • 14. 5.3.3.1 クラステンプレートの仮想関数 Virtual functions of class templates  クラステンプレート内の仮想関数は、テンプレートが 実体化される度に(使われていなくても)生成される • ライブラリでこれをやってしまうと、100KB単位で オブジェクトコードサイズが増加する  テンプレートにしなくても済む部分は非テンプレート の外部クラスに追い出す • 状態変数や生ポインタのハンドリングも • ios_baseがiosから独立している理由がコレ  仮想関数が大量にあるクラステンプレートは 設計を見直したほうがよい
  • 15. 5.3.4 インライン化 Inlining  「インライン化」はどの程度効果があるのか? • inline無指定 -- px->g(1) / x.g(1) • inline指定 -- ps->k(1) / x.k(1) • 関数形式マクロ -- K(ps, 1) / K(&s, 1)
  • 16. 5.3.4 インライン化 Inlining  小さい関数では効果は絶大  賢いコンパイラは勝手にinline化している  「inlineキーワードは無視される」は、 賢くないコンパイラには当てはまらない
  • 17. 5.3.5 多重継承 Multiple Inheritance  処理系によって内部実装が違う  例えば、メンバ関数へ渡す thisポインタの調整方法 • 呼び出し側で調整してから渡すか、 • サンクを作り間接呼び出しにするか  struct Devied: Base1, Base2 { }; の時、Base1を左親、Base2を右親とする
  • 18. 5.3.5 多重継承 Multiple Inheritance  単一継承・多重継承(左の親/右の親)、 非仮想・仮想呼び出しで比較 • 単一継承 -- px->g(1) / px->f(1) • 多重(左親) -- pc->g(i) / pa->f(i) • 多重(右親) -- pc->gg(i) / pb->ff(i)
  • 19. 5.3.5 多重継承 Multiple Inheritance  #1, #4は多重継承すると呼び出しがinline化された  #1, #2は単一・多重で呼び出しコストに差が無い  #3, #5は多重継承時に右親の仮想関数を呼ぶと追 加でコストがかかっている
  • 20. 5.3.6 仮想基底クラス Virtual Base Classes  基底クラスへのアクセスが仮想化される  非仮想の単一継承と比較 • 単一継承 -- px->g(1) / px->f(1) • 仮想継承 -- pd->gg(i) / pa->f(i)
  • 21. 5.3.6 仮想基底クラス Virtual Base Classes  非仮想呼出で… • #3は少しオーバーヘッドがあるように見える • #2, #5は明らかに遅くなっている • #1, #4は仮想継承のほうがなぜか速い
  • 22. 5.3.6 仮想基底クラス Virtual Base Classes  仮想呼出で… • 非仮想呼出の時よりは影響が小さく見える • #5のみ明らかにオーバーヘッドがある • コンパイラによる最適化の効きが影響大
  • 23. 5.3.7 型情報 Type Information  いわゆるRTTI • フリー関数(参考) -- h(1) • 基底クラス -- typeid(pa) • 派生クラス -- typeid(pc) • 仮想基底クラス -- typeid(pa) • 仮想継承 -- typeid(pd)
  • 24. 5.3.7 型情報 Type Information  仮想継承かどうかはパフォーマンスには 影響していない  基底か派生かは影響を受ける  どちらにせよ、関数呼び出しよりも明らかに遅い
  • 25. 5.3.8 動的キャスト Dynamic Cast  Vtblの参照、type_infoの比較、thisの調整を 一度に行うキャスト • Down-cast -- 基底クラスへのキャスト • Up-cast -- 派生クラスへのキャスト • Cross-cast -- 横方向へのキャスト  「オブジェクト指向言語」のキャストは大体コレ
  • 26. 5.3.8 動的キャスト Dynamic Cast • 仮想関数呼び出し -- px->f(1) • 左親へのup-cast -- cast(pa, pc) • 右親へのup-cast -- cast(pb, pc) • 左親からdown-cast -- cast(pc, pa) • 右親からdown-cast -- cast(pc, pb)
  • 27. 5.3.8 動的キャスト Dynamic Cast  多段継承もあるが同じ結果なので省略  Up-castはstatic_castと変わらない  Down-castは仮想関数呼び出しより遅い  Cross-castは壊滅的に遅い • 本来はUp-cast + Down-castで実現できるはずだが…
  • 28. 5.4 例外処理 Exception Handling  詳しく説明すると3時間くらいは語れるので、 Binary Hacks読んでください。
  • 29. 5.5 テンプレート Templates  Templateの無いC++なんてC++じゃない!!! • が、無条件で便利に使えるわけではない • 実行時間とコンパイル時間のトレードオフ
  • 30. 5.5.1 テンプレートのオーバーヘッド Templates Overheads  書き方によっては予想外にオブジェクトコード が膨張することがある  T*に対する操作をvoid*に追い出すのは 常套手段 (thin-wrapper) • 例: list<T*>の実装を裏でplist<T>に委譲 →plist<T>は内部でvoid*にキャストする • 賢いコンパイラでは自動でマージするらしい
  • 31. 5.5.2 テンプレート vs. 継承 Templates vs. Inheritance  自明でないプログラムには、通常コンテナと アルゴリズムが必要 • C++はTemplateによる実装で用意(STL) • .NETのGenericコンテナの中身は継承ベース • 他の多くは継承ベースの実装で用意 • Smalltalk • Java • 他にもたくさん
  • 32. 5.5.2 テンプレート vs. 継承 Templates vs. Inheritance  昔々、C++にテンプレートやRTTIが 導入される前の話 • NIH Class Libraryというライブラリがあった • 当然継承ベースでの実装 • ほとんどのメンバ関数がvirtual • RTTIも自前で用意 • Object型から派生したクラスを操作するよう設計
  • 33. 5.5.2 テンプレート vs. 継承 Templates vs. Inheritance  今のtemplateベースの実装に比べると… • 継承が深すぎて、テンプレートを使わないのに オブジェクトコードの肥大化を起こしていた • Object型の派生クラスしか扱えないため、 int等の組込型は直接扱うことはできなかった • 型安全にできなかった • 他のライブラリに混ぜて使うことができなかった  後年、C++にテンプレートベースのクラスライ ブラリ(STL)が導入される
  • 34. 5.6 プログラマによる最適化 Programmer Directed Optimizations  本節に対する驚くべき解説を思いついたが、 それを解説するには時間が足りなさすぎる!!!
  • 35. 最後に  C++のパフォーマンスはコンパイラによって 激しく上下するので、みんなでGCCを改良し ましょう  より詳しい内容が気になる人が居たら、 TR18015読書会でもしますか