SlideShare una empresa de Scribd logo
1 de 44
Descargar para leer sin conexión
Benchmarking in
Elixir
https://github.com/PragTob
/benchee
Developer: JavaScript, Elixir at Blueberry
Gardener
Traveller
Email: antonin.hackenberg@gmail.com
LinkedIn: https://cz.linkedin.com/in/antoninhackenberg
Github: https://github.com/TondaHack
Antonín Hackenberg
Elixir
● 2012 (José Valim)
● Erlang bytecode
● Erlang
○ Amazon, Yahoo, Facebook, WhatsApp, T-Mobile, Motorola, Ericsson,
World of Warcraft
● Low-latency, Distributed, Fault-tolerant
Elixir
● Amazing Tooling
● Good documentation
● Metaprogramming
● Millions users
● Lonely planet, Pinterest,
Bet365, Cabify
Elixir - use-cases
● Web applications - Pheonix Framework
● Web APIs (JSON and GraphQL) - Absinthe
● Real-time web - Channels
Elixir - use-cases
● Stateful web - OTP
● Distributed systems (Erlang Distribution
Protocol :rpc)
● Internet of things - Nerves project
Benchmarking
What?
Where?
How?
80/20
Benchmarking
Benchmark vs. Profile
Micro vs. Macro
Correctness
Tooling
Let’s Benchmark Tail Call
Optimization
Sum recursion - No Tail Call Optimization
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + sum_no_tco([2, 3, 4])
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + sum_no_tco([2, 3, 4])
+ 2 + sum_no_tco([3, 4])
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + sum_no_tco([2, 3, 4])
+ 2 + sum_no_tco([3, 4])
+ 3 + sum_no_tco([4])
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + sum_no_tco([2, 3, 4])
+ 2 + sum_no_tco([3, 4])
+ 3 + sum_no_tco([4])
+ 4 + sum_no_tco([])
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + sum_no_tco([2, 3, 4])
+ 2 + sum_no_tco([3, 4])
+ 3 + sum_no_tco([4])
+ 4 + sum_no_tco([])
+ 0
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + sum_no_tco([2, 3, 4])
+ 2 + sum_no_tco([3, 4])
+ 3 + sum_no_tco([4])
+ 4 + 0
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + sum_no_tco([2, 3, 4])
+ 2 + sum_no_tco([3, 4])
+ 3 + 4
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + sum_no_tco([2, 3, 4])
+ 2 + 7
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
1 + 9
Sum function - Without Tail Call
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
NoTCO.sum_no_tco([1, 2, 3, 4])
= 10
Sum function - Tail Call Optimization
defmodule TCO do
def sum([], acc), do: acc
def sum([head | tail], acc) do
sum(tail, head + acc)
end
end
Sum function - Tail Call Optimization
defmodule TCO do
def sum([], acc), do: acc
def sum([head | tail], acc) do
sum(tail, head + acc)
end
end
TCO.sum([1, 2, 3, 4], 0)
Sum function - Tail Call Optimization
defmodule TCO do
def sum([], acc), do: acc
def sum([head | tail], acc) do
sum(tail, head + acc)
end
end
TCO.sum([1, 2, 3, 4], 0)
sum([2, 3, 4], 1)
Sum function - Tail Call Optimization
defmodule TCO do
def sum([], acc), do: acc
def sum([head | tail], acc) do
sum(tail, head + acc)
end
end
TCO.sum([1, 2, 3, 4], 0)
sum([3, 4], 3)
Sum function - Tail Call Optimization
defmodule TCO do
def sum([], acc), do: acc
def sum([head | tail], acc) do
sum(tail, head + acc)
end
end
TCO.sum([1, 2, 3, 4], 0)
sum([4], 6)
Sum function - Tail Call Optimization
defmodule TCO do
def sum([], acc), do: acc
def sum([head | tail], acc) do
sum(tail, head + acc)
end
end
TCO.sum([1, 2, 3, 4], 0)
sum([], 10)
Sum function - Tail Call Optimization
defmodule TCO do
def sum([], acc), do: acc
def sum([head | tail], acc) do
sum(tail, head + acc)
end
end
TCO.sum([1, 2, 3, 4], 0)
10
Difference
defmodule TCO do
def sum([], acc), do: acc
def sum([head | tail], acc) do
sum(tail, head + acc)
end
end
defmodule NoTCO do
def sum_no_tco([]), do: 0
def sum_no_tco([head | tail]) do
head + sum_no_tco(tail)
end
end
Benchmarking
iex(1)> :timer.tc fn -> NoTCO.sum_no_tco(Enum.to_list(1..100_000)) end
{17673, 5000050000}
iex(2)> :timer.tc fn -> TCO.sum(Enum.to_list(1..100_000), 0) end
{10518, 5000050000}
inputs = %{
"1_000 list size" => Enum.to_list(1..1_000),
"100_000 list size" => Enum.to_list(1..1000_000),
"1000_000 list size" => Enum.to_list(1..1000_000),
}
Benchee.run(%{
"Tail Call Optimizitation" => fn(list) -> TCO.sum(list, 0) end,
"No TCO" => fn(list) -> NoTCO.sum_no_tco(list) end,
"Enum sum" => fn(list) -> Enum.sum(list) end
},
time: 10,
memory_time: 2,
inputs: inputs,
formatters: [
Benchee.Formatters.HTML,
Benchee.Formatters.Console
],
formatter_options: [html: [file: "lib/report/tco.html"]]
)
Real example
def parse(file_path, modifiers  %{}, options  %{}, take) do
file_path
|> File.stream!()
|> CsvParser.decode_csv()
|> Stream.take(take)
|> Stream.map(&process_item(&1, options, modifiers))
|> Stream.filter(&filter_items(&1, options["elastic_search_index" ]))
|> Stream.chunk_every(1000)
|> Stream.each(&store_items(&1, options["elastic_search_index" ]))
|> Stream.run()
end
[modifiers, file_path] = PpcbeeElixirBackend.Enhance.download(191)
Benchee.run(
%{
"No Parallelism" => fn ->
PpcbeeElixirBackend.DataParser.parse(file_path, modifiers, %{}, 10_000)
end,
"Parallelism Task.async_stream" => fn ->
PpcbeeElixirBackend.DataParser.parse_async_stream(file_path, modifiers, %{},10_000)
end,
"Parallelism Task.async" => fn ->
PpcbeeElixirBackend.DataParser.parse_async_task(file_path, modifiers, %{}, 10_000)
end,
"Parallelism flow" => fn ->
PpcbeeElixirBackend.DataParser.parse_flow(file_path, modifiers, %{}, 10_000)
end
},
time: 5 * 60,
formatters: [
Benchee.Formatters.HTML,
],
formatter_options: [html: [file: "lib/benchmark/report/parallelism/report.html"]]
)
Ruby vs. Elixir - Tested on one machine
Ruby - previous service after optimization
● 200 / items per seconds
● CPU 100%
● RAM 560 mb
Elixir - before optimization
● 310 (no parallelism), 620 (paralellism)
● CPU 100%, 300%
● RAM 65 mb
Profiling - eprof, ExProf
“The module eprof provides a set of functions for time
profiling of Erlang programs to find out how the
execution time is used. The profiling is done using
the Erlang trace BIFs. Tracing of local function calls
for a specified set of processes is enabled when
profiling is begun, and disabled when profiling is
stopped.”
http://erlang.org/doc/man/eprof.html
...
Benchmarking is not real user!
Thank you :)
Sources
● https://www.issart.com/blog/benchmarking-best-practice-fo
r-code-optimization
● https://pragtob.wordpress.com/2016/06/16/tail-call-optimi
zation-in-elixir-erlang-not-as-efficient-and-important-as
-you-probably-think/
● https://www.youtube.com/watch?v=KSrImdsfjL4
● https://www.amberbit.com/blog/2018/5/15/when-to-use-elixi
r-language/
● https://github.com/parroty/exprof
● https://github.com/PragTob/benchee
● https://www.ppcbee.com/

Más contenido relacionado

La actualidad más candente

Functional Pattern Matching on Python
Functional Pattern Matching on PythonFunctional Pattern Matching on Python
Functional Pattern Matching on Python
Daker Fernandes
 
Go for the would be network programmer
Go for the would be network programmerGo for the would be network programmer
Go for the would be network programmer
Eleanor McHugh
 
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
clkao
 
Python utan-stodhjul-motorsag
Python utan-stodhjul-motorsagPython utan-stodhjul-motorsag
Python utan-stodhjul-motorsag
niklal
 

La actualidad más candente (20)

Going Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with GoGoing Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with Go
 
Let's golang
Let's golangLet's golang
Let's golang
 
Basics
BasicsBasics
Basics
 
Hello Go
Hello GoHello Go
Hello Go
 
Functional Pattern Matching on Python
Functional Pattern Matching on PythonFunctional Pattern Matching on Python
Functional Pattern Matching on Python
 
Go for the would be network programmer
Go for the would be network programmerGo for the would be network programmer
Go for the would be network programmer
 
JFugue, Music, and the Future of Java [JavaOne 2016, CON1851]
JFugue, Music, and the Future of Java [JavaOne 2016, CON1851]JFugue, Music, and the Future of Java [JavaOne 2016, CON1851]
JFugue, Music, and the Future of Java [JavaOne 2016, CON1851]
 
The Art, Joy, and Power of Creating Musical Programs (JFugue at SXSW Interact...
The Art, Joy, and Power of Creating Musical Programs (JFugue at SXSW Interact...The Art, Joy, and Power of Creating Musical Programs (JFugue at SXSW Interact...
The Art, Joy, and Power of Creating Musical Programs (JFugue at SXSW Interact...
 
Encrypt all transports
Encrypt all transportsEncrypt all transports
Encrypt all transports
 
AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
 
P4 2018 io_functions
P4 2018 io_functionsP4 2018 io_functions
P4 2018 io_functions
 
Fewer cables
Fewer cablesFewer cables
Fewer cables
 
Music as data
Music as dataMusic as data
Music as data
 
What's New in PHP 5.5
What's New in PHP 5.5What's New in PHP 5.5
What's New in PHP 5.5
 
Abusing text/template for data transformation
Abusing text/template for data transformationAbusing text/template for data transformation
Abusing text/template for data transformation
 
Elixir @ Paris.rb
Elixir @ Paris.rbElixir @ Paris.rb
Elixir @ Paris.rb
 
Exploring slides
Exploring slidesExploring slides
Exploring slides
 
Python utan-stodhjul-motorsag
Python utan-stodhjul-motorsagPython utan-stodhjul-motorsag
Python utan-stodhjul-motorsag
 
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While TestingQA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
 
P3 2018 python_regexes
P3 2018 python_regexesP3 2018 python_regexes
P3 2018 python_regexes
 

Similar a FPBrno 2018-05-22: Benchmarking in elixir

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
Profiling and optimization
Profiling and optimizationProfiling and optimization
Profiling and optimization
g3_nittala
 

Similar a FPBrno 2018-05-22: Benchmarking in elixir (20)

Very basic functional design patterns
Very basic functional design patternsVery basic functional design patterns
Very basic functional design patterns
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
 
Developer Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duoDeveloper Experience i TypeScript. Najbardziej ikoniczne duo
Developer Experience i TypeScript. Najbardziej ikoniczne duo
 
Elixir cheatsheet
Elixir cheatsheetElixir cheatsheet
Elixir cheatsheet
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a Elixir
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Profiling and optimization
Profiling and optimizationProfiling and optimization
Profiling and optimization
 
pa-pe-pi-po-pure Python Text Processing
pa-pe-pi-po-pure Python Text Processingpa-pe-pi-po-pure Python Text Processing
pa-pe-pi-po-pure Python Text Processing
 
Add an interactive command line to your C++ application
Add an interactive command line to your C++ applicationAdd an interactive command line to your C++ application
Add an interactive command line to your C++ application
 
3 things you must know to think reactive - Geecon Kraków 2015
3 things you must know to think reactive - Geecon Kraków 20153 things you must know to think reactive - Geecon Kraków 2015
3 things you must know to think reactive - Geecon Kraków 2015
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185
 
Do snow.rwn
Do snow.rwnDo snow.rwn
Do snow.rwn
 
Fourier project presentation
Fourier project  presentationFourier project  presentation
Fourier project presentation
 
Writing Faster Python 3
Writing Faster Python 3Writing Faster Python 3
Writing Faster Python 3
 
Valerii Vasylkov Erlang. measurements and benefits.
Valerii Vasylkov Erlang. measurements and benefits.Valerii Vasylkov Erlang. measurements and benefits.
Valerii Vasylkov Erlang. measurements and benefits.
 
SE2016 Exotic Valerii Vasylkov "Erlang. Measurements and benefits"
SE2016 Exotic Valerii Vasylkov "Erlang. Measurements and benefits"SE2016 Exotic Valerii Vasylkov "Erlang. Measurements and benefits"
SE2016 Exotic Valerii Vasylkov "Erlang. Measurements and benefits"
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
CS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term RewritingCS4200 2019 | Lecture 5 | Transformation by Term Rewriting
CS4200 2019 | Lecture 5 | Transformation by Term Rewriting
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012
 
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicitElixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
 

Último

%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
masabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 

Último (20)

%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 

FPBrno 2018-05-22: Benchmarking in elixir

  • 2. Developer: JavaScript, Elixir at Blueberry Gardener Traveller Email: antonin.hackenberg@gmail.com LinkedIn: https://cz.linkedin.com/in/antoninhackenberg Github: https://github.com/TondaHack Antonín Hackenberg
  • 3. Elixir ● 2012 (José Valim) ● Erlang bytecode ● Erlang ○ Amazon, Yahoo, Facebook, WhatsApp, T-Mobile, Motorola, Ericsson, World of Warcraft ● Low-latency, Distributed, Fault-tolerant
  • 4. Elixir ● Amazing Tooling ● Good documentation ● Metaprogramming ● Millions users ● Lonely planet, Pinterest, Bet365, Cabify
  • 5. Elixir - use-cases ● Web applications - Pheonix Framework ● Web APIs (JSON and GraphQL) - Absinthe ● Real-time web - Channels
  • 6. Elixir - use-cases ● Stateful web - OTP ● Distributed systems (Erlang Distribution Protocol :rpc) ● Internet of things - Nerves project
  • 8. Benchmarking Benchmark vs. Profile Micro vs. Macro Correctness Tooling
  • 9. Let’s Benchmark Tail Call Optimization
  • 10. Sum recursion - No Tail Call Optimization defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end
  • 11. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4])
  • 12. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + sum_no_tco([2, 3, 4])
  • 13. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + sum_no_tco([2, 3, 4]) + 2 + sum_no_tco([3, 4])
  • 14. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + sum_no_tco([2, 3, 4]) + 2 + sum_no_tco([3, 4]) + 3 + sum_no_tco([4])
  • 15. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + sum_no_tco([2, 3, 4]) + 2 + sum_no_tco([3, 4]) + 3 + sum_no_tco([4]) + 4 + sum_no_tco([])
  • 16. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + sum_no_tco([2, 3, 4]) + 2 + sum_no_tco([3, 4]) + 3 + sum_no_tco([4]) + 4 + sum_no_tco([]) + 0
  • 17. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + sum_no_tco([2, 3, 4]) + 2 + sum_no_tco([3, 4]) + 3 + sum_no_tco([4]) + 4 + 0
  • 18. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + sum_no_tco([2, 3, 4]) + 2 + sum_no_tco([3, 4]) + 3 + 4
  • 19. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + sum_no_tco([2, 3, 4]) + 2 + 7
  • 20. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) 1 + 9
  • 21. Sum function - Without Tail Call defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end NoTCO.sum_no_tco([1, 2, 3, 4]) = 10
  • 22. Sum function - Tail Call Optimization defmodule TCO do def sum([], acc), do: acc def sum([head | tail], acc) do sum(tail, head + acc) end end
  • 23. Sum function - Tail Call Optimization defmodule TCO do def sum([], acc), do: acc def sum([head | tail], acc) do sum(tail, head + acc) end end TCO.sum([1, 2, 3, 4], 0)
  • 24. Sum function - Tail Call Optimization defmodule TCO do def sum([], acc), do: acc def sum([head | tail], acc) do sum(tail, head + acc) end end TCO.sum([1, 2, 3, 4], 0) sum([2, 3, 4], 1)
  • 25. Sum function - Tail Call Optimization defmodule TCO do def sum([], acc), do: acc def sum([head | tail], acc) do sum(tail, head + acc) end end TCO.sum([1, 2, 3, 4], 0) sum([3, 4], 3)
  • 26. Sum function - Tail Call Optimization defmodule TCO do def sum([], acc), do: acc def sum([head | tail], acc) do sum(tail, head + acc) end end TCO.sum([1, 2, 3, 4], 0) sum([4], 6)
  • 27. Sum function - Tail Call Optimization defmodule TCO do def sum([], acc), do: acc def sum([head | tail], acc) do sum(tail, head + acc) end end TCO.sum([1, 2, 3, 4], 0) sum([], 10)
  • 28. Sum function - Tail Call Optimization defmodule TCO do def sum([], acc), do: acc def sum([head | tail], acc) do sum(tail, head + acc) end end TCO.sum([1, 2, 3, 4], 0) 10
  • 29. Difference defmodule TCO do def sum([], acc), do: acc def sum([head | tail], acc) do sum(tail, head + acc) end end defmodule NoTCO do def sum_no_tco([]), do: 0 def sum_no_tco([head | tail]) do head + sum_no_tco(tail) end end
  • 30. Benchmarking iex(1)> :timer.tc fn -> NoTCO.sum_no_tco(Enum.to_list(1..100_000)) end {17673, 5000050000} iex(2)> :timer.tc fn -> TCO.sum(Enum.to_list(1..100_000), 0) end {10518, 5000050000}
  • 31. inputs = %{ "1_000 list size" => Enum.to_list(1..1_000), "100_000 list size" => Enum.to_list(1..1000_000), "1000_000 list size" => Enum.to_list(1..1000_000), } Benchee.run(%{ "Tail Call Optimizitation" => fn(list) -> TCO.sum(list, 0) end, "No TCO" => fn(list) -> NoTCO.sum_no_tco(list) end, "Enum sum" => fn(list) -> Enum.sum(list) end }, time: 10, memory_time: 2, inputs: inputs, formatters: [ Benchee.Formatters.HTML, Benchee.Formatters.Console ], formatter_options: [html: [file: "lib/report/tco.html"]] )
  • 32.
  • 33.
  • 34. Real example def parse(file_path, modifiers %{}, options %{}, take) do file_path |> File.stream!() |> CsvParser.decode_csv() |> Stream.take(take) |> Stream.map(&process_item(&1, options, modifiers)) |> Stream.filter(&filter_items(&1, options["elastic_search_index" ])) |> Stream.chunk_every(1000) |> Stream.each(&store_items(&1, options["elastic_search_index" ])) |> Stream.run() end
  • 35. [modifiers, file_path] = PpcbeeElixirBackend.Enhance.download(191) Benchee.run( %{ "No Parallelism" => fn -> PpcbeeElixirBackend.DataParser.parse(file_path, modifiers, %{}, 10_000) end, "Parallelism Task.async_stream" => fn -> PpcbeeElixirBackend.DataParser.parse_async_stream(file_path, modifiers, %{},10_000) end, "Parallelism Task.async" => fn -> PpcbeeElixirBackend.DataParser.parse_async_task(file_path, modifiers, %{}, 10_000) end, "Parallelism flow" => fn -> PpcbeeElixirBackend.DataParser.parse_flow(file_path, modifiers, %{}, 10_000) end }, time: 5 * 60, formatters: [ Benchee.Formatters.HTML, ], formatter_options: [html: [file: "lib/benchmark/report/parallelism/report.html"]] )
  • 36.
  • 37. Ruby vs. Elixir - Tested on one machine Ruby - previous service after optimization ● 200 / items per seconds ● CPU 100% ● RAM 560 mb Elixir - before optimization ● 310 (no parallelism), 620 (paralellism) ● CPU 100%, 300% ● RAM 65 mb
  • 38. Profiling - eprof, ExProf “The module eprof provides a set of functions for time profiling of Erlang programs to find out how the execution time is used. The profiling is done using the Erlang trace BIFs. Tracing of local function calls for a specified set of processes is enabled when profiling is begun, and disabled when profiling is stopped.” http://erlang.org/doc/man/eprof.html
  • 39. ...
  • 40.
  • 41. Benchmarking is not real user!
  • 42.
  • 44. Sources ● https://www.issart.com/blog/benchmarking-best-practice-fo r-code-optimization ● https://pragtob.wordpress.com/2016/06/16/tail-call-optimi zation-in-elixir-erlang-not-as-efficient-and-important-as -you-probably-think/ ● https://www.youtube.com/watch?v=KSrImdsfjL4 ● https://www.amberbit.com/blog/2018/5/15/when-to-use-elixi r-language/ ● https://github.com/parroty/exprof ● https://github.com/PragTob/benchee ● https://www.ppcbee.com/