SlideShare a Scribd company logo
1 of 35
Elixir Flow:
How to build and tune concurrent,
parallel workflows
Luke Galea - CTO, Precision Nutrition
GenStage
Producer
defmodule GenstageExample.Producer do
use GenStage
def start_link(initial  0) do
GenStage.start_link(__MODULE__, initial,
name: __MODULE__)
end
def init(counter), do: {:producer, counter}
def handle_demand(demand, state) do
events = Enum.to_list(state..(state +
demand - 1))
{:noreply, events, state + demand}
end
end
Producer-Consumer
defmodule GenstageExample.ProducerConsumer do
use GenStage
require Integer
def start_link do
GenStage.start_link(__MODULE__, :state_doesnt_matter, name: __MODULE__)
end
def init(state) do
{:producer_consumer, state, subscribe_to: [GenstageExample.Producer]}
end
def handle_events(events, _from, state) do
numbers =
events
|> Enum.filter(&Integer.is_even/1)
{:noreply, numbers, state}
end
end
Consumer
defmodule GenstageExample.Consumer do
use GenStage
def start_link do
GenStage.start_link(__MODULE__, :state_doesnt_matter)
end
def init(state) do
{:consumer, state, subscribe_to:
[GenstageExample.ProducerConsumer]}
end
def handle_events(events, _from, state) do
for event <- events do
IO.inspect({self(), event, state})
end
# As a consumer we never emit events
{:noreply, [], state}
end
end
What is Flow?
Flow allows developers to express
computations on collections, similar
to the Enum and Stream modules,
although computations will be
executed in parallel using multiple
GenStages.
API
Case Study: Link Checker
Eager to Lazy to
Concurrent to Parallel
EagerHTTPoison.start
File.read!("element_content.csv")
|> NimbleCSV.RFC4180.parse_string
|> Enum.map(fn [id, markdown] -> [id, Earmark.as_html!(markdown)] end)
|> Enum.map( fn [id, html] -> [id, html |> Floki.find("a") |> Floki.attribute("href")] end)
|> Enum.reject(fn
[_, []] -> true
_ -> false
end)
|> Enum.flat_map( fn [id, links] -> links |> Enum.map(&([id, &1])) end)
|> Enum.reject( fn [_, url] ->
case URI.parse(url) do
%URI{scheme: nil} -> true
%URI{host: nil} -> true
%URI{path: nil} -> true
_ -> false
end
end)
|> Enum.reject( fn [_, url] ->
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{status_code: status_code}}
when status_code >= 200 and status_code <= 399 -> true
_ -> false
end
end)
|> Enum.to_list()
Time to run: 23mins 12secs
Eager
File.read!("element_content.csv")
|> CSV.parse_string
|> map(&render_markdown/1)
|> map(&find_links/1)
|> reject(&has_no_links?/1)
|> flat_map(&flatten_links/1)
|> reject(&invalid_link?/1)
|> map(&check_link/1)
|> reject(&is_valid_link/1)
|> to_list()
Eager Performance
Eager Performance
Instrumentation
http://teamon.eu/2016/measuring-visualizing-genstage-flow-with-gnuplot/
Instrumentation
Progress.start_link([:links_parsed, :url_checked])
File.read!("element_content.csv")
|> NimbleCSV.RFC4180.parse_string
|> Enum.map(&render_markdown/1)
|> Enum.map(&find_links/1)
|> Enum.reject(&has_no_links?/1)
|> Enum.flat_map( fn [id, links] -> links |> Enum.map(&([id, &1])) end)
|> Enum.reject(&invalid_link?/1)
|> Enum.map(fn x -> Progress.incr(:links_parsed); x end)
|> Enum.map(&check_link/1)
|> Enum.map(fn x -> Progress.incr(:url_checked); x end)
|> Enum.reject(fn [_, _, valid] -> valid end) #Discard valid
|> Enum.to_list()
Progress.done()
Eager
Performance
Lazy
HTTPoison.start
output = IO.stream(:stdio, :line)
File.stream!("element_content.csv")
|> CSV.parse_stream
|> Stream.map(&render_markdown/1)
|> Stream.map(&find_links/1)
|> Stream.reject(&has_no_links?/1)
|> Stream.flat_map(&flatten_links/1)
|> Stream.reject(&invalid_link?/1)
|> Stream.map(fn x -> Progress.incr(:links_parsed); x end)
|> Stream.map(&check_link/1)
|> Stream.map(fn x -> Progress.incr(:url_checked); x end)
|> Stream.reject(&is_valid_link/1)
|> Stream.into(output, &"#{inspect &1}n")
|> Stream.run
Time to run: 23mins 20secs
+8 secs
Lazy Performance
Lazy Performance
Flow
Concurrent?
File.stream!("element_content.csv")
|> CSV.parse_stream
|> Flow.from_enumerable(stages: 1)
|> Flow.map(&render_markdown/1)
|> Flow.map(&find_links/1)
|> Flow.reject(&has_no_links?/1)
|> Flow.flat_map(&flatten/links/1)
|> Flow.reject(&invalid_link?/1)
|> Flow.map(&check_link/1)
|> Flow.reject(&is_valid_link/1)
|> Enum.to_list()
Time to run: 22mins 18secs
-54 secs
FlowViz.start_link([:links_parsed, :url_checked])
FlowViz.plot()
File.stream!("element_content.csv")
|> CSV.parse_stream
|> Flow.from_enumerable(max_demand: 2, min_demand: 1)
|> Flow.map(&render_markdown/1)
|> Flow.map(&find_links/1)
|> Flow.reject(&has_no_links?/1)
|> Flow.flat_map(&flatten_links/1)
|> Flow.reject(&invalid_link?/1)
|> FlowViz.checkpoint(:links_parsed)
|> Flow.map(&check_link/1)
|> FlowViz.checkpoint(:url_checked)
|> Flow.reject(&is_valid_link/1)
|> Enum.to_list()
Demo
Parallel
File.stream!("element_content.csv")
|> NimbleCSV.RFC4180.parse_stream
|> Flow.from_enumerable(stages: System.schedulers_online)
|> Flow.map(&render_markdown/1)
|> Flow.map(&find_links/1)
|> Flow.reject(&has_no_links?/1)
|> Flow.flat_map( fn [id, links] -> links |> Enum.map(&([id, &1])) end)
|> Flow.reject(&invalid_link?/1)
|> Flow.each(fn _ -> FlowProgress.incr(:links_parsed) end)
|> Flow.map(&check_link/1)
|> Flow.each(fn _ -> FlowProgress.incr(:url_checked) end)
|> Flow.reject(fn [_, _, valid] -> valid end) #Discard valid
|> Enum.to_list()
Time to run: 4mins 21secs
5.3x speedup on 8 logical cores
Parallel Performance
Concurrent + Parallel
File.stream!("element_content.csv")
|> CSV.parse_stream
|> Flow.from_enumerable
|> Flow.map(&render_markdown/1)
|> Flow.map(&find_links/1)
|> Flow.reject(&has_no_links?/1)
|> Flow.flat_map(&flatten_links/1)
|> Flow.reject(&invalid_link?/1)
|> Flow.map(&check_link/1)
|> Flow.reject(fn [_, _, valid] -> valid end) #Discard valid
|> Enum.to_list()
CPU Bound
IO Bound
Partition
Partition
Partitioned
File.stream!("element_content.csv")
|> NimbleCSV.RFC4180.parse_stream
|> Flow.from_enumerable
|> Flow.map(&render_markdown/1)
|> Flow.map(&find_links/1)
|> Flow.reject(&has_no_links?/1)
|> Flow.flat_map( fn [id, links] -> links |> Enum.map(&([id, &1])) end)
|> Flow.reject(&invalid_link?/1)
|> Flow.each(fn _ -> FlowProgress.incr(:links_parsed) end)
|> Flow.partition
|> Flow.map(&check_link/1)
|> Flow.each(fn _ -> FlowProgress.incr(:url_checked) end)
|> Flow.reject(fn [_, _, valid] -> valid end) #Discard valid
|> Enum.to_list()
Time to run: 4mins 02secs
Only slightly faster than non-partitioned
What’s happening?
Optimized
File.stream!("element_content.csv")
|> NimbleCSV.RFC4180.parse_stream
|> Flow.from_enumerable
|> Flow.map(&render_markdown/1)
|> Flow.map(&find_links/1)
|> Flow.reject(&has_no_links?/1)
|> Flow.flat_map( fn [id, links] -> links |> Enum.map(&([id, &1])) end)
|> Flow.reject(&invalid_link?/1)
|> Flow.each(fn _ -> FlowProgress.incr(:links_parsed) end)
|> Flow.partition(stages: 50)
|> Flow.map(&check_link/1)
|> Flow.each(fn _ -> FlowProgress.incr(:url_checked) end)
|> Flow.reject(fn [_, _, valid] -> valid end) #Discard valid
|> Enum.to_list()
Time to run: 1mins 34secs
~15x faster!
Demand
Flow.partition(
max_demand: 2,
min_demand: 1,
stages: 50)
Time to run: 1mins 45secs

More Related Content

What's hot

VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access RunbookTaha Shakeel
 
UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기NAVER SHOPPING
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react applicationGreg Bergé
 
Higher-Order Components — Ilya Gelman
Higher-Order Components — Ilya GelmanHigher-Order Components — Ilya Gelman
Higher-Order Components — Ilya Gelman500Tech
 
AngularJS $http Interceptors (Explanation and Examples)
AngularJS $http Interceptors (Explanation and Examples)AngularJS $http Interceptors (Explanation and Examples)
AngularJS $http Interceptors (Explanation and Examples)Brian Swartzfager
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonKris Wallsmith
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Real Time App with Node.js
Real Time App with Node.jsReal Time App with Node.js
Real Time App with Node.jsJxck Jxck
 
jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace PatternDiego Fleury
 
Angular 2.0 Pipes
Angular 2.0 PipesAngular 2.0 Pipes
Angular 2.0 PipesEyal Vardi
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Subjecting state to good behavior
Subjecting state to good behaviorSubjecting state to good behavior
Subjecting state to good behaviorSeven Peaks Speaks
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
AngularJS Routing
AngularJS RoutingAngularJS Routing
AngularJS RoutingEyal Vardi
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Eyal Vardi
 

What's hot (20)

VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access Runbook
 
UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기UI 모듈화로 워라밸 지키기
UI 모듈화로 워라밸 지키기
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react application
 
Jquery ajax & form
Jquery ajax & formJquery ajax & form
Jquery ajax & form
 
Higher-Order Components — Ilya Gelman
Higher-Order Components — Ilya GelmanHigher-Order Components — Ilya Gelman
Higher-Order Components — Ilya Gelman
 
AngularJS $http Interceptors (Explanation and Examples)
AngularJS $http Interceptors (Explanation and Examples)AngularJS $http Interceptors (Explanation and Examples)
AngularJS $http Interceptors (Explanation and Examples)
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Real Time App with Node.js
Real Time App with Node.jsReal Time App with Node.js
Real Time App with Node.js
 
jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace Pattern
 
Feeds drupal cafe
Feeds drupal cafeFeeds drupal cafe
Feeds drupal cafe
 
Matters of State
Matters of StateMatters of State
Matters of State
 
Angular 2.0 Pipes
Angular 2.0 PipesAngular 2.0 Pipes
Angular 2.0 Pipes
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Jquery Fundamentals
Jquery FundamentalsJquery Fundamentals
Jquery Fundamentals
 
Subjecting state to good behavior
Subjecting state to good behaviorSubjecting state to good behavior
Subjecting state to good behavior
 
getSIDUsers
getSIDUsersgetSIDUsers
getSIDUsers
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
AngularJS Routing
AngularJS RoutingAngularJS Routing
AngularJS Routing
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
 

Similar to Elixir flow: Building and tuning concurrent workflows

Yurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of Elixir
Yurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of ElixirYurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of Elixir
Yurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of ElixirElixir Club
 
Very basic functional design patterns
Very basic functional design patternsVery basic functional design patterns
Very basic functional design patternsTomasz Kowal
 
Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Anyscale
 
Operation Flow @ ChicagoRoboto
Operation Flow @ ChicagoRobotoOperation Flow @ ChicagoRoboto
Operation Flow @ ChicagoRobotoSeyed Jafari
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
A Deep Dive into Structured Streaming in Apache Spark
A Deep Dive into Structured Streaming in Apache Spark A Deep Dive into Structured Streaming in Apache Spark
A Deep Dive into Structured Streaming in Apache Spark Anyscale
 
ClojureScript interfaces to React
ClojureScript interfaces to ReactClojureScript interfaces to React
ClojureScript interfaces to ReactMichiel Borkent
 
How to create a magento controller in magento extension
How to create a magento controller in magento extensionHow to create a magento controller in magento extension
How to create a magento controller in magento extensionHendy Irawan
 
PyCon SG x Jublia - Building a simple-to-use Database Management tool
PyCon SG x Jublia - Building a simple-to-use Database Management toolPyCon SG x Jublia - Building a simple-to-use Database Management tool
PyCon SG x Jublia - Building a simple-to-use Database Management toolCrea Very
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowVrann Tulika
 
Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Fabio Biondi
 
Advanced React Component Patterns - ReactNext 2018
Advanced React Component Patterns - ReactNext 2018Advanced React Component Patterns - ReactNext 2018
Advanced React Component Patterns - ReactNext 2018Robert Herbst
 
The Steel industry, Elixir, PostgreSQL & file_fdw
The Steel industry, Elixir, PostgreSQL & file_fdwThe Steel industry, Elixir, PostgreSQL & file_fdw
The Steel industry, Elixir, PostgreSQL & file_fdwFlorian Kraft
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTPMustafa TURAN
 

Similar to Elixir flow: Building and tuning concurrent workflows (20)

Yurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of Elixir
Yurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of ElixirYurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of Elixir
Yurii Bodarev - OTP, Phoenix & Ecto: Three Pillars of Elixir
 
Om nom nom nom
Om nom nom nomOm nom nom nom
Om nom nom nom
 
Very basic functional design patterns
Very basic functional design patternsVery basic functional design patterns
Very basic functional design patterns
 
React hooks
React hooksReact hooks
React hooks
 
ReactJS
ReactJSReactJS
ReactJS
 
Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0Continuous Application with Structured Streaming 2.0
Continuous Application with Structured Streaming 2.0
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
Operation Flow @ ChicagoRoboto
Operation Flow @ ChicagoRobotoOperation Flow @ ChicagoRoboto
Operation Flow @ ChicagoRoboto
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
A Deep Dive into Structured Streaming in Apache Spark
A Deep Dive into Structured Streaming in Apache Spark A Deep Dive into Structured Streaming in Apache Spark
A Deep Dive into Structured Streaming in Apache Spark
 
ClojureScript interfaces to React
ClojureScript interfaces to ReactClojureScript interfaces to React
ClojureScript interfaces to React
 
How to create a magento controller in magento extension
How to create a magento controller in magento extensionHow to create a magento controller in magento extension
How to create a magento controller in magento extension
 
J query training
J query trainingJ query training
J query training
 
PyCon SG x Jublia - Building a simple-to-use Database Management tool
PyCon SG x Jublia - Building a simple-to-use Database Management toolPyCon SG x Jublia - Building a simple-to-use Database Management tool
PyCon SG x Jublia - Building a simple-to-use Database Management tool
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request Flow
 
Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)
 
Advanced React Component Patterns - ReactNext 2018
Advanced React Component Patterns - ReactNext 2018Advanced React Component Patterns - ReactNext 2018
Advanced React Component Patterns - ReactNext 2018
 
The Steel industry, Elixir, PostgreSQL & file_fdw
The Steel industry, Elixir, PostgreSQL & file_fdwThe Steel industry, Elixir, PostgreSQL & file_fdw
The Steel industry, Elixir, PostgreSQL & file_fdw
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
 

Recently uploaded

The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 

Recently uploaded (20)

The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 

Elixir flow: Building and tuning concurrent workflows

Editor's Notes

  1. Hi everyone! I’m going to be talking about how you can easily build concurrent, parallel workflows using Flow and I’ll be going into some of the details of instrumenting and tuning a Flow.. flow?
  2. I’m from Precision Nutrition – we do online nutrition and fitness coaching. We’re mostly an Ember+Rails shop, but we’re starting to use Elixir more and more. We’ve had our url shortener (get.pn) running on elixir in production for over a year and we’re in the process of extracting all financial/billing logic out of our app into a separate elixir/phoenix payment processing system. Today I’ll be going over a basic intro on Flow but I’ll also get into a specific case study of where we’ve used Flow at PN.
  3. Before we get into Flow, it helps to understand GenStage because Flow is built on top of it. Here’s Jose Valim – the creator of Elixir – presenting on GenStage. This is going to be a tad dry/painful so bear with me because Flow will make this super awesome. The gist is that you have several “stages”, with work moving from stage to stage, but rather than each stage pushing completing work to the next stage, it works in reverse. Each stage requests batches of work from the previous stage. GenStage calls this “Demand”. Each stage can be a producer, a consumer or a producer consumer.
  4. Flow is a useful subset of the Enum and Stream API. This is great because it let’s you use comfortable, high level abstractions to write parallel, concurrent code.
  5. Moving forward, let’s use a real world example of where Flow is handy. At it’s core, our software is a learning management system – filled with content. We also have a simple link checker written in elixir that we use to periodically check every link in our content. This talk is about how I built the fastest link checker, ever.. And you can too!
  6. The fact that Enum, Stream and Flow share a nearly common API means that you can more or less develop as you would normally (with a few caveats) and then later “Flow your code”.
  7. So – why does it take 23 minutes? We can see that it does all of each step before proceeding to the next.
  8. Then it is done all cpu and gets stuck on slowly checking each link, one by one.
  9. Another way to see this is to instrument the code. There’s a great article by Tymon Toblski on this along with a simple “Progress” module that you can use to dump out timing for each step.
  10. Using this, I can just choose a few points in the code and drop in a progress call. A few caveats – avoid dropping rows.
  11. If we graph the output we can see a huge spike and that explains what we’re seeing when we like at system resource utilization.
  12. The next step is to go from eager to lazy. The Stream API is very similar so for the most part this just involves swapping out an import or changing Enum references to String as well as messing with the input and output steps. Interestingly enough, this actually takes longer because we’re still all in a single process.. All we’ve done is reduce memory use because we aren’t holding everything in memory at once.
  13. And we can see that instead of a spike, we have these nice curves.
  14. Before we run it, I want to tell you about FlowViz! I published this early in the week and basically took Tyrone’s work – made it more performant by using delayed writes and wired it up with Gnuplot to give realtime performance plotting.