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

WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2
 
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!WSO2
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationJuha-Pekka Tolvanen
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2
 
WSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2
 
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAMWSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAMWSO2
 
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...Bert Jan Schrijver
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public Administration
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public AdministrationWSO2CON 2024 - How CSI Piemonte Is Apifying the Public Administration
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public AdministrationWSO2
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxAnnaArtyushina1
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
WSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next IntegrationWSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next IntegrationWSO2
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...WSO2
 

Recently uploaded (20)

WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - Kanchana
 
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
WSO2CON 2024 - Not Just Microservices: Rightsize Your Services!
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
WSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration Tooling
 
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAMWSO2Con2024 - Organization Management: The Revolution in B2B CIAM
WSO2Con2024 - Organization Management: The Revolution in B2B CIAM
 
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...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public Administration
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public AdministrationWSO2CON 2024 - How CSI Piemonte Is Apifying the Public Administration
WSO2CON 2024 - How CSI Piemonte Is Apifying the Public Administration
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
WSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next IntegrationWSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...
WSO2CON 2024 - Unlocking the Identity: Embracing CIAM 2.0 for a Competitive A...
 

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.