Flexibility versus performance J. Daniel Garcia · Static versus dynamic polymorphism Who am I? A...

Post on 04-Jun-2020

0 views 0 download

transcript

Static versus dynamic polymorphism

Static versus dynamic polymorphismFlexibility versus performance

J. Daniel Garcia

ARCOS GroupUniversity Carlos III of Madrid

Spain

December 2, 2016

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 1/97

Static versus dynamic polymorphism

Warning

c This work is under Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)license.You are free to Share — copy and redistribute the ma-terial in any medium or format.

b You must give appropriate credit, provide a link to thelicense, and indicate if changes were made. You maydo so in any reasonable manner, but not in any way thatsuggests the licensor endorses you or your use.

e You may not use the material for commercial purposes.d If you remix, transform, or build upon the material, you

may not distribute the modified material.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 2/97

Static versus dynamic polymorphism

Who am I?

A C++ programmer.Started writing C++ code in 1989.

A university professor in Computer Architecture.

A ISO C++ language standards committee member.

My goal: Improve applications programming.Performance → faster applications.Energy efficiency → better performance per Watt.Maintainability → easier to modify.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 3/97

Static versus dynamic polymorphism

Who am I?

A C++ programmer.Started writing C++ code in 1989.

A university professor in Computer Architecture.

A ISO C++ language standards committee member.

My goal: Improve applications programming.Performance → faster applications.Energy efficiency → better performance per Watt.Maintainability → easier to modify.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 3/97

Static versus dynamic polymorphism

Who am I?

A C++ programmer.Started writing C++ code in 1989.

A university professor in Computer Architecture.

A ISO C++ language standards committee member.

My goal: Improve applications programming.Performance → faster applications.Energy efficiency → better performance per Watt.Maintainability → easier to modify.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 3/97

Static versus dynamic polymorphism

Who am I?

A C++ programmer.Started writing C++ code in 1989.

A university professor in Computer Architecture.

A ISO C++ language standards committee member.

My goal: Improve applications programming.Performance → faster applications.Energy efficiency → better performance per Watt.Maintainability → easier to modify.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 3/97

Static versus dynamic polymorphism

ARCOS@uc3m

UC3M: A young, international, research oriented university.

ARCOS: Applied research group:Lines: High Performance Computing, Big data,Cyberphisical Systems, and Programming Models forApplication Improvement

Improving Applications:REPARA: Reengineering and Enabling Performance andpoweR of Applications. Funded by EU (FP7).RePhrase: REfactoring Parallel Heterogeneous ResourceAware Applications. Funded by EU (H2020).

Standards:ISO/IEC JTC/SC22/WG21. ISO C++ Committee.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 4/97

Static versus dynamic polymorphism

Acknowledgments

Some ideas in this talk are highly inspired from SeanParent’s talk Inheritance is base class of evil.

Many thanks to the following individuals for providingfeedback:

Ion Gaztañaga.Manu Sánchez.Joaquín M. López.Bjarne Stroustrup.

Complete code examples can be found at:github.com/jdgarciauc3m/polyexamples.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 5/97

Static versus dynamic polymorphism

What is this talk about?

Revisit some ideas about classical object orientation.

Remind that polymorphism can be either static ordynamic.

Introduce type erasure as a way to simplify interfaces.

Improvements through small object optimization toreduce allocations and improve performance.

Illustrate both techniques with a canonical simpleexample.

Including performance evaluation.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 6/97

Static versus dynamic polymorphism

Introduction

1 Introduction

2 Some observations

3 Problem

4 Simple solution

5 Heterogeneous solution

6 Combining polymorphisms: Type Erasure

7 Optimizing small objects

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 7/97

Static versus dynamic polymorphism

Introduction

Tools and problems

A hammer is a wonderful tool for driving a nail

What about nuts?What about screws?What about debugging programs?

Is Object Orientation the programmer’s hammer?

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 8/97

Static versus dynamic polymorphism

Introduction

Tools and problems

A hammer is a wonderful tool for driving a nailWhat about nuts?

What about screws?What about debugging programs?

Is Object Orientation the programmer’s hammer?

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 8/97

Static versus dynamic polymorphism

Introduction

Tools and problems

A hammer is a wonderful tool for driving a nailWhat about nuts?What about screws?

What about debugging programs?

Is Object Orientation the programmer’s hammer?

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 8/97

Static versus dynamic polymorphism

Introduction

Tools and problems

A hammer is a wonderful tool for driving a nailWhat about nuts?What about screws?What about debugging programs?

Is Object Orientation the programmer’s hammer?

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 8/97

Static versus dynamic polymorphism

Introduction

Tools and problems

A hammer is a wonderful tool for driving a nailWhat about nuts?What about screws?What about debugging programs?

Is Object Orientation the programmer’s hammer?

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 8/97

Static versus dynamic polymorphism

Introduction

Origins

Subroutine:David Wheeler and Maurice Wilkes. 1951.

Functional Programming:Lisp, Johh McCarthy. 1958.

Object Oriented ProgrammingSimula, Simula-67. Ole-Johan Dahl and Kristen Nygaard.1960-1970.Smalltalk, Smalltalk-80. Alan C. Kay. 1970-1980.. . .

Generic Programming:CLU. Barbara Liskov. 1974.Ada. Jean Ichbiah. 1983.C++. Bjarne Stroustrup. 1983. STL. Alexander Stepanov.1998.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 9/97

Static versus dynamic polymorphism

Introduction

Origins

Subroutine:David Wheeler and Maurice Wilkes. 1951.

Functional Programming:Lisp, Johh McCarthy. 1958.

Object Oriented ProgrammingSimula, Simula-67. Ole-Johan Dahl and Kristen Nygaard.1960-1970.Smalltalk, Smalltalk-80. Alan C. Kay. 1970-1980.. . .

Generic Programming:CLU. Barbara Liskov. 1974.Ada. Jean Ichbiah. 1983.C++. Bjarne Stroustrup. 1983. STL. Alexander Stepanov.1998.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 9/97

Static versus dynamic polymorphism

Introduction

Origins

Subroutine:David Wheeler and Maurice Wilkes. 1951.

Functional Programming:Lisp, Johh McCarthy. 1958.

Object Oriented ProgrammingSimula, Simula-67. Ole-Johan Dahl and Kristen Nygaard.1960-1970.Smalltalk, Smalltalk-80. Alan C. Kay. 1970-1980.. . .

Generic Programming:CLU. Barbara Liskov. 1974.Ada. Jean Ichbiah. 1983.C++. Bjarne Stroustrup. 1983. STL. Alexander Stepanov.1998.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 9/97

Static versus dynamic polymorphism

Introduction

Origins

Subroutine:David Wheeler and Maurice Wilkes. 1951.

Functional Programming:Lisp, Johh McCarthy. 1958.

Object Oriented ProgrammingSimula, Simula-67. Ole-Johan Dahl and Kristen Nygaard.1960-1970.Smalltalk, Smalltalk-80. Alan C. Kay. 1970-1980.. . .

Generic Programming:CLU. Barbara Liskov. 1974.Ada. Jean Ichbiah. 1983.C++. Bjarne Stroustrup. 1983. STL. Alexander Stepanov.1998.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 9/97

Static versus dynamic polymorphism

Introduction

But, when did they become popular?

1979-1983: C++.1986: Object Pascal.1986: Eiffel.1995: Java.1995: Ada95.2000: C#.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 10/97

Static versus dynamic polymorphism

Introduction

Did anything else happen in the 90’s?

Before 2005: Welived in DisneylandAfter 2005: Hit byreality.

Graphic: The free lunch is overHerb Sutter.http://www.gotw.ca/publications/concurrency-ddj.htm

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 11/97

Static versus dynamic polymorphism

Some observations

1 Introduction

2 Some observations

3 Problem

4 Simple solution

5 Heterogeneous solution

6 Combining polymorphisms: Type Erasure

7 Optimizing small objects

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 12/97

Static versus dynamic polymorphism

Some observations

Object orientation

Can we get OO development without OO languages?

Theoretically: YES.Also true in practice:

Old examples: X-Window System, OSF/Motif.

However: Too complicated and error prone.Easy to make mistakes.Don’t leave up to programmers what compilers can dobetter.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 13/97

Static versus dynamic polymorphism

Some observations

Object orientation

Can we get OO development without OO languages?Theoretically: YES.

Also true in practice:Old examples: X-Window System, OSF/Motif.

However: Too complicated and error prone.Easy to make mistakes.Don’t leave up to programmers what compilers can dobetter.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 13/97

Static versus dynamic polymorphism

Some observations

Object orientation

Can we get OO development without OO languages?Theoretically: YES.Also true in practice:

Old examples: X-Window System, OSF/Motif.

However: Too complicated and error prone.Easy to make mistakes.Don’t leave up to programmers what compilers can dobetter.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 13/97

Static versus dynamic polymorphism

Some observations

Object orientation

Can we get OO development without OO languages?Theoretically: YES.Also true in practice:

Old examples: X-Window System, OSF/Motif.

However: Too complicated and error prone.Easy to make mistakes.Don’t leave up to programmers what compilers can dobetter.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 13/97

Static versus dynamic polymorphism

Some observations

Sometimes we forget

Principles on X-Window design (Bob Scheifler and JimGettys, 1984).

Do not add new functionality unless an implementor cannotcomplete a real application without it.It is as important to decide what a system is not as todecide what it is. Do not serve all the world’s needs.The only thing worse than generalizing from one example isgeneralizing from no examples at all.If a problem is not completely understood, it is probablybest to provide no solution at all.If you can get 90 percent of the desired effect for 10 percentof the work, use the simpler solution.Isolate complexity as much as possible.Provide mechanism rather than policy.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 14/97

Static versus dynamic polymorphism

Some observations

Everything should be a “method”

Why do we use classes?

Information hiding principle. David Parnas (1972).Increment flexibility and comprehension.Reduce development time.Reduce global coupling.

But ...We assumed that a module or component is mapped to aclass.And we insist in hiding . . .

Even when nothing needs to be hidden.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 15/97

Static versus dynamic polymorphism

Some observations

Everything should be a “method”

Why do we use classes?Information hiding principle. David Parnas (1972).

Increment flexibility and comprehension.Reduce development time.Reduce global coupling.

But ...We assumed that a module or component is mapped to aclass.And we insist in hiding . . .

Even when nothing needs to be hidden.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 15/97

Static versus dynamic polymorphism

Some observations

Everything should be a “method”

Why do we use classes?Information hiding principle. David Parnas (1972).

Increment flexibility and comprehension.Reduce development time.Reduce global coupling.

But ...We assumed that a module or component is mapped to aclass.

And we insist in hiding . . .Even when nothing needs to be hidden.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 15/97

Static versus dynamic polymorphism

Some observations

Everything should be a “method”

Why do we use classes?Information hiding principle. David Parnas (1972).

Increment flexibility and comprehension.Reduce development time.Reduce global coupling.

But ...We assumed that a module or component is mapped to aclass.And we insist in hiding . . .

Even when nothing needs to be hidden.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 15/97

Static versus dynamic polymorphism

Some observations

Everything should be a “method”

Why do we use classes?Information hiding principle. David Parnas (1972).

Increment flexibility and comprehension.Reduce development time.Reduce global coupling.

But ...We assumed that a module or component is mapped to aclass.And we insist in hiding . . .

Even when nothing needs to be hidden.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 15/97

Static versus dynamic polymorphism

Some observations

Class “methods”

A method from the metaclass → Shared by all instances.What is this thing?

Java

public final class Math {public static double abs(double a) {/∗...∗/}

}

// Invocationx = Math.abs(y);

C++

namespace std {double abs(double arg);

}

// Invocation

x = abs(y);

We tend to invent classes:I just need to put this in some class!

Or invent animals like Integer.Or contort main to become a method.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 16/97

Static versus dynamic polymorphism

Some observations

Class “methods”

A method from the metaclass → Shared by all instances.What is this thing?

Java

public final class Math {public static double abs(double a) {/∗...∗/}

}

// Invocationx = Math.abs(y);

C++

namespace std {double abs(double arg);

}

// Invocation

x = abs(y);

We tend to invent classes:I just need to put this in some class!

Or invent animals like Integer.Or contort main to become a method.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 16/97

Static versus dynamic polymorphism

Some observations

Class “methods”

A method from the metaclass → Shared by all instances.What is this thing?

Java

public final class Math {public static double abs(double a) {/∗...∗/}

}

// Invocationx = Math.abs(y);

C++

namespace std {double abs(double arg);

}

// Invocation

x = abs(y);

We tend to invent classes:I just need to put this in some class!

Or invent animals like Integer.Or contort main to become a method.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 16/97

Static versus dynamic polymorphism

Some observations

Class “methods”

A method from the metaclass → Shared by all instances.What is this thing?

Java

public final class Math {public static double abs(double a) {/∗...∗/}

}

// Invocationx = Math.abs(y);

C++

namespace std {double abs(double arg);

}

// Invocation

x = abs(y);

We tend to invent classes:I just need to put this in some class!

Or invent animals like Integer.Or contort main to become a method.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 16/97

Static versus dynamic polymorphism

Some observations

Class “methods”

A method from the metaclass → Shared by all instances.What is this thing?

Java

public final class Math {public static double abs(double a) {/∗...∗/}

}

// Invocationx = Math.abs(y);

C++

namespace std {double abs(double arg);

}

// Invocation

x = abs(y);

We tend to invent classes:I just need to put this in some class!

Or invent animals like Integer.

Or contort main to become a method.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 16/97

Static versus dynamic polymorphism

Some observations

Class “methods”

A method from the metaclass → Shared by all instances.What is this thing?

Java

public final class Math {public static double abs(double a) {/∗...∗/}

}

// Invocationx = Math.abs(y);

C++

namespace std {double abs(double arg);

}

// Invocation

x = abs(y);

We tend to invent classes:I just need to put this in some class!

Or invent animals like Integer.Or contort main to become a method.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 16/97

Static versus dynamic polymorphism

Some observations

Paranoid information hiding

Attributes in a class must always be private.

And then we fill up everything with getters and setters.Where is information hiding then?

A key-value entry

class entry {public:

entry( int k, const string & v);void set_key(int k) { key_=k; }int get_key() const { return key_; }void set_value(const string & v) { value_=v; }string get_value() const { return value_; }

private:int key_;string value_;

};

Or a key-value entry

struct entry {entry( int k, const string & v);int key;string value;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 17/97

Static versus dynamic polymorphism

Some observations

Paranoid information hiding

Attributes in a class must always be private.And then we fill up everything with getters and setters.

Where is information hiding then?

A key-value entry

class entry {public:

entry( int k, const string & v);void set_key(int k) { key_=k; }int get_key() const { return key_; }void set_value(const string & v) { value_=v; }string get_value() const { return value_; }

private:int key_;string value_;

};

Or a key-value entry

struct entry {entry( int k, const string & v);int key;string value;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 17/97

Static versus dynamic polymorphism

Some observations

Paranoid information hiding

Attributes in a class must always be private.And then we fill up everything with getters and setters.Where is information hiding then?

A key-value entry

class entry {public:

entry( int k, const string & v);void set_key(int k) { key_=k; }int get_key() const { return key_; }void set_value(const string & v) { value_=v; }string get_value() const { return value_; }

private:int key_;string value_;

};

Or a key-value entry

struct entry {entry( int k, const string & v);int key;string value;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 17/97

Static versus dynamic polymorphism

Some observations

Paranoid information hiding

Attributes in a class must always be private.And then we fill up everything with getters and setters.Where is information hiding then?

A key-value entry

class entry {public:

entry( int k, const string & v);void set_key(int k) { key_=k; }int get_key() const { return key_; }void set_value(const string & v) { value_=v; }string get_value() const { return value_; }

private:int key_;string value_;

};

Or a key-value entry

struct entry {entry( int k, const string & v);int key;string value;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 17/97

Static versus dynamic polymorphism

Some observations

Paranoid information hiding

Attributes in a class must always be private.And then we fill up everything with getters and setters.Where is information hiding then?

A key-value entry

class entry {public:

entry( int k, const string & v);void set_key(int k) { key_=k; }int get_key() const { return key_; }void set_value(const string & v) { value_=v; }string get_value() const { return value_; }

private:int key_;string value_;

};

Or a key-value entry

struct entry {entry( int k, const string & v);int key;string value;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 17/97

Static versus dynamic polymorphism

Some observations

Inheritance

Inheritance: Code reuse mechanism.Interface inheritance (Subtyping): Establishes an is-arelationship.Implementation inheritance: Implementation reusemechanism.

Approaches:All classes must be organized in a single universalhierarchy.

A Vector extends an AbstractList which extends anAbstractCollection which extend an Object.

Limited use of inheritance and only if really needed.A std::vector does not inherit from any other class.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 18/97

Static versus dynamic polymorphism

Some observations

Inheritance

Inheritance: Code reuse mechanism.Interface inheritance (Subtyping): Establishes an is-arelationship.Implementation inheritance: Implementation reusemechanism.

Approaches:All classes must be organized in a single universalhierarchy.

A Vector extends an AbstractList which extends anAbstractCollection which extend an Object.

Limited use of inheritance and only if really needed.A std::vector does not inherit from any other class.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 18/97

Static versus dynamic polymorphism

Some observations

Polymorphism

Polymorphism: Ability to offer the same interface withvarying implementations.

Usually a synonym for dynamic polymorphism.

Dynamic Polymorphism: Implementation selection takenat run-time (late binding).

Small overhead per function invocation.Acceptable when limited use.However additional cost derived from allocation and heapfragmentation.

Sometimes leading to designs more flexible than reallyneeded.

Just in case some day . . .

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 19/97

Static versus dynamic polymorphism

Some observations

Polymorphism

Polymorphism: Ability to offer the same interface withvarying implementations.Usually a synonym for dynamic polymorphism.

Dynamic Polymorphism: Implementation selection takenat run-time (late binding).

Small overhead per function invocation.Acceptable when limited use.However additional cost derived from allocation and heapfragmentation.

Sometimes leading to designs more flexible than reallyneeded.

Just in case some day . . .

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 19/97

Static versus dynamic polymorphism

Some observations

Polymorphism

Polymorphism: Ability to offer the same interface withvarying implementations.Usually a synonym for dynamic polymorphism.

Dynamic Polymorphism: Implementation selection takenat run-time (late binding).

Small overhead per function invocation.Acceptable when limited use.However additional cost derived from allocation and heapfragmentation.

Sometimes leading to designs more flexible than reallyneeded.

Just in case some day . . .

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 19/97

Static versus dynamic polymorphism

Some observations

There is another polymorphism

Static polymorphism: Implementation selection taken atcompile-time (early binding).

It is not always possible.Enough flexibility in many situations.No run-time overhead.

Generic sort

template <typename C>void sort(C & c) {

sort (c.begin() , c.end()) ;}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 20/97

Static versus dynamic polymorphism

Some observations

An additional problem

Resource management.Many OO languages have taken the choice of makingprogrammers life easy by means of garbage collection.

But we still have memory leaks everywhere.

Garbage collection.Generally has impact on performance.Increases impact due to the multi-core revolution.The best garbage collection strategy is not to generategarbage.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 21/97

Static versus dynamic polymorphism

Some observations

An additional problem

Resource management.Many OO languages have taken the choice of makingprogrammers life easy by means of garbage collection.

But we still have memory leaks everywhere.

Garbage collection.Generally has impact on performance.Increases impact due to the multi-core revolution.The best garbage collection strategy is not to generategarbage.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 21/97

Static versus dynamic polymorphism

Some observations

An additional problem

Resource management.Many OO languages have taken the choice of makingprogrammers life easy by means of garbage collection.

But we still have memory leaks everywhere.

Garbage collection.Generally has impact on performance.Increases impact due to the multi-core revolution.The best garbage collection strategy is not to generategarbage.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 21/97

Static versus dynamic polymorphism

Problem

1 Introduction

2 Some observations

3 Problem

4 Simple solution

5 Heterogeneous solution

6 Combining polymorphisms: Type Erasure

7 Optimizing small objects

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 22/97

Static versus dynamic polymorphism

Problem

Vector graphics

We want to represent a graphic scene with a collection ofgeometric shapes (rectangles, circles, . . . ).

All objects have a position (x,y).For simplicity we use integer coordinates.

Operations on a scene:Load from file.Store to file.Compute sum of all areas.Translate all objects (given a translation offset).Enlarge objects (given a factor).

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 23/97

Static versus dynamic polymorphism

Problem

Some utilities to consider

Generate a file with random shapes.Determine the addition of all shapes in a file.Translate all shapes in a file.Enlarge all objects in a file.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 24/97

Static versus dynamic polymorphism

Simple solution

1 Introduction

2 Some observations

3 Problem

4 Simple solution

5 Heterogeneous solution

6 Combining polymorphisms: Type Erasure

7 Optimizing small objects

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 25/97

Static versus dynamic polymorphism

Simple solution

Minimal solution

Consider that the only possible shape the rectangle.All shapes are rectangles.Position (x,y).Size (width,height).

Simplified code:A single class (rectangle).Scene contains a vector<rectangle>.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 26/97

Static versus dynamic polymorphism

Simple solution

File format

scenerectangle: 37 29 7 10rectangle: 73 100 4 5rectangle: 31 75 9 2rectangle: 84 28 7 3rectangle: 5 63 2 6end-scene

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 27/97

Static versus dynamic polymorphism

Simple solution

A rectangle

rectangle.h

class rectangle {public:

rectangle() noexcept = default;

rectangle( int x, int y, int w, int h) noexcept :x_{x}, y_{y}, width_{w}, height_{h} {}

int area() const noexcept{ return width_ ∗ height_; }

void translate ( int dx, int dy) noexcept{ x_ += dx; y_ += dy; }

void enlarge(int k) noexcept{ width_ ∗= k; height_ ∗= k; }

// ...cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 28/97

Static versus dynamic polymorphism

Simple solution

A rectangle

rectangle.h

// ...

friend std :: ostream & operator<<(std::ostream & os, const rectangle & r);friend std :: istream & operator>>(std::istream & is, rectangle & r) ;

private:int x_=0;int y_=0;int width_=0;int height_=0;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 29/97

Static versus dynamic polymorphism

Simple solution

Rectangles I/O

rectangle.cpp

std :: ostream & operator<<(std::ostream & os, const rectangle & r) {return os << r.x_ << " " << r.y_ << " "

<< r.width_ << " " << r.height_;}

std :: istream & operator>>(std::istream & is, rectangle & r) {return is >> r.x_ >> r.y_

>> r.width_ >> r.height_;}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 30/97

Static versus dynamic polymorphism

Simple solution

A scene

scene.h

class rectangle;

class scene {public:

void add_shape(const rectangle & r);int size () const noexcept { return shapes_.size(); }

long long area() const noexcept;void translate ( int dx, int dy) noexcept;void enlarge(int k) noexcept;

friend std :: ostream & operator<<(std::ostream & os, const scene & s);friend std :: istream & operator>>(std::istream & is, scene & s);

private:std :: vector<rectangle> shapes_;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 31/97

Static versus dynamic polymorphism

Simple solution

Implementing a scene

scene.cpp

void scene::add_shape(const rectangle & r) {shapes_.push_back(r);

}

long long scene::area() const noexcept {// transform_reduce(begin(shapes_), end(shapes_).// []( auto x) { return x.area() ; }// []( auto x, auto y) { return x+y; }) ;long long r = 0;for (auto && s : shapes_) {

r += s.area() ;}return r ;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 32/97

Static versus dynamic polymorphism

Simple solution

Implementing a scene

scene.cpp

void scene::translate( int dx, int dy) noexcept {for (auto && s : shapes_) {

s. translate (dx,dy);}

}

void scene::enlarge(int k) noexcept {for (auto && s : shapes_) {

s.enlarge(k);}

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 33/97

Static versus dynamic polymorphism

Simple solution

Dumping a scene

scene.cpp

std :: ostream & operator<<(std::ostream & os, const scene & s) {os << "scene\n";for (auto && s : s.shapes_) {

os << "rectangle: " << s << std ::endl;}os << "end−scene";return os;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 34/97

Static versus dynamic polymorphism

Simple solution

Reading a scene

scene.cpp

std :: istream & operator>>(std::istream & is, scene & s) {using namespace std;string w;is >> w;if (w!="scene") return is;while ( is >> w) {

if (w=="rectangle:") {rectangle r ;is >> r;s.add_shape(r);

}else if (w=="end−scene") {

return is ;}else {

is . setstate(ios_base:: failbit ) ;return is ;

}}return is ;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 35/97

Static versus dynamic polymorphism

Simple solution

Generating scenes

genscene.cpp

void generate_scene(const std::string & name, int n) {using namespace std;using namespace dsl;

cout << "Writing file " << name << endl;cout << "sizeof(rectangle)= " << sizeof(dsl :: rectangle) << endl;cout << "Generating " << n << " elements\n";

random_device rd;scene s;for ( int i=0; i<n; i++) {

auto r = random_rectangle(rd);s.add_shape(r);

}

ofstream of{name};of << s << endl;if (! of) throw runtime_error{"Cannot write to file : " + name};

cout << "Generated file " << name << " with " << n << " elements\n";}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 36/97

Static versus dynamic polymorphism

Simple solution

Computing areas

area.cpp

void print_area(const std:: string & inname) {using namespace std;using namespace dsl;

scene s;ifstream in{inname};in >> s;if (! in ) throw runtime_error{"Error reading scene file " };

cout << s.area() << endl;}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 37/97

Static versus dynamic polymorphism

Simple solution

Translating shapes

translate.cpp

void translate_scene(const std::string & inname, const std::string & outname,int dx, int dy) {

using namespace std;using namespace dsl;

cout << "Reading gfile " << inname << endl;

scene s;ifstream in{inname};in >> s;if (! in ) throw runtime_error{"Error reading scene file : " + inname};

s. translate (dx,dy);

ofstream out{outname};out << s;if (! out) throw runtime_error{"Error writing scene file " + outname};

cout << s.size () << " shapes written to file " << outname << endl;}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 38/97

Static versus dynamic polymorphism

Heterogeneous solution

1 Introduction

2 Some observations

3 Problem

4 Simple solution

5 Heterogeneous solution

6 Combining polymorphisms: Type Erasure

7 Optimizing small objects

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 39/97

Static versus dynamic polymorphism

Heterogeneous solution

Shapes may be different

Multiple types for shapes.We will restrict our example to rectangle and circle.After all this is a textbook example :-)

Classical solution:A base class: shape.One derived class per shape kind: rectangle, circle.Scene keeps a list of shapes.

We cannot store objects from different types/sizes in acontainer.We store (smart) pointers to shapes.We use std::shared_ptr to simplify memory management:

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 40/97

Static versus dynamic polymorphism

Heterogeneous solution

Designing the base class

Construction and destruction:Destructor needs to be virtual.We need to explicitly define the empty constructor.

shape.h

class shape {public:

shape() noexcept = default;virtual ~shape() noexcept = default;

shape(int x, int y) noexcept :x_{x}, y_{y} {}

private:int x_=0;int y_=0;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 41/97

Static versus dynamic polymorphism

Heterogeneous solution

Designing the base class

Position remains in the shape.Translation is managed here.Pure virtual functions to be refined in derived classes.

shape.h

// ...

void translate ( int dx, int dy) noexcept{ x_ += dx; y_ += dy; }

virtual int area() const noexcept = 0;virtual void enlarge(int k) noexcept = 0;

// ...

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 42/97

Static versus dynamic polymorphism

Heterogeneous solution

I/O

Insertion and extraction operators need to be virtualized.An operator and a pure virtual function.A function to obtain the text tag with the object type.

rectangle, circle.

shape.h

// ...

virtual std :: string tagname() const = 0;

friend std :: ostream & operator<<(std::ostream & os, const shape & r);virtual std :: ostream & insert(std :: ostream & os) const;

friend std :: istream & operator>>(std::istream & is, shape & r);virtual std :: istream & extract (std :: istream & is ) ;

// ...

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 43/97

Static versus dynamic polymorphism

Heterogeneous solution

I/O

shape.cpp

std :: ostream & shape::insert(std ::ostream & os) const {return os << x_ << ’ ’ << y_ << ’ ’ ;

}

std :: istream & shape::extract(std :: istream & is ) {return is >> x_ >> y_;

}

std :: ostream & operator<<(std::ostream & os, const shape & r) {return r . insert (os);

}

std :: istream & operator>>(std::istream & is, shape & r) {return r . extract ( is ) ;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 44/97

Static versus dynamic polymorphism

Heterogeneous solution

Deriving the rectangle

rectangle.h

class rectangle final : public shape {public:

rectangle() noexcept = default;

rectangle( int x, int y, int w, int h) :shape{x,y}, width_{w}, height_{h} {}

int area() const noexcept override{ return width_ ∗ height_; }

void enlarge(int k) noexcept override{ width_ ∗= k; height_ ∗= k; }

private:int width_=0;int height_=0;

};cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 45/97

Static versus dynamic polymorphism

Heterogeneous solution

Deriving the rectangle

rectangle.h

std :: string tagname() const override{ return "rectangle"; }

friend std :: ostream & operator<<(std::ostream & os, const rectangle & r);std :: ostream & insert(std :: ostream & os) const override;

friend std :: istream & operator>>(std::istream & is, rectangle & r) ;std :: istream & extract (std :: istream & is ) override;

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 46/97

Static versus dynamic polymorphism

Heterogeneous solution

Rectangle I/O

rectangle.cpp

std :: ostream & operator<<(std::ostream & os, const rectangle & r) {return r . insert (os);

}

std :: ostream & rectangle::insert (std :: ostream & os) const {shape::insert(os);return os << width_ << " " << height_;

}

std :: istream & operator>>(std::istream & is, rectangle & r) {return r . extract ( is ) ;

}

std :: istream & rectangle :: extract (std :: istream & is ) {shape::extract( is ) ;return is >> width_ >> height_;

}cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 47/97

Static versus dynamic polymorphism

Heterogeneous solution

Designing the scene

Polymorphic storage of shapes.Shapes are kept in a vector of pointers to the base class(shape).We use shared_ptr to get proper memory management.

Interface for adding shapes to a scene.Function add_shape() now takes an argumentshared_ptr<shape>.Argument taken as r-value reference.

It allows to take advantage of move semantics.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 48/97

Static versus dynamic polymorphism

Heterogeneous solution

A scene with polymorphic shapes

scene.hclass shape;

class scene {public:

void add_shape(std::shared_ptr<shape> && s) {shapes_.push_back(std::forward<std::shared_ptr<shape>>(s));

}int size () const noexcept { return shapes_.size(); }

long long area() const noexcept;void translate ( int dx, int dy) noexcept;void enlarge(int k) noexcept;

friend std :: ostream & operator<<(std::ostream & os, const scene & s);friend std :: istream & operator>>(std::istream & is, scene & s);

private:std :: vector<std ::shared_ptr<shape>> shapes_;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 49/97

Static versus dynamic polymorphism

Heterogeneous solution

Implementing scenes

scene.cpp

long long scene::area() const noexcept {long long r = 0;for (auto && s : shapes_) {

r += s−>area();}return r ;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 50/97

Static versus dynamic polymorphism

Heterogeneous solution

Implementing scenes

scene.cpp

void scene::translate( int dx, int dy) noexcept {for (auto && s : shapes_) {

s−>translate(dx,dy);}

}

void scene::enlarge(int k) noexcept {for (auto && s : shapes_) {

s−>enlarge(k);}

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 51/97

Static versus dynamic polymorphism

Heterogeneous solution

Writing scenes

scene.cpp

std :: ostream & operator<<(std::ostream & os, const scene & s) {os << "scene\n";for (auto && s : s.shapes_) {

os << s−>tagname() << ": ";s−>insert(os); // Polymorphic writeos << std ::endl;

}os << "end−scene";return os;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 52/97

Static versus dynamic polymorphism

Heterogeneous solution

A shape factory

scene.cpp

namespace { // Anonymous namespace

std :: shared_ptr<shape> make_shape(const std::string & cname) {using namespace std;shared_ptr<shape> p = nullptr;if (cname=="rectangle:") p = make_shared<rectangle>();else if (cname=="circle:") p = make_shared<circle>();return p;

}

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 53/97

Static versus dynamic polymorphism

Heterogeneous solution

Reading shapes

scene.cpp

std :: istream & operator>>(std::istream & is, scene & s) {using namespace std;string w;is >> w;if (w!="scene") return is;while ( is >> w) {

auto sh = make_shape(w);if (sh) {

is >> ∗sh;s.add_shape(std::move(sh));

}else if (w=="end−scene") {

return is ;}else {

is . setstate(ios_base:: failbit ) ;return is ;

}}return is ;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 54/97

Static versus dynamic polymorphism

Heterogeneous solution

Using the scenes

Changing the interface:Function add_shape() changed its interface.

Effects on code:Complexity transferred to shape developer.Objects created in dynamic memory need to be transferred.

Effects on performance:Dynamic memory higher use.

One allocation per shape.Worse processors cache behaviour.

Shapes are no longer contiguous in memory.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 55/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

1 Introduction

2 Some observations

3 Problem

4 Simple solution

5 Heterogeneous solution

6 Combining polymorphisms: Type Erasure

7 Optimizing small objects

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 56/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

Dynamic versus static polymorphism

Dynamic polymorphism:Provides extra flexibility.Requires to incorporate new classes into a class hierarchy.Exhibits higher run time cost.

Static polymorphism:Lower flexibility (although enough in many occasions).Used types may be completely unrelated.Lower run-time cost.

Virtue is the golden mean between two extremes(Aristotle).

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 57/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

Dynamic versus static polymorphism

Dynamic polymorphism:Provides extra flexibility.Requires to incorporate new classes into a class hierarchy.Exhibits higher run time cost.

Static polymorphism:Lower flexibility (although enough in many occasions).Used types may be completely unrelated.Lower run-time cost.

Virtue is the golden mean between two extremes(Aristotle).

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 57/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

Dynamic versus static polymorphism

Dynamic polymorphism:Provides extra flexibility.Requires to incorporate new classes into a class hierarchy.Exhibits higher run time cost.

Static polymorphism:Lower flexibility (although enough in many occasions).Used types may be completely unrelated.Lower run-time cost.

Virtue is the golden mean between two extremes(Aristotle).

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 57/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

Hiding polymorphism

Hide polymorphism behind a single class.Allows using completely unrelated.Hides inheritance as an implementation mechanism.

Shapes design:A generic constructor taking values from any type.A factory function for empty values.Class is move constructible but not copyable.Class hierarchy becomes an implementation private detail.A pointer to base class may hold a derived object.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 58/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A generic constructor

A generic class . . .

template <typename T>class A {public:

A(T x);// ...

};

Each instantiation leadsto a different class.

Types A<int> andA<long> are different.

. . . different from generic constructor

class A {public:

template <typename T>A(T x);// ...

};

All instantiation lead tothe same type.

Both A{x} y A{y} havetype A.

Even if x and y havedifferent types.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 59/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A generic constructor

A generic class . . .

template <typename T>class A {public:

A(T x);// ...

};

Each instantiation leadsto a different class.

Types A<int> andA<long> are different.

. . . different from generic constructor

class A {public:

template <typename T>A(T x);// ...

};

All instantiation lead tothe same type.

Both A{x} y A{y} havetype A.

Even if x and y havedifferent types.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 59/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

What is type erasure about?

A technique to allow a concrete type to hold values fromdifferent unrelated types.

Accept values from multiple types in constructor.Define wrapper classes for each of those types.Define a single base class for all wrappers.Hold a pointer to the single base classe.Delegate operations to wrappers through base classinterface.

The accepted unrelated types are erased as they are nolonger visible.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 60/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

Erasing types

Hierarchy

class wrapper_base {// ...string to_string () const;

};

class wrapper_int : public wrapper_base {// ...string to_string () const;

private:int value;

};

class wrapper_double : public wrapper_base {// ...string to_string () const;

private:double value;

};

Valueclass value {public:

value(int x) :wrapper{make_unique<wrapper_int>(x)} {}

value(double x) :wrapper{make_unique<wrapper_double>(x)} {}

string to_string () const { wrapper_−>to_string(); }

private:unique_ptr<wrapper_base> wrapper_;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 61/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A private hierarchy

Hierarcy for shape

class shape {public:

template <typename T> shape(T x);

private:class shape_base { /∗...∗/ };

template <typename T>class concrete_shape : public shape_base {

// ...private:

T impl_;};

std :: unique_ptr<shape_base> self_;};

self_ pointer holds anobject from any derivedclass.

Class shape_base mayhave pure virtualfunctions.

Virtual function redefinedin class concrete_shape.

Class concrete_shapemay delegate to objectimplementation impl_.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 62/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A polymorphic factory function

Factory function

class shape {// ...template <typename T>friend shape make_shape();// ...

};

template <typename T>shape make_shape() {

shape s;s. self_ = make_unique<

shape::concrete_shape<T>>();return s;

}

Can’t have a genericempty constructor.Factory function ismade friend to getimplementationaccess.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 63/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A shape with value semantics

shape.h

class shape {public:

shape() : self_ {nullptr} {}

template<typename T>shape(T x);

shape(const shape &) = delete;shape & operator=(const shape &) = delete;

shape(shape &&) noexcept = default;shape & operator=(shape &&) = default;

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 64/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A shape with value semantics

shape.h

std :: string tagname() const { return self_−>tagname(); }int area() const { return self_−>area(); }void translate ( int dx, int dy) { self_−>translate(dx,dy); }void enlarge(int k) {self_−>enlarge(k); }

friend std :: ostream & operator<<(std::ostream & os, const shape & s){ s. self_−>insert(os); return os; }

friend std :: istream & operator>>(std::istream & is, const shape & s){ s. self_−>extract(is) ; return is ; }

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 65/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A shape with value semantics

shape.h

private:

class shape_base {public:

shape_base() {}virtual ~shape_base() = default;virtual std :: string tagname() const = 0;virtual int area() const = 0;virtual void translate ( int dx, int dy) = 0;virtual void enlarge(int k) = 0;virtual void insert (std :: ostream & os) const = 0;virtual void extract (std :: istream & is ) = 0;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 66/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A shape with value semantics

shape.h

template <typename T>class concrete_shape final : public shape_base {public:

concrete_shape() : impl_{} {}concrete_shape(T && x) : impl_{std::forward<T>(x)} {}virtual ~concrete_shape() = default;std :: string tagname() const override { return impl_.tagname(); }int area() const override { return impl_.area(); }void translate ( int dx, int dy) override { impl_. translate (dx,dy); }void enlarge(int k) override {impl_.enlarge(k); }void insert (std :: ostream & os) const override { os << impl_; }void extract (std :: istream & is ) override { is >> impl_; }

private:T impl_;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 67/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

A shape with value semantics

shape.h

std :: unique_ptr<shape_base> self_;

template <typename U> friend shape make_shape();};

template <typename T>shape::shape(T x) :

self_ {std :: make_unique<concrete_shape<T>>(std::forward<T>(x))}{}

template<typename T>shape make_shape() {

shape s;s. self_ = std :: make_unique<shape::concrete_shape<T>>();return s;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 68/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

What about concrete classes?

Simplification:They are now classes without dependencies.They do not inherit from any other class.All member functions are now non-virtual.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 69/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

What about the scene?

scene.h

class scene {public:

void add_shape(shape && s) { shapes_.push_back(std::forward<shape>(s)); }int size () const { return shapes_.size(); }

long long area() const;void translate ( int dx, int dy);void enlarge(int k) ;

friend std :: ostream & operator<<(std::ostream & os, const scene & s);friend std :: istream & operator>>(std::istream & is, scene & s);

private:std :: vector<shape> shapes_;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 70/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

And what about client code?

Value semantics is back!

Client code

shape s = make_shape<rectangle>();myscene.add_shape(move(s));// ...

Or even better!

Client code

myscene.add_shape(make_shape<rectangle>());// ...

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 71/97

Static versus dynamic polymorphism

Combining polymorphisms: Type Erasure

And what about client code?

Value semantics is back!

Client code

shape s = make_shape<rectangle>();myscene.add_shape(move(s));// ...

Or even better!

Client code

myscene.add_shape(make_shape<rectangle>());// ...

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 71/97

Static versus dynamic polymorphism

Optimizing small objects

1 Introduction

2 Some observations

3 Problem

4 Simple solution

5 Heterogeneous solution

6 Combining polymorphisms: Type Erasure

7 Optimizing small objects

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 72/97

Static versus dynamic polymorphism

Optimizing small objects

Memory layout and performance

Type erasure based solution simplifies extension butexhibits same performance problems that object orientedversion.

Each object is allocated independently.Many individual memory allocations.Objects are not contiguously allocated.Low processor cache hit rate.

Slightly mitigated by use of make_shared():One allocation per call insted of two.Implicit use of std::allocator.Implementations sometimes use memory pools forstd::allocator.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 73/97

Static versus dynamic polymorphism

Optimizing small objects

Memory layout and performance

Type erasure based solution simplifies extension butexhibits same performance problems that object orientedversion.

Each object is allocated independently.Many individual memory allocations.Objects are not contiguously allocated.Low processor cache hit rate.

Slightly mitigated by use of make_shared():One allocation per call insted of two.Implicit use of std::allocator.Implementations sometimes use memory pools forstd::allocator.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 73/97

Static versus dynamic polymorphism

Optimizing small objects

Small object optimization

Use a fixed size buffer for each shape.If the object is very small construct directly in buffer.If object is large construct in buffer a pointer to adynamically allocated object.

Buffer type

constexpr static int size_threshold = 32;

using internal_buffer = char[size_threshold];

We may fix the buffer size to 32 bytes.Enough size for very small objects plus a vptr pointer.A size of 16 allows only extremely small objects.A size of 64 would decrease hit rate.Threshold might be application dependent.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 74/97

Static versus dynamic polymorphism

Optimizing small objects

Small object optimization

Use a fixed size buffer for each shape.If the object is very small construct directly in buffer.If object is large construct in buffer a pointer to adynamically allocated object.

Buffer type

constexpr static int size_threshold = 32;

using internal_buffer = char[size_threshold];

We may fix the buffer size to 32 bytes.Enough size for very small objects plus a vptr pointer.A size of 16 allows only extremely small objects.A size of 64 would decrease hit rate.Threshold might be application dependent.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 74/97

Static versus dynamic polymorphism

Optimizing small objects

Class hierarchy

Private classes as implementation detail.

shape_base: Base in hierarchy.Base class with pure virtual functions.Pure virtual function to move construct in a buffer withplacement (placement_move()).

local_shape<S>: Derived wrapper for small objects.Holds a member with shape S.Delegate virtual operations to that member.

dynamic_shape<S>: Derived wrapper for pointer to largeobjects.

Holds a member with pointer to allocated shape S.Delegate virtual operations to the pointed object.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 75/97

Static versus dynamic polymorphism

Optimizing small objects

private class hierarchy

shape.h

class shape {private:

// ...class shape_base { /∗ ... ∗/ };

template <typename S>class local_shape final : public shape_base { /∗ ... ∗/ };

template <typename S>class dynamic_shape final : public shape_base { /∗ ... ∗/ };

};

However:

We do not keep a pointer to the base.Instead we use a buffer where we store either a local_shape<S>or a dynamic_shape<S>.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 76/97

Static versus dynamic polymorphism

Optimizing small objects

Defining the buffer

A buffer for objects

class shape {private:

using internal_buffer = char[size_threshold];internal_buffer buffer_ ;

shape_base ∗ self() noexcept {return reinterpret_cast<shape_base∗>(&buffer_);

}// ...

};

Just need to guarantee that every shape always has avalid object derived from shape_base in its buffer_.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 77/97

Static versus dynamic polymorphism

Optimizing small objects

A base for all shapes

shape.h

class shape_base {public:

shape_base() noexcept {}virtual ~shape_base() noexcept = default;

virtual void placement_move(internal_buffer & buf) noexcept = 0;

virtual std :: string tagname() const = 0;virtual int area() const noexcept = 0;virtual void translate ( int dx, int dy) noexcept = 0;virtual void enlarge(int k) noexcept = 0;virtual std :: ostream & insert(std :: ostream & os) const noexcept = 0;virtual std :: istream & extract (std :: istream & is ) noexcept = 0;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 78/97

Static versus dynamic polymorphism

Optimizing small objects

A local shape

shape.h

template <typename S>class local_shape final : public shape_base {public:

local_shape() noexcept : impl_{} {}local_shape(S && x) noexcept : impl_{std::forward<S>(x)} {}virtual ~local_shape() noexcept = default;

virtual void placement_move(internal_buffer & buf) noexcept override;

std :: string tagname() const override { return impl_.tagname(); }int area() const noexcept override { return impl_.area(); }void translate ( int dx, int dy) noexcept override { impl_.translate(dx,dy); }void enlarge(int k) noexcept override {impl_.enlarge(k); }std :: ostream & insert(std :: ostream & os) const noexcept override { return os << impl_; }std :: istream & extract (std :: istream & is ) noexcept override { return is >> impl_; }

private:S impl_;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 79/97

Static versus dynamic polymorphism

Optimizing small objects

A dynamic shape

shape.h

template <typename S>class dynamic_shape final : public shape_base {public:

dynamic_shape() : impl_{std::make_unique<S>()} {}dynamic_shape(S && s) : impl_{std::make_unique<S>(std::forward<S>(s))} {}dynamic_shape(std::unique_ptr<S> && p) noexcept : impl_{std::forward<std::unique_ptr<S>>(p)} {}virtual ~dynamic_shape() noexcept = default;

virtual void placement_move(internal_buffer & buf) noexcept override;

std :: string tagname() const noexcept override { return impl_−>tagname(); }int area() const noexcept override { return impl_−>area(); }void translate ( int dx, int dy) noexcept override { impl_−>translate(dx,dy); }void enlarge(int k) noexcept override {impl_−>enlarge(k); }std :: ostream & insert(std :: ostream & os) const noexcept override { return os << ∗impl_; }std :: istream & extract (std :: istream & is ) noexcept override { return is >> ∗impl_; }

private:std :: unique_ptr<S> impl_;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 80/97

Static versus dynamic polymorphism

Optimizing small objects

Placement move

Move construct an object into a given buffer.Operation is virtualized.

shape.h

template <typename S>void shape::local_shape<S>::placement_move(internal_buffer & buf) noexcept {

new (&buf) local_shape<S>(std::move(impl_));}

template <typename S>void shape::dynamic_shape<S>::placement_move(internal_buffer & buf) noexcept {

new (&buf) dynamic_shape<S>(std::move(impl_));}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 81/97

Static versus dynamic polymorphism

Optimizing small objects

Support for concepts-like

shape.h

template <typename T>static constexpr bool is_small() {

return sizeof(local_shape<T>) <= size_threshold;}

template <typename T>using Small = typename std::enable_if<is_small<T>(), shape>::type;

template <typename T>using Large = typename std::enable_if<(!is_small<T>()), shape>::type;

is_small<T>() is a predicate on type T to verify if it is small.Small<T> is type shape only if T is small.Large<T> is type shape only if T is not small.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 82/97

Static versus dynamic polymorphism

Optimizing small objects

Selecting shapes move

shape.h

template <typename S,Small<S> ∗ = nullptr>

shape(S && s) noexcept {new (&buffer_) local_shape<S>{std::forward<S>(s)};

}

template <typename S,Large<S> ∗ = nullptr>

shape(S && s) noexcept {new (&buffer_) dynamic_shape<S>{std::forward<S>(s)};

}

Depending on size of T only one of them really exists.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 83/97

Static versus dynamic polymorphism

Optimizing small objects

Simulating an empty selective constructor

shape.h

template <typename S>friend Small<S> make_shape() noexcept;

template <typename S>friend Large<S> make_shape() noexcept;

Allows to simulate an empty constructor with templateargument.make_shape() is a friend factory function.

Needs access to private empty constructor.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 84/97

Static versus dynamic polymorphism

Optimizing small objects

Implementing factory functions

shape.h

template <typename S>shape::Small<S> make_shape() noexcept {

shape s;new (&s.buffer_) shape::local_shape<S>{};return s;

}

template <typename S>shape::Large<S> make_shape() noexcept {

shape s;new (&s.buffer_) shape::dynamic_shape<S>{};return s;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 85/97

Static versus dynamic polymorphism

Optimizing small objects

Copy, move and destruction

shape.h

shape(const shape &) noexcept = delete;shape & operator=(const shape &) noexcept = delete;

shape(shape && s) noexcept {s. self ()−>placement_move(buffer_);

}

shape & operator=(shape &&) noexcept = delete;

~shape() noexcept {self ()−>~shape_base();

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 86/97

Static versus dynamic polymorphism

Optimizing small objects

Delegated functionality

shape.h

std :: string tagname() const { return self()−>tagname(); }int area() const noexcept { return self()−>area(); }void translate ( int dx, int dy) noexcept { self()−>translate(dx,dy); }void enlarge(int k) noexcept {self()−>enlarge(k); }

friend std :: ostream & operator<<(std::ostream & os, const shape & s){ return s. self ()−>insert(os); }

friend std :: istream & operator>>(std::istream & is, shape & s){ return s. self ()−>extract(is) ; }

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 87/97

Static versus dynamic polymorphism

Optimizing small objects

A simplified scene (again)

scene.h

class scene {public:

void add_shape(shape && s) { shapes_.push_back(std::forward<shape>(s)); }int size () const noexcept { return shapes_.size(); }

long long area() const noexcept ;void translate ( int dx, int dy) noexcept ;void enlarge(int k) noexcept;

friend std :: ostream & operator<<(std::ostream & os, const scene & s);friend std :: istream & operator>>(std::istream & is, scene & s);

private:std :: vector<shape> shapes_;

};

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 88/97

Static versus dynamic polymorphism

Optimizing small objects

Memory allocations

Classic: 25 memory allocations.

Object Oriented: 1,000,025 memory allocations.Type erased: 1,000,028 memory allocations.Type erased small object (size=16): 1,000,028 memoryallocations.Type erased small object (size=32): 28 memoryallocations.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 89/97

Static versus dynamic polymorphism

Optimizing small objects

Memory allocations

Classic: 25 memory allocations.Object Oriented: 1,000,025 memory allocations.

Type erased: 1,000,028 memory allocations.Type erased small object (size=16): 1,000,028 memoryallocations.Type erased small object (size=32): 28 memoryallocations.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 89/97

Static versus dynamic polymorphism

Optimizing small objects

Memory allocations

Classic: 25 memory allocations.Object Oriented: 1,000,025 memory allocations.Type erased: 1,000,028 memory allocations.

Type erased small object (size=16): 1,000,028 memoryallocations.Type erased small object (size=32): 28 memoryallocations.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 89/97

Static versus dynamic polymorphism

Optimizing small objects

Memory allocations

Classic: 25 memory allocations.Object Oriented: 1,000,025 memory allocations.Type erased: 1,000,028 memory allocations.Type erased small object (size=16): 1,000,028 memoryallocations.

Type erased small object (size=32): 28 memoryallocations.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 89/97

Static versus dynamic polymorphism

Optimizing small objects

Memory allocations

Classic: 25 memory allocations.Object Oriented: 1,000,025 memory allocations.Type erased: 1,000,028 memory allocations.Type erased small object (size=16): 1,000,028 memoryallocations.Type erased small object (size=32): 28 memoryallocations.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 89/97

Static versus dynamic polymorphism

Optimizing small objects

Global execution time (area computation)

1k 10k 100k 1m 10m

100

101

102

103

Size

Exe

cutio

ntim

e(s

)

simpleobject-oriented

type erasedsmall size=16small size=32

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 90/97

Static versus dynamic polymorphism

Optimizing small objects

Global execution time (area computation)

10m0

1,000

2,000

3,000

Size

Exe

cutio

ntim

e(s

)

simpleobject-oriented

type erasedsmall size=16small size=32

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 91/97

Static versus dynamic polymorphism

Optimizing small objects

Normalized execution time (10 million elements)

Classic: 1.0Object Oriented: 1.20Type erased: 1.13Type erased small object (size=16): 1.22Type erased small object (size=32): 1.04

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 92/97

Static versus dynamic polymorphism

Optimizing small objects

Summary

Performance more critical now than object orientationbecame popular.

Forget dogmatism! Go back to principles!

Polymorphism is not necessarily dynamic polymorphism.

We also have static polymorphism.

Dynamic polymorphism implies in practice many smallmemory allocations.

Type erasure simplifies interfaces.

Small object optimization increases performance.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 93/97

Static versus dynamic polymorphism

Optimizing small objects

Summary

Performance more critical now than object orientationbecame popular.

Forget dogmatism! Go back to principles!

Polymorphism is not necessarily dynamic polymorphism.

We also have static polymorphism.

Dynamic polymorphism implies in practice many smallmemory allocations.

Type erasure simplifies interfaces.

Small object optimization increases performance.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 93/97

Static versus dynamic polymorphism

Optimizing small objects

Summary

Performance more critical now than object orientationbecame popular.

Forget dogmatism! Go back to principles!

Polymorphism is not necessarily dynamic polymorphism.

We also have static polymorphism.

Dynamic polymorphism implies in practice many smallmemory allocations.

Type erasure simplifies interfaces.

Small object optimization increases performance.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 93/97

Static versus dynamic polymorphism

Optimizing small objects

Summary

Performance more critical now than object orientationbecame popular.

Forget dogmatism! Go back to principles!

Polymorphism is not necessarily dynamic polymorphism.We also have static polymorphism.

Dynamic polymorphism implies in practice many smallmemory allocations.

Type erasure simplifies interfaces.

Small object optimization increases performance.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 93/97

Static versus dynamic polymorphism

Optimizing small objects

Summary

Performance more critical now than object orientationbecame popular.

Forget dogmatism! Go back to principles!

Polymorphism is not necessarily dynamic polymorphism.We also have static polymorphism.

Dynamic polymorphism implies in practice many smallmemory allocations.

Type erasure simplifies interfaces.

Small object optimization increases performance.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 93/97

Static versus dynamic polymorphism

Optimizing small objects

Summary

Performance more critical now than object orientationbecame popular.

Forget dogmatism! Go back to principles!

Polymorphism is not necessarily dynamic polymorphism.We also have static polymorphism.

Dynamic polymorphism implies in practice many smallmemory allocations.

Type erasure simplifies interfaces.

Small object optimization increases performance.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 93/97

Static versus dynamic polymorphism

Optimizing small objects

Summary

Performance more critical now than object orientationbecame popular.

Forget dogmatism! Go back to principles!

Polymorphism is not necessarily dynamic polymorphism.We also have static polymorphism.

Dynamic polymorphism implies in practice many smallmemory allocations.

Type erasure simplifies interfaces.

Small object optimization increases performance.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 93/97

Static versus dynamic polymorphism

Optimizing small objects

A word on concepts

Concepts TS simplifies generic programming.

Concepts based programming

template <typename T>concept bool Small = sizeof(local_shape<T>) <= size_threshold;

template <Small S>shape make_shape() noexcept {

shape s;new (&s.buffer_) shape::local_shape<S>{};return s;

}

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 94/97

Static versus dynamic polymorphism

Optimizing small objects

A word about alignment

We can make sure that the buffer in shape is aligned.

Aligned buffer

using internal_buffer = typename std::aligned_buffer<size_threshold,size_threshold>::type;

However:C++14 does not guarantee allocation of over-aligned data.We cannot guarantee that a std::vector<shape> will be aligned.Unless we use a platform specific allocator(tbb::cache_aligned_allocator).C++17 solves this issue.

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 95/97

Static versus dynamic polymorphism

Optimizing small objects

Source code available

github.com/jdgarciauc3m/polyexamples

How to find me:

Twitter: @jdgarciauc3m

Web: www.arcos.inf.uc3m.es/wp/jdgarcia

E-mail: josedaniel.garcia@uc3m.es

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 96/97

Static versus dynamic polymorphism

Optimizing small objects

Static versus dynamic polymorphismFlexibility versus performance

J. Daniel Garcia

ARCOS GroupUniversity Carlos III of Madrid

Spain

December 2, 2016

cbed – J. Daniel Garcia – ARCOS@UC3M (josedaniel.garcia@uc3m.es) – Twitter: @jdgarciauc3m 97/97