SlideShare a Scribd company logo
1 of 93
Download to read offline
ACCU 2015
PROJECT
DATE CONFERENCE
23 APRIL
PREMATURE OPTIMISATION WORKSHOP
ARJAN VAN LEEUWEN
WWW.OPERA.COM
JOIN THE COOL KIDS ON THE INFORMATION SUPERHIGHWAY
ACCU 2015
PROJECT
DATE CONFERENCE
23 APRIL
PREMATURE OPTIMISATION WORKSHOP
ARJAN VAN LEEUWEN
A short conversation
OPTIMISING IS FUN
AND KNOWING HOW TO DO IT CAN BE USEFUL
PREMATURE
OPTIMISATION
IS THE ROOT OF
ALL EVIL
DONALD KNUTH,
“STRUCTURED
PROGRAMMING WITH GOTO
STATEMENTS”
PROGRAMMERS WASTE ENORMOUS AMOUNTS OF
TIME THINKING ABOUT, OR WORRYING ABOUT, THE
SPEED OF NONCRITICAL PARTS OF THEIR
PROGRAMS, AND THESE ATTEMPTS AT
EFFICIENCY ACTUALLY HAVE A STRONG NEGATIVE
IMPACT WHEN DEBUGGING AND MAINTENANCE
ARE CONSIDERED.
WE SHOULD FORGET ABOUT SMALL EFFICIENCIES,
SAY ABOUT 97% OF THE TIME: PREMATURE
OPTIMISATION IS THE ROOT OF ALL EVIL.
YET WE SHOULD NOT PASS UP OUR
OPPORTUNITIES IN THAT CRITICAL 3%.
“
”
IN ESTABLISHED ENGINEERING
DISCIPLINES A 12%
IMPROVEMENT, EASILY OBTAINED,
IS NEVER CONSIDERED MARGINAL
AND I BELIEVE THE SAME
VIEWPOINT SHOULD PREVAIL IN
SOFTWARE ENGINEERING.
“
”
SMALL THINGS CAN MAKE A DIFFERENCE
AND ARE WORTH STUDYING
Goals
Find small changes that can
make a difference

Don’t sacrifice elegance for
speed

Give ideas on how to
optimise
In the toolbox
Common sense (doing
nothing is always faster)

Disassembler

Time measurement

Profiling tools
MICRO-OPTIMISATIONS IN C++
C++
Close to the metal

Object model well-defined [Lippman96]

Efficiency has been a major design goal for C++
from the beginning

“You don’t pay for what you don’t use”

Benefits from years of C optimisation experience
Branches
Basis of much we do in
imperative languages

Compare and branch
if-else-if
void GetAndProcessResult() {
if (GetResult() == DOWNLOADED)
return ProcessDownloadedFile();
else if (GetResult() == NEEDS_DOWNLOAD)
return DownloadFile();
else if (GetResult() == NOT_AVAILABLE)
return ReportNotAvailable();
else if (GetResult() == ERROR)
return ReportError();
}
if-else-if
void GetAndProcessResult() {
const int result = GetResult();
if (result == DOWNLOADED)
return ProcessDownloadedFile();
else if (result == NEEDS_DOWNLOAD)
return DownloadFile();
else if (result == NOT_AVAILABLE)
return ReportNotAvailable();
else if (result == ERROR)
return ReportError();
}
if-else-if switch!
void GetAndProcessResult() {
switch (GetResult()) {
case DOWNLOADED:
return ProcessDownloadedFile();
case NEEDS_DOWNLOAD:
return DownloadFile();
case NOT_AVAILABLE:
return ReportNotAvailable();
case ERROR:
return ReportError();
}
}
The joys of switch
Clarifies intention

Clearer warnings / error messages

Always allows compiler to create jump table or do
binary search

O(1) lookups
Jump table
void GetAndProcessResult() {
switch (GetResult()) {
case DOWNLOADED:
return ProcessDownloadedFile();
case NEEDS_DOWNLOAD:
return DownloadFile();
case NOT_AVAILABLE:
return ReportNotAvailable();
case ERROR:
return ReportError();
}
}
Jump table
void GetAndProcessResult() {
switch (GetResult()) {
}
}
case 0:
return ProcessDownloadedFile();
case 1:
return DownloadFile();
case 2:
return ReportNotAvailable();
case 3:
return ReportError();
Jump table
case 0: return ProcessDownloadedFile();
case 1: return DownloadFile();
case 2: return ReportNotAvailable();
case 3: return ReportError();
Jump table
void GetAndProcessResult() {
switch (GetResult()) {
}
}
case 0:
return ProcessDownloadedFile();
case 1:
return DownloadFile();
case 2:
return ReportNotAvailable();
case 3:
return ReportError();
Jump table
void GetAndProcessResult() {
switch (GetResult()) {
case 102:
return ProcessDownloadedFile();
case 103:
return DownloadFile();
case 104:
return ReportNotAvailable();
case 105:
return ReportError();
}
}
Jump table
void GetAndProcessResult() {
switch (GetResult()) {
case 102+0:
return ProcessDownloadedFile();
case 102+1:
return DownloadFile();
case 102+2:
return ReportNotAvailable();
case 102+3:
return ReportError();
}
}
Jump table?
void GetAndProcessResult() {
switch (GetResult()) {
case 1:
return ProcessDownloadedFile();
case 16:
return DownloadFile();
case 88:
return ReportNotAvailable();
case 65536:
return ReportError();
}
}
Jump table Binary search
void GetAndProcessResult() {
switch (GetResult()) {
case 1:
return ProcessDownloadedFile();
case 16:
return DownloadFile();
case 88:
return ReportNotAvailable();
case 65536:
return ReportError();
}
}
Compilers are smart
Predicting branches
Predicting branches is hard

Automated mechanisms (profile-guided
optimisations) can offer big gains at the cost of
having to profile your build

If you’re very certain of your case, some compilers
offer instructions such as __builtin_expect
(gcc, clang)
Strings
Most used and mis-used
type in programming

Mutable strings are the root
of all evil
Strings misuse
String is not a basic type

A mutable string is a dynamic array of characters

Almost anything you can do with a string is a
function of the characters in that string

Think about what will happen with long strings
Using std::string
Be careful with modifying operations such as
append()

Avoid creating a string out of many parts, better to
create at once

Look into when alternative string types are useful
Growing strings
std::string CopyString(
const char* to_copy, size_t length) {
std::string copied;
for (size_t i = 0; i < length; i += BLOCKSIZE)
copied.append(to_copy + i,
std::min(BLOCKSIZE, length - i));
return copied;
}
Growing strings
std::string CopyString(
const char* to_copy, size_t length) {
std::stringstream copied;
for (size_t i = 0; i < length; i += BLOCKSIZE)
copied.write(to_copy + i,
std::min(BLOCKSIZE, length - i));
return copied.str();
}
Growing strings
std::string CopyString(
const char* to_copy, size_t length) {
std::string copied;
copied.reserve(length);
for (size_t i = 0; i < length; i += BLOCKSIZE)
copied.append(to_copy + i,
std::min(BLOCKSIZE, length - i));
return copied;
}
Growing strings
Method Time spent, 3 run average (ms)
std::string::append() 1399
std::stringstream 5102
std::string::append() with
std::string::reserve()
851
Converting numbers to
strings and vice versa
Can be a major source of slowness

Often more features than needed

Investigate alternative libraries (boost::spirit)

Writing specialised functions a possibility (but with
its own maintainability issues)
Integer-to-string conversion
std::string Convert(int i) {
std::stringstream stream;
stream << i;
return stream.str();
}
Integer-to-string conversion
std::string Convert(int i) {
return std::to_string(i);
}
Integer-to-string conversion
std::string Convert(int i) {
namespace karma = boost::spirit::karma;
std::string converted;
std::back_insert_iterator<std::string>
sink(converted);
karma::generate(sink, karma::int_, i);
return converted;
}
Integer-to-string conversion
Method Time spent, 3 run average (ms)
std::stringstream 2959
std::to_string 1012
boost::spirit::karma 332
String-to-integer
conversion
int Convert(const std::string& str) {
return std::stoi(str);
}
String-to-integer
conversion
int Convert(const std::string& str) {
namespace qi = boost::spirit::qi;
int converted;
qi::parse(str.begin(), str.end(),
qi::int_, converted);
return converted;
}
String-to-integer
conversion
Method Time spent, 3 run average (ms)
std::stoi 3920
boost::spirit::qi 1276
Function calls
Function calls have
overhead

Lookup in virtual function
table

Setting up stack, restoring
stack
Avoiding virtual functions or
virtual function calls
Only declare functions (this includes destructors)
virtual when it’s actually needed

Don’t use virtual functions for types that are
handled by value

If type is known, no lookup is needed

Sometimes compile-time polymorphism offers an
alternative
Avoiding function calls
For small functions called in tight loops, inlining
helps

Allow the compiler to inline functions where it
makes sense (have definition available)

If the compiler doesn’t co-operate and you’re sure
it makes sense (measure this), force it
Tail calls
A tail call happens when a function is the final call
made in another function

Tail calls can be eliminated, so that they end up
being a jump construction

Eliminates call overhead

Be aware of this and create tail calls where possible

Also allows efficient recursive functions
Facilitating tail calls
unsigned djb_hash(const char* string) {
int c = *string;
if (!c)
return 5381;
return djb_hash(string + 1) * 33 + c;
}
Facilitating tail calls
unsigned djb_hash(
const char* string, unsigned seed) {
int c = *string;
if (!c)
return seed;
return djb_hash(
string + 1, seed * 33 + c);
}
Facilitating tail calls
Method Time spent, 3 run average (ms)
Tail call elimination not possible 2274
Tail call elimination possible 1097
Use lambda functions
C++11 lambdas can always be trivially inlined,
unlike function pointers

Offers an elegant and fast way of processing data

Combines well with aggregate functions
Use lambda functions
void twice(int& value) {
value *= 2;
}
std::vector<int> EverythingTwice(
const std::vector<int>& original) {
std::vector<int> result(original);
std::for_each(result.begin(), result.end(),
&twice);
return result;
}
Use lambda functions
std::vector<int> EverythingTwice2(
const std::vector<int>& original) {
std::vector<int> result(original);
std::for_each(result.begin(), result.end(),
[](int& value){ value *= 2; });
return result;
}
Use lambda functions
Method Time spent, 3 run average (ms)
Function pointer (not inlined) 1684
Lambda function (inlined) 220
Return-value optimisation
Allows the compiler to avoid copy construction on
temporaries

Executed by compilers when function returns one
named variable 

Be aware of where it could be possible, allow the
compiler to help you

But sometimes it’s more helpful to implement…
Move semantics
User defines for movable types how they can be
moved correctly

‘Guaranteed’ way of getting return value
optimisation

Helpful in combination with std::vector (to keep
data local)

Can come for free using “Rule of zero”
Move semantics
class Typical {
public:
Typical()
: content_("this is a typical string") {}
Typical(const Typical& other)
: content_(other.content_) {}
private:
std::string content_;
};
Move semantics
class Typical {
public:
TypicalMove ()
: content_("this is a typical string") {}
private:
std::string content_;
};
Move semantics
std::vector<Typical> CreateTypical() {
std::vector<Typical> new_content;
for (int i = 0; i < 1024; ++i)
new_content.push_back(Typical());
return new_content;
}
Move semantics
Method Time spent, 3 run average (ms)
With copy constructor 2617
Following “Rule of zero” 1002
Data
Make sure that all data you
need in a loop is physically
as close together as possible

Allows CPU to use its cache
efficiently

Use contiguous memory
arrays where possible

Avoid data structures that
rely on pointers (eg. linked
lists)
Data
int sum() {
std::forward_list<int> data(1024, 5);
int result;
for (int i = 0; i < 1000000; ++i) {
result = std::accumulate(
data.begin(), data.end(), 0);
}
return result;
}
Data
int sum() {
std::vector<int> data(1024, 5);
int result;
for (int i = 0; i < 1000000; ++i) {
result = std::accumulate(
data.begin(), data.end(), 0);
}
return result;
}
Data
Method Time spent, 3 run average (ms)
std::forward_list 1115
std::vector 61
MICRO-OPTIMISATIONS IN PYTHON
Python
Emphasises readability

Dynamic type system, automatic memory
management

Several projects dedicated to improving
performance

Always try to avoid calling functions many times
Prefer literals over
“constructors”
def a():
return dict(firstkey=1, secondkey=2)
Prefer literals over
“constructors”
def a():
return dict(firstkey=1, secondkey=2)
def b():
return { 'firstkey': 1, 'secondkey': 2 }
Prefer literals over
“constructors”
Method Time spent, 3 run minimum (ms)
dict() 376
Dictionary literals 135
Prefer slice notation over
“copy constructor”
l = [ 'a', 'b', 'c', 'd', 'e', 'f' ]
def a():
return list(l)
Prefer slice notation over
“copy constructor”
l = [ 'a', 'b', 'c', 'd', 'e', 'f' ]
def a():
return list(l)
def b():
return l[:]
Prefer slice notation over
“copy constructor”
Method Time spent, 3 run minimum (ms)
Copy via list() 2671
Slice notation 1679
All functions have overhead
Function call overhead in Python is substantial

All functions can be redefined - even built-ins need
to be looked up first

Try to avoid function calls (even more so than in

C++)

Using literals or other built-in constructs can help
avoid function calls
String formatting
Python has a built-in function str() to convert
other types to string

In most cases this offers enough features for
conversions of types to strings

Faster than formatting
String formatting
def a():
a = 5
b = 2
c = 3
return "%d" % (a*(b+c))
String formatting
def a():
a = 5
b = 2
c = 3
return "%d" % (a*(b+c))
def b():
a = 5
b = 2
c = 3
return str(a*(b+c))
String formatting
def a():
a = 5
b = 2
c = 3
return "%d" % (a*(b+c))
def c():
a = 5
b = 2
c = 3
return "%s" % (a*(b+c))
Method Time spent, 3 run minimum (ms)
“%d” 514
str() 260
“%s” 233
String formatting
Prefer aggregate functions
def a():
s = 0;
for i in range(50000):
s += i
return s
Prefer aggregate functions
def a():
s = 0;
for i in range(50000):
s += i
return s
def b():
return sum(range(50000))
Method Time spent, 3 run minimum (ms)
Summing manually 1728
Using sum() 587
Prefer aggregate functions
Prefer aggregate functions
Python has a number of built-in functions for
aggregates: all(), min(), max(), sum(), etc

Using them brings big speed advantages

Always preferred over manually iterating
Use list comprehensions
def a():
l = []
for i in range(1000):
l.append(i)
return l
Use list comprehensions
def a():
l = []
for i in range(1000):
l.append(i)
return l
def b():
return [i for i in range(1000)]
Method Time spent, 3 run minimum (ms)
Append to list 701
List comprehension 321
Use list comprehensions
List comprehensions offer a concise way of
creating lists

Speed as well as readability advantages

Can be nested as well!
Use list comprehensions
Don’t use optimisations
from other languages
def a():
x = 1;
for i in range(1000):
x = x + x
return x
Don’t use optimisations
from other languages
def b():
x = 1;
for i in range(1000):
x = x * 2
return x
Don’t use optimisations
from other languages
def c():
x = 1;
for i in range(1000):
x = x << 1
return x
Method Time spent, 3 run minimum (ms)
x + x 736
x * 2 1001
x << 1 1342
Don’t use optimisations
from other languages
LET’S TRY IT
PREPARE YOUR LAPTOPS!
PYTHON: WWW.CYBER-
DOJO.ORG 

E94905
C++:
git clone https://github.com/
avl7771/premature_optimization.git
Conclusions
Optimising is fun!

Knowledge about optimisations can help you help
your compiler or interpreter

Not all optimisations worsen maintainability

Micro-optimisations can differ between languages,
compilers, architectures… Measuring works!

Test your assumptions
ARJAN VAN LEEUWEN
@AVL7771

More Related Content

What's hot

Go concurrency
Go concurrencyGo concurrency
Go concurrencysiuyin
 
Scaling Rails with Ruby-prof -- Ruby Conf Kenya 2017 by Ben Hughes
Scaling Rails with Ruby-prof -- Ruby Conf Kenya 2017 by Ben Hughes Scaling Rails with Ruby-prof -- Ruby Conf Kenya 2017 by Ben Hughes
Scaling Rails with Ruby-prof -- Ruby Conf Kenya 2017 by Ben Hughes Michael Kimathi
 
Gabriele Petronella - FP for front-end development: should you care? - Codemo...
Gabriele Petronella - FP for front-end development: should you care? - Codemo...Gabriele Petronella - FP for front-end development: should you care? - Codemo...
Gabriele Petronella - FP for front-end development: should you care? - Codemo...Codemotion
 
Whats new in ES2019
Whats new in ES2019Whats new in ES2019
Whats new in ES2019chayanikaa
 
Leap Ahead with Redis 6.2
Leap Ahead with Redis 6.2Leap Ahead with Redis 6.2
Leap Ahead with Redis 6.2VMware Tanzu
 
Rust Intro @ Roma Rust meetup
Rust Intro @ Roma Rust meetup Rust Intro @ Roma Rust meetup
Rust Intro @ Roma Rust meetup Claudio Capobianco
 
chapter 5 Java at rupp cambodia
chapter 5 Java at rupp cambodiachapter 5 Java at rupp cambodia
chapter 5 Java at rupp cambodiaSami Mut
 
Homomorphic encryption and Private Machine Learning Classification
Homomorphic encryption and Private Machine Learning ClassificationHomomorphic encryption and Private Machine Learning Classification
Homomorphic encryption and Private Machine Learning ClassificationMohammed Ashour
 
Lattice-Based Cryptography: CRYPTANALYSIS OF COMPACT-LWE
Lattice-Based Cryptography: CRYPTANALYSIS OF COMPACT-LWELattice-Based Cryptography: CRYPTANALYSIS OF COMPACT-LWE
Lattice-Based Cryptography: CRYPTANALYSIS OF COMPACT-LWEPriyanka Aash
 
Cryptography Using Laplace Transform
Cryptography Using Laplace TransformCryptography Using Laplace Transform
Cryptography Using Laplace TransformIJERA Editor
 
Partial Homomorphic Encryption
Partial Homomorphic EncryptionPartial Homomorphic Encryption
Partial Homomorphic Encryptionsecurityxploded
 

What's hot (15)

Go concurrency
Go concurrencyGo concurrency
Go concurrency
 
Scaling Rails with Ruby-prof -- Ruby Conf Kenya 2017 by Ben Hughes
Scaling Rails with Ruby-prof -- Ruby Conf Kenya 2017 by Ben Hughes Scaling Rails with Ruby-prof -- Ruby Conf Kenya 2017 by Ben Hughes
Scaling Rails with Ruby-prof -- Ruby Conf Kenya 2017 by Ben Hughes
 
Gabriele Petronella - FP for front-end development: should you care? - Codemo...
Gabriele Petronella - FP for front-end development: should you care? - Codemo...Gabriele Petronella - FP for front-end development: should you care? - Codemo...
Gabriele Petronella - FP for front-end development: should you care? - Codemo...
 
Scala to assembly
Scala to assemblyScala to assembly
Scala to assembly
 
Overview of MONOMI
Overview of MONOMIOverview of MONOMI
Overview of MONOMI
 
Whats new in ES2019
Whats new in ES2019Whats new in ES2019
Whats new in ES2019
 
Leap Ahead with Redis 6.2
Leap Ahead with Redis 6.2Leap Ahead with Redis 6.2
Leap Ahead with Redis 6.2
 
Rust Intro @ Roma Rust meetup
Rust Intro @ Roma Rust meetup Rust Intro @ Roma Rust meetup
Rust Intro @ Roma Rust meetup
 
同態加密
同態加密同態加密
同態加密
 
chapter 5 Java at rupp cambodia
chapter 5 Java at rupp cambodiachapter 5 Java at rupp cambodia
chapter 5 Java at rupp cambodia
 
Homomorphic encryption and Private Machine Learning Classification
Homomorphic encryption and Private Machine Learning ClassificationHomomorphic encryption and Private Machine Learning Classification
Homomorphic encryption and Private Machine Learning Classification
 
Project in programming
Project in programmingProject in programming
Project in programming
 
Lattice-Based Cryptography: CRYPTANALYSIS OF COMPACT-LWE
Lattice-Based Cryptography: CRYPTANALYSIS OF COMPACT-LWELattice-Based Cryptography: CRYPTANALYSIS OF COMPACT-LWE
Lattice-Based Cryptography: CRYPTANALYSIS OF COMPACT-LWE
 
Cryptography Using Laplace Transform
Cryptography Using Laplace TransformCryptography Using Laplace Transform
Cryptography Using Laplace Transform
 
Partial Homomorphic Encryption
Partial Homomorphic EncryptionPartial Homomorphic Encryption
Partial Homomorphic Encryption
 

Similar to ACCU 2015 Premature Optimisation Workshop

Object oriented programming system with C++
Object oriented programming system with C++Object oriented programming system with C++
Object oriented programming system with C++msharshitha03s
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184Mahmoud Samir Fayed
 
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdfProgramming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdfssuser6254411
 
Compiler optimizations based on call-graph flattening
Compiler optimizations based on call-graph flatteningCompiler optimizations based on call-graph flattening
Compiler optimizations based on call-graph flatteningCAFxX
 
Optimization in Programming languages
Optimization in Programming languagesOptimization in Programming languages
Optimization in Programming languagesAnkit Pandey
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestPavan Chitumalla
 
OOPS USING C++(UNIT 2)
OOPS USING C++(UNIT 2)OOPS USING C++(UNIT 2)
OOPS USING C++(UNIT 2)SURBHI SAROHA
 
Performance measurement and tuning
Performance measurement and tuningPerformance measurement and tuning
Performance measurement and tuningAOE
 
2.overview of c++ ________lecture2
2.overview of c++  ________lecture22.overview of c++  ________lecture2
2.overview of c++ ________lecture2Warui Maina
 
Numerical tour in the Python eco-system: Python, NumPy, scikit-learn
Numerical tour in the Python eco-system: Python, NumPy, scikit-learnNumerical tour in the Python eco-system: Python, NumPy, scikit-learn
Numerical tour in the Python eco-system: Python, NumPy, scikit-learnArnaud Joly
 
3.Process Management
3.Process Management3.Process Management
3.Process ManagementSenthil Kanth
 

Similar to ACCU 2015 Premature Optimisation Workshop (20)

Code optimization
Code optimization Code optimization
Code optimization
 
Code optimization
Code optimization Code optimization
Code optimization
 
Object oriented programming system with C++
Object oriented programming system with C++Object oriented programming system with C++
Object oriented programming system with C++
 
Oop object oriented programing topics
Oop object oriented programing topicsOop object oriented programing topics
Oop object oriented programing topics
 
Legacy is Good
Legacy is GoodLegacy is Good
Legacy is Good
 
Writing Faster Python 3
Writing Faster Python 3Writing Faster Python 3
Writing Faster Python 3
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Code Tuning
Code TuningCode Tuning
Code Tuning
 
The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184The Ring programming language version 1.5.3 book - Part 89 of 184
The Ring programming language version 1.5.3 book - Part 89 of 184
 
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdfProgramming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
Programming For Big Data [ Submission DvcScheduleV2.cpp and StaticA.pdf
 
Compiler optimizations based on call-graph flattening
Compiler optimizations based on call-graph flatteningCompiler optimizations based on call-graph flattening
Compiler optimizations based on call-graph flattening
 
Optimization in Programming languages
Optimization in Programming languagesOptimization in Programming languages
Optimization in Programming languages
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
OOPS USING C++(UNIT 2)
OOPS USING C++(UNIT 2)OOPS USING C++(UNIT 2)
OOPS USING C++(UNIT 2)
 
Performance measurement and tuning
Performance measurement and tuningPerformance measurement and tuning
Performance measurement and tuning
 
2.overview of c++ ________lecture2
2.overview of c++  ________lecture22.overview of c++  ________lecture2
2.overview of c++ ________lecture2
 
Saving lives with rx java
Saving lives with rx javaSaving lives with rx java
Saving lives with rx java
 
Numerical tour in the Python eco-system: Python, NumPy, scikit-learn
Numerical tour in the Python eco-system: Python, NumPy, scikit-learnNumerical tour in the Python eco-system: Python, NumPy, scikit-learn
Numerical tour in the Python eco-system: Python, NumPy, scikit-learn
 
3.Process Management
3.Process Management3.Process Management
3.Process Management
 
Chapter 2
Chapter 2Chapter 2
Chapter 2
 

Recently uploaded

CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineeringssuserb3a23b
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 

Recently uploaded (20)

CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
Software Coding for software engineering
Software Coding for software engineeringSoftware Coding for software engineering
Software Coding for software engineering
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 

ACCU 2015 Premature Optimisation Workshop

  • 1. ACCU 2015 PROJECT DATE CONFERENCE 23 APRIL PREMATURE OPTIMISATION WORKSHOP ARJAN VAN LEEUWEN
  • 2. WWW.OPERA.COM JOIN THE COOL KIDS ON THE INFORMATION SUPERHIGHWAY
  • 3. ACCU 2015 PROJECT DATE CONFERENCE 23 APRIL PREMATURE OPTIMISATION WORKSHOP ARJAN VAN LEEUWEN
  • 5. OPTIMISING IS FUN AND KNOWING HOW TO DO IT CAN BE USEFUL
  • 6. PREMATURE OPTIMISATION IS THE ROOT OF ALL EVIL DONALD KNUTH, “STRUCTURED PROGRAMMING WITH GOTO STATEMENTS”
  • 7. PROGRAMMERS WASTE ENORMOUS AMOUNTS OF TIME THINKING ABOUT, OR WORRYING ABOUT, THE SPEED OF NONCRITICAL PARTS OF THEIR PROGRAMS, AND THESE ATTEMPTS AT EFFICIENCY ACTUALLY HAVE A STRONG NEGATIVE IMPACT WHEN DEBUGGING AND MAINTENANCE ARE CONSIDERED. WE SHOULD FORGET ABOUT SMALL EFFICIENCIES, SAY ABOUT 97% OF THE TIME: PREMATURE OPTIMISATION IS THE ROOT OF ALL EVIL. YET WE SHOULD NOT PASS UP OUR OPPORTUNITIES IN THAT CRITICAL 3%. “ ”
  • 8. IN ESTABLISHED ENGINEERING DISCIPLINES A 12% IMPROVEMENT, EASILY OBTAINED, IS NEVER CONSIDERED MARGINAL AND I BELIEVE THE SAME VIEWPOINT SHOULD PREVAIL IN SOFTWARE ENGINEERING. “ ”
  • 9. SMALL THINGS CAN MAKE A DIFFERENCE AND ARE WORTH STUDYING
  • 10. Goals Find small changes that can make a difference Don’t sacrifice elegance for speed Give ideas on how to optimise
  • 11. In the toolbox Common sense (doing nothing is always faster) Disassembler Time measurement Profiling tools
  • 13. C++ Close to the metal Object model well-defined [Lippman96] Efficiency has been a major design goal for C++ from the beginning “You don’t pay for what you don’t use” Benefits from years of C optimisation experience
  • 14. Branches Basis of much we do in imperative languages Compare and branch
  • 15. if-else-if void GetAndProcessResult() { if (GetResult() == DOWNLOADED) return ProcessDownloadedFile(); else if (GetResult() == NEEDS_DOWNLOAD) return DownloadFile(); else if (GetResult() == NOT_AVAILABLE) return ReportNotAvailable(); else if (GetResult() == ERROR) return ReportError(); }
  • 16. if-else-if void GetAndProcessResult() { const int result = GetResult(); if (result == DOWNLOADED) return ProcessDownloadedFile(); else if (result == NEEDS_DOWNLOAD) return DownloadFile(); else if (result == NOT_AVAILABLE) return ReportNotAvailable(); else if (result == ERROR) return ReportError(); }
  • 17. if-else-if switch! void GetAndProcessResult() { switch (GetResult()) { case DOWNLOADED: return ProcessDownloadedFile(); case NEEDS_DOWNLOAD: return DownloadFile(); case NOT_AVAILABLE: return ReportNotAvailable(); case ERROR: return ReportError(); } }
  • 18. The joys of switch Clarifies intention Clearer warnings / error messages Always allows compiler to create jump table or do binary search O(1) lookups
  • 19. Jump table void GetAndProcessResult() { switch (GetResult()) { case DOWNLOADED: return ProcessDownloadedFile(); case NEEDS_DOWNLOAD: return DownloadFile(); case NOT_AVAILABLE: return ReportNotAvailable(); case ERROR: return ReportError(); } }
  • 20. Jump table void GetAndProcessResult() { switch (GetResult()) { } } case 0: return ProcessDownloadedFile(); case 1: return DownloadFile(); case 2: return ReportNotAvailable(); case 3: return ReportError();
  • 21. Jump table case 0: return ProcessDownloadedFile(); case 1: return DownloadFile(); case 2: return ReportNotAvailable(); case 3: return ReportError();
  • 22. Jump table void GetAndProcessResult() { switch (GetResult()) { } } case 0: return ProcessDownloadedFile(); case 1: return DownloadFile(); case 2: return ReportNotAvailable(); case 3: return ReportError();
  • 23. Jump table void GetAndProcessResult() { switch (GetResult()) { case 102: return ProcessDownloadedFile(); case 103: return DownloadFile(); case 104: return ReportNotAvailable(); case 105: return ReportError(); } }
  • 24. Jump table void GetAndProcessResult() { switch (GetResult()) { case 102+0: return ProcessDownloadedFile(); case 102+1: return DownloadFile(); case 102+2: return ReportNotAvailable(); case 102+3: return ReportError(); } }
  • 25. Jump table? void GetAndProcessResult() { switch (GetResult()) { case 1: return ProcessDownloadedFile(); case 16: return DownloadFile(); case 88: return ReportNotAvailable(); case 65536: return ReportError(); } }
  • 26. Jump table Binary search void GetAndProcessResult() { switch (GetResult()) { case 1: return ProcessDownloadedFile(); case 16: return DownloadFile(); case 88: return ReportNotAvailable(); case 65536: return ReportError(); } } Compilers are smart
  • 27. Predicting branches Predicting branches is hard Automated mechanisms (profile-guided optimisations) can offer big gains at the cost of having to profile your build If you’re very certain of your case, some compilers offer instructions such as __builtin_expect (gcc, clang)
  • 28. Strings Most used and mis-used type in programming Mutable strings are the root of all evil
  • 29. Strings misuse String is not a basic type A mutable string is a dynamic array of characters Almost anything you can do with a string is a function of the characters in that string Think about what will happen with long strings
  • 30. Using std::string Be careful with modifying operations such as append() Avoid creating a string out of many parts, better to create at once Look into when alternative string types are useful
  • 31. Growing strings std::string CopyString( const char* to_copy, size_t length) { std::string copied; for (size_t i = 0; i < length; i += BLOCKSIZE) copied.append(to_copy + i, std::min(BLOCKSIZE, length - i)); return copied; }
  • 32. Growing strings std::string CopyString( const char* to_copy, size_t length) { std::stringstream copied; for (size_t i = 0; i < length; i += BLOCKSIZE) copied.write(to_copy + i, std::min(BLOCKSIZE, length - i)); return copied.str(); }
  • 33. Growing strings std::string CopyString( const char* to_copy, size_t length) { std::string copied; copied.reserve(length); for (size_t i = 0; i < length; i += BLOCKSIZE) copied.append(to_copy + i, std::min(BLOCKSIZE, length - i)); return copied; }
  • 34. Growing strings Method Time spent, 3 run average (ms) std::string::append() 1399 std::stringstream 5102 std::string::append() with std::string::reserve() 851
  • 35. Converting numbers to strings and vice versa Can be a major source of slowness Often more features than needed Investigate alternative libraries (boost::spirit) Writing specialised functions a possibility (but with its own maintainability issues)
  • 36. Integer-to-string conversion std::string Convert(int i) { std::stringstream stream; stream << i; return stream.str(); }
  • 37. Integer-to-string conversion std::string Convert(int i) { return std::to_string(i); }
  • 38. Integer-to-string conversion std::string Convert(int i) { namespace karma = boost::spirit::karma; std::string converted; std::back_insert_iterator<std::string> sink(converted); karma::generate(sink, karma::int_, i); return converted; }
  • 39. Integer-to-string conversion Method Time spent, 3 run average (ms) std::stringstream 2959 std::to_string 1012 boost::spirit::karma 332
  • 41. String-to-integer conversion int Convert(const std::string& str) { namespace qi = boost::spirit::qi; int converted; qi::parse(str.begin(), str.end(), qi::int_, converted); return converted; }
  • 42. String-to-integer conversion Method Time spent, 3 run average (ms) std::stoi 3920 boost::spirit::qi 1276
  • 43. Function calls Function calls have overhead Lookup in virtual function table Setting up stack, restoring stack
  • 44. Avoiding virtual functions or virtual function calls Only declare functions (this includes destructors) virtual when it’s actually needed Don’t use virtual functions for types that are handled by value If type is known, no lookup is needed Sometimes compile-time polymorphism offers an alternative
  • 45. Avoiding function calls For small functions called in tight loops, inlining helps Allow the compiler to inline functions where it makes sense (have definition available) If the compiler doesn’t co-operate and you’re sure it makes sense (measure this), force it
  • 46. Tail calls A tail call happens when a function is the final call made in another function Tail calls can be eliminated, so that they end up being a jump construction Eliminates call overhead Be aware of this and create tail calls where possible Also allows efficient recursive functions
  • 47. Facilitating tail calls unsigned djb_hash(const char* string) { int c = *string; if (!c) return 5381; return djb_hash(string + 1) * 33 + c; }
  • 48. Facilitating tail calls unsigned djb_hash( const char* string, unsigned seed) { int c = *string; if (!c) return seed; return djb_hash( string + 1, seed * 33 + c); }
  • 49. Facilitating tail calls Method Time spent, 3 run average (ms) Tail call elimination not possible 2274 Tail call elimination possible 1097
  • 50. Use lambda functions C++11 lambdas can always be trivially inlined, unlike function pointers Offers an elegant and fast way of processing data Combines well with aggregate functions
  • 51. Use lambda functions void twice(int& value) { value *= 2; } std::vector<int> EverythingTwice( const std::vector<int>& original) { std::vector<int> result(original); std::for_each(result.begin(), result.end(), &twice); return result; }
  • 52. Use lambda functions std::vector<int> EverythingTwice2( const std::vector<int>& original) { std::vector<int> result(original); std::for_each(result.begin(), result.end(), [](int& value){ value *= 2; }); return result; }
  • 53. Use lambda functions Method Time spent, 3 run average (ms) Function pointer (not inlined) 1684 Lambda function (inlined) 220
  • 54. Return-value optimisation Allows the compiler to avoid copy construction on temporaries Executed by compilers when function returns one named variable Be aware of where it could be possible, allow the compiler to help you But sometimes it’s more helpful to implement…
  • 55. Move semantics User defines for movable types how they can be moved correctly ‘Guaranteed’ way of getting return value optimisation Helpful in combination with std::vector (to keep data local) Can come for free using “Rule of zero”
  • 56. Move semantics class Typical { public: Typical() : content_("this is a typical string") {} Typical(const Typical& other) : content_(other.content_) {} private: std::string content_; };
  • 57. Move semantics class Typical { public: TypicalMove () : content_("this is a typical string") {} private: std::string content_; };
  • 58. Move semantics std::vector<Typical> CreateTypical() { std::vector<Typical> new_content; for (int i = 0; i < 1024; ++i) new_content.push_back(Typical()); return new_content; }
  • 59. Move semantics Method Time spent, 3 run average (ms) With copy constructor 2617 Following “Rule of zero” 1002
  • 60. Data Make sure that all data you need in a loop is physically as close together as possible Allows CPU to use its cache efficiently Use contiguous memory arrays where possible Avoid data structures that rely on pointers (eg. linked lists)
  • 61. Data int sum() { std::forward_list<int> data(1024, 5); int result; for (int i = 0; i < 1000000; ++i) { result = std::accumulate( data.begin(), data.end(), 0); } return result; }
  • 62. Data int sum() { std::vector<int> data(1024, 5); int result; for (int i = 0; i < 1000000; ++i) { result = std::accumulate( data.begin(), data.end(), 0); } return result; }
  • 63. Data Method Time spent, 3 run average (ms) std::forward_list 1115 std::vector 61
  • 65. Python Emphasises readability Dynamic type system, automatic memory management Several projects dedicated to improving performance Always try to avoid calling functions many times
  • 66. Prefer literals over “constructors” def a(): return dict(firstkey=1, secondkey=2)
  • 67. Prefer literals over “constructors” def a(): return dict(firstkey=1, secondkey=2) def b(): return { 'firstkey': 1, 'secondkey': 2 }
  • 68. Prefer literals over “constructors” Method Time spent, 3 run minimum (ms) dict() 376 Dictionary literals 135
  • 69. Prefer slice notation over “copy constructor” l = [ 'a', 'b', 'c', 'd', 'e', 'f' ] def a(): return list(l)
  • 70. Prefer slice notation over “copy constructor” l = [ 'a', 'b', 'c', 'd', 'e', 'f' ] def a(): return list(l) def b(): return l[:]
  • 71. Prefer slice notation over “copy constructor” Method Time spent, 3 run minimum (ms) Copy via list() 2671 Slice notation 1679
  • 72. All functions have overhead Function call overhead in Python is substantial All functions can be redefined - even built-ins need to be looked up first Try to avoid function calls (even more so than in
 C++) Using literals or other built-in constructs can help avoid function calls
  • 73. String formatting Python has a built-in function str() to convert other types to string In most cases this offers enough features for conversions of types to strings Faster than formatting
  • 74. String formatting def a(): a = 5 b = 2 c = 3 return "%d" % (a*(b+c))
  • 75. String formatting def a(): a = 5 b = 2 c = 3 return "%d" % (a*(b+c)) def b(): a = 5 b = 2 c = 3 return str(a*(b+c))
  • 76. String formatting def a(): a = 5 b = 2 c = 3 return "%d" % (a*(b+c)) def c(): a = 5 b = 2 c = 3 return "%s" % (a*(b+c))
  • 77. Method Time spent, 3 run minimum (ms) “%d” 514 str() 260 “%s” 233 String formatting
  • 78. Prefer aggregate functions def a(): s = 0; for i in range(50000): s += i return s
  • 79. Prefer aggregate functions def a(): s = 0; for i in range(50000): s += i return s def b(): return sum(range(50000))
  • 80. Method Time spent, 3 run minimum (ms) Summing manually 1728 Using sum() 587 Prefer aggregate functions
  • 81. Prefer aggregate functions Python has a number of built-in functions for aggregates: all(), min(), max(), sum(), etc Using them brings big speed advantages Always preferred over manually iterating
  • 82. Use list comprehensions def a(): l = [] for i in range(1000): l.append(i) return l
  • 83. Use list comprehensions def a(): l = [] for i in range(1000): l.append(i) return l def b(): return [i for i in range(1000)]
  • 84. Method Time spent, 3 run minimum (ms) Append to list 701 List comprehension 321 Use list comprehensions
  • 85. List comprehensions offer a concise way of creating lists Speed as well as readability advantages Can be nested as well! Use list comprehensions
  • 86. Don’t use optimisations from other languages def a(): x = 1; for i in range(1000): x = x + x return x
  • 87. Don’t use optimisations from other languages def b(): x = 1; for i in range(1000): x = x * 2 return x
  • 88. Don’t use optimisations from other languages def c(): x = 1; for i in range(1000): x = x << 1 return x
  • 89. Method Time spent, 3 run minimum (ms) x + x 736 x * 2 1001 x << 1 1342 Don’t use optimisations from other languages
  • 90. LET’S TRY IT PREPARE YOUR LAPTOPS!
  • 91. PYTHON: WWW.CYBER- DOJO.ORG 
 E94905 C++: git clone https://github.com/ avl7771/premature_optimization.git
  • 92. Conclusions Optimising is fun! Knowledge about optimisations can help you help your compiler or interpreter Not all optimisations worsen maintainability Micro-optimisations can differ between languages, compilers, architectures… Measuring works! Test your assumptions