SlideShare a Scribd company logo
1 of 28
Download to read offline
Experimental.Flow
An overview of experimental Elixir Flow module that allows developers
to express processing steps for collections, like Stream, but utilizing the
power of parallel execution.
Resources
ElixirConf 2016 - Keynote by José Valim
www.youtube.com/watch?v=srtMWzyqdp8
Kyiv Elixir Meetup 3 - Flow-Based Programming with Elixir, Anton
Mishchuk
www.youtube.com/watch?v=yDaPaCxAVq8
www.slideshare.net/AntonMishchuk/flowbased-programming-with-
elixir
Resources
Announcing GenStage
elixir-lang.org/blog/2016/07/14/announcing-genstage/
gen_stage
hex.pm/packages/gen_stage
https://hexdocs.pm/gen_stage/
https://hexdocs.pm/gen_stage/Experimental.Flow.html
Task
Implement word counting algorithm using Eager, Lazy and Concurrent
approaches
• Eager – Enum
• Lazy – Stream
• Concurrent - Flow
Eager
+ High processing speed (for small collections)
- May require large amounts of memory
Good for fast processing of small collections
Eager (Enum)
def process_eager(path_to_file) do
path_to_file
|> File.read!()
|> String.split()
|> Enum.reduce(%{}, &words_to_map/2)
end
Helper functions
defp words_to_map(word, map) do
word
|> String.replace(~r/W/u, "")
|> filter_map(map)
end
defp filter_map("", map), do: map
defp filter_map(word, map) do
word = String.downcase(word)
Map.update(map, word, 1, &(&1 + 1))
end
Lazy (Stream)
+ Allows us to “control” memory consumption
- Processing overhead
Allows us to work with large datasets without loading them all into
memory
Lazy (Stream)
def process_lazy(path_to_file) do
path_to_file
|> File.stream!()
|> Stream.flat_map(&String.split/1)
|> Enum.reduce(%{}, &words_to_map/2)
end
Concurrent (Flow)
+ Concurrency
+ Allows us to “control” memory consumption
- Processing overhead
Allows us to process large or infinite collections concurrently on
multicore machines
GenStage is a new Elixir behaviour for exchanging events
with back-pressure between Elixir processes
producer
producer
consumer
producer
consumer
consumer
GenStage: demand-driven message exchange
producer
producer
consumer
consumer
Asks 10
Sends 10 max Sends 10 max
Asks 10
Dispatcher defines how the events are dispatched to
multiple consumers
P
C
C
C
Dispatcher
DemandDispatcher - dispatches events according to a
demand
P
C
C
C
1, 2, 3, 4, 5, 6, 7
1, 4, 7
2, 5
3, 6
PartitionDispatcher - dispatches events according to a
hash
P
C
C
C
“a”, “b”, “c”, “a”,
“d”, “c”, “a”
“c”, “c”
“a”, “a”,
“a”, “d”
“b”
Concurrent (Flow)
def process_flow(path_to_file) do
path_to_file
|> File.stream!()
|> Flow.from_enumerable()
|> Flow.flat_map(&String.split/1)
|> Flow.map(&String.replace(&1, ~r/W/u, ""))
|> Flow.filter_map(fn w -> w != "" end, &String.downcase/1)
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, map ->
Map.update(map, word, 1, &(&1 + 1))
end)
|> Enum.into(%{})
end
Concurrent (Flow)
def process_flow(path_to_file) do
path_to_file
|> File.stream!()
|> Flow.from_enumerable()
|> Flow.flat_map(&String.split/1)
|> Flow.map(&String.replace(&1, ~r/W/u, ""))
|> Flow.filter_map(fn w -> w != "" end, &String.downcase/1)
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, map ->
Map.update(map, word, 1, &(&1 + 1))
end)
|> Enum.into(%{})
end
P
Concurrent (Flow)
def process_flow(path_to_file) do
path_to_file
|> File.stream!()
|> Flow.from_enumerable()
|> Flow.flat_map(&String.split/1)
|> Flow.map(&String.replace(&1, ~r/W/u, ""))
|> Flow.filter_map(fn w -> w != "" end, &String.downcase/1)
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, map ->
Map.update(map, word, 1, &(&1 + 1))
end)
|> Enum.into(%{})
end
P
PC PC
DemandDispatcher
Concurrent (Flow)
def process_flow(path_to_file) do
path_to_file
|> File.stream!()
|> Flow.from_enumerable()
|> Flow.flat_map(&String.split/1)
|> Flow.map(&String.replace(&1, ~r/W/u, ""))
|> Flow.filter_map(fn w -> w != "" end, &String.downcase/1)
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, map ->
Map.update(map, word, 1, &(&1 + 1))
end)
|> Enum.into(%{})
end
P
PC PC
DemandDispatcher
PC PC
PartitionDispatcher
Concurrent (Flow)
def process_flow(path_to_file) do
path_to_file
|> File.stream!()
|> Flow.from_enumerable()
|> Flow.flat_map(&String.split/1)
|> Flow.map(&String.replace(&1, ~r/W/u, ""))
|> Flow.filter_map(fn w -> w != "" end, &String.downcase/1)
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, map ->
Map.update(map, word, 1, &(&1 + 1))
end)
|> Enum.into(%{})
end
P
PC PC
DemandDispatcher
PartitionDispatcher
PC PC
C CReducers
%{} %{}
Concurrent (Flow)
def process_flow(path_to_file) do
path_to_file
|> File.stream!()
|> Flow.from_enumerable()
|> Flow.flat_map(&String.split/1)
|> Flow.map(&String.replace(&1, ~r/W/u, ""))
|> Flow.filter_map(fn w -> w != "" end, &String.downcase/1)
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, map ->
Map.update(map, word, 1, &(&1 + 1))
end)
|> Enum.into(%{})
end
Concurrent (Flow): multiple sources
streams =
for file <- File.ls!(path_to_dir) do
File.stream!(path_to_dir <> "/" <> file,
read_ahead: 100_000)
end
Concurrent (Flow): multiple sources
streams
|> Flow.from_enumerables()
|> Flow.flat_map(&String.split/1)
|> Flow.map(&String.replace(&1, ~r/W/u, ""))
|> Flow.filter_map(fn w -> w != "" end, &String.downcase/1)
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, map ->
Map.update(map, word, 1, &(&1 + 1))
end)
|> Enum.into(%{})
Concurrent (Flow): multiple sources
streams
|> Flow.from_enumerables()
|> Flow.flat_map(&String.split/1)
|> Flow.map(&String.replace(&1, ~r/W/u, ""))
|> Flow.filter_map(fn w -> w != "" end, &String.downcase/1)
|> Flow.partition()
|> Flow.reduce(fn -> %{} end, fn word, map ->
Map.update(map, word, 1, &(&1 + 1))
end)
|> Enum.into(%{})
FS
P P
FSFS
P
C
%{}
C
%{}
2 cores
3 files
Configuration (demand, the number of stages)
Flow.partition(stages: 8)
• :stages - the number of partitions (reducer stages)
• :hash - the hashing function
• :max_demand - the maximum demand for this subscription
• :min_demand - the minimum demand for this subscription
• …
Experimental.Flow.Window
Splits a flow into windows that are materialized at certain triggers.
window = Flow.Window.global
|> Flow.Window.trigger_every(10, :keep)
window = Flow.Window.global
|> Flow.Window.trigger_every(10, :reset)
Experimental.Flow.Window
Flow.from_enumerable(1..100)
|> Flow.partition(window: window, stages: 1)
|> Flow.reduce(fn -> 0 end, & &1 + &2)
|> Flow.emit(:state)
|> Enum.to_list()
keep> [55, 210, 465, 820, 1275, 1830, 2485, 3240, 4095, 5050,
5050]
reset> [55, 155, 255, 355, 455, 555, 655, 755, 855, 955, 0]
THANK YOU!!!
https://github.com/yuriibodarev/elixir_flow

More Related Content

More from Elixir Club

BEAM architecture handbook - Andrea Leopardi | Elixir Club Ukraine
BEAM architecture handbook - Andrea Leopardi  | Elixir Club UkraineBEAM architecture handbook - Andrea Leopardi  | Elixir Club Ukraine
BEAM architecture handbook - Andrea Leopardi | Elixir Club UkraineElixir Club
 
You ain't gonna need write a GenServer - Ulisses Almeida | Elixir Club Ukraine
You ain't gonna need write a GenServer - Ulisses Almeida  | Elixir Club UkraineYou ain't gonna need write a GenServer - Ulisses Almeida  | Elixir Club Ukraine
You ain't gonna need write a GenServer - Ulisses Almeida | Elixir Club UkraineElixir Club
 
— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | ...
 — Knock, knock — An async templates — Who’s there? - Alexander Khokhlov  |  ... — Knock, knock — An async templates — Who’s there? - Alexander Khokhlov  |  ...
— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | ...Elixir Club
 
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Elixir Club
 
Erlang cluster. How is it? Production experience. — Valerii Vasylkov | Elixi...
Erlang cluster. How is it? Production experience. —  Valerii Vasylkov | Elixi...Erlang cluster. How is it? Production experience. —  Valerii Vasylkov | Elixi...
Erlang cluster. How is it? Production experience. — Valerii Vasylkov | Elixi...Elixir Club
 
Promo Phx4RailsDevs - Volodya Sveredyuk
Promo Phx4RailsDevs - Volodya SveredyukPromo Phx4RailsDevs - Volodya Sveredyuk
Promo Phx4RailsDevs - Volodya SveredyukElixir Club
 
Web of today — Alexander Khokhlov
Web of today —  Alexander KhokhlovWeb of today —  Alexander Khokhlov
Web of today — Alexander KhokhlovElixir Club
 
ElixirConf Eu 2018, what was it like? – Eugene Pirogov
ElixirConf Eu 2018, what was it like? – Eugene PirogovElixirConf Eu 2018, what was it like? – Eugene Pirogov
ElixirConf Eu 2018, what was it like? – Eugene PirogovElixir Club
 
Implementing GraphQL API in Elixir – Victor Deryagin
Implementing GraphQL API in Elixir – Victor DeryaginImplementing GraphQL API in Elixir – Victor Deryagin
Implementing GraphQL API in Elixir – Victor DeryaginElixir Club
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerElixir Club
 
GenServer in Action – Yurii Bodarev
GenServer in Action – Yurii Bodarev   GenServer in Action – Yurii Bodarev
GenServer in Action – Yurii Bodarev Elixir Club
 
Russian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
Russian Doll Paradox: Elixir Web without Phoenix - Alex RozumiiRussian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
Russian Doll Paradox: Elixir Web without Phoenix - Alex RozumiiElixir Club
 
Practical Fault Tolerance in Elixir - Alexei Sholik
Practical Fault Tolerance in Elixir - Alexei SholikPractical Fault Tolerance in Elixir - Alexei Sholik
Practical Fault Tolerance in Elixir - Alexei SholikElixir Club
 
Phoenix and beyond: Things we do with Elixir - Alexander Khokhlov
Phoenix and beyond: Things we do with Elixir - Alexander KhokhlovPhoenix and beyond: Things we do with Elixir - Alexander Khokhlov
Phoenix and beyond: Things we do with Elixir - Alexander KhokhlovElixir Club
 
Monads are just monoids in the category of endofunctors - Ike Kurghinyan
Monads are just monoids in the category of endofunctors - Ike KurghinyanMonads are just monoids in the category of endofunctors - Ike Kurghinyan
Monads are just monoids in the category of endofunctors - Ike KurghinyanElixir Club
 
Craft effective API with GraphQL and Absinthe - Ihor Katkov
Craft effective API with GraphQL and Absinthe - Ihor KatkovCraft effective API with GraphQL and Absinthe - Ihor Katkov
Craft effective API with GraphQL and Absinthe - Ihor KatkovElixir Club
 
Elixir in a service of government - Alex Troush
Elixir in a service of government - Alex TroushElixir in a service of government - Alex Troush
Elixir in a service of government - Alex TroushElixir Club
 
Pattern matching in Elixir by example - Alexander Khokhlov
Pattern matching in Elixir by example - Alexander KhokhlovPattern matching in Elixir by example - Alexander Khokhlov
Pattern matching in Elixir by example - Alexander KhokhlovElixir Club
 
Ecto and Phoenix: Doing web with Elixir - Yurii Bodarev
Ecto and Phoenix: Doing web with Elixir - Yurii BodarevEcto and Phoenix: Doing web with Elixir - Yurii Bodarev
Ecto and Phoenix: Doing web with Elixir - Yurii BodarevElixir Club
 
Handling external APIs with Elixir - Alex Rozumii
Handling external APIs with Elixir - Alex RozumiiHandling external APIs with Elixir - Alex Rozumii
Handling external APIs with Elixir - Alex RozumiiElixir Club
 

More from Elixir Club (20)

BEAM architecture handbook - Andrea Leopardi | Elixir Club Ukraine
BEAM architecture handbook - Andrea Leopardi  | Elixir Club UkraineBEAM architecture handbook - Andrea Leopardi  | Elixir Club Ukraine
BEAM architecture handbook - Andrea Leopardi | Elixir Club Ukraine
 
You ain't gonna need write a GenServer - Ulisses Almeida | Elixir Club Ukraine
You ain't gonna need write a GenServer - Ulisses Almeida  | Elixir Club UkraineYou ain't gonna need write a GenServer - Ulisses Almeida  | Elixir Club Ukraine
You ain't gonna need write a GenServer - Ulisses Almeida | Elixir Club Ukraine
 
— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | ...
 — Knock, knock — An async templates — Who’s there? - Alexander Khokhlov  |  ... — Knock, knock — An async templates — Who’s there? - Alexander Khokhlov  |  ...
— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | ...
 
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
 
Erlang cluster. How is it? Production experience. — Valerii Vasylkov | Elixi...
Erlang cluster. How is it? Production experience. —  Valerii Vasylkov | Elixi...Erlang cluster. How is it? Production experience. —  Valerii Vasylkov | Elixi...
Erlang cluster. How is it? Production experience. — Valerii Vasylkov | Elixi...
 
Promo Phx4RailsDevs - Volodya Sveredyuk
Promo Phx4RailsDevs - Volodya SveredyukPromo Phx4RailsDevs - Volodya Sveredyuk
Promo Phx4RailsDevs - Volodya Sveredyuk
 
Web of today — Alexander Khokhlov
Web of today —  Alexander KhokhlovWeb of today —  Alexander Khokhlov
Web of today — Alexander Khokhlov
 
ElixirConf Eu 2018, what was it like? – Eugene Pirogov
ElixirConf Eu 2018, what was it like? – Eugene PirogovElixirConf Eu 2018, what was it like? – Eugene Pirogov
ElixirConf Eu 2018, what was it like? – Eugene Pirogov
 
Implementing GraphQL API in Elixir – Victor Deryagin
Implementing GraphQL API in Elixir – Victor DeryaginImplementing GraphQL API in Elixir – Victor Deryagin
Implementing GraphQL API in Elixir – Victor Deryagin
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan Wintermeyer
 
GenServer in Action – Yurii Bodarev
GenServer in Action – Yurii Bodarev   GenServer in Action – Yurii Bodarev
GenServer in Action – Yurii Bodarev
 
Russian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
Russian Doll Paradox: Elixir Web without Phoenix - Alex RozumiiRussian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
Russian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
 
Practical Fault Tolerance in Elixir - Alexei Sholik
Practical Fault Tolerance in Elixir - Alexei SholikPractical Fault Tolerance in Elixir - Alexei Sholik
Practical Fault Tolerance in Elixir - Alexei Sholik
 
Phoenix and beyond: Things we do with Elixir - Alexander Khokhlov
Phoenix and beyond: Things we do with Elixir - Alexander KhokhlovPhoenix and beyond: Things we do with Elixir - Alexander Khokhlov
Phoenix and beyond: Things we do with Elixir - Alexander Khokhlov
 
Monads are just monoids in the category of endofunctors - Ike Kurghinyan
Monads are just monoids in the category of endofunctors - Ike KurghinyanMonads are just monoids in the category of endofunctors - Ike Kurghinyan
Monads are just monoids in the category of endofunctors - Ike Kurghinyan
 
Craft effective API with GraphQL and Absinthe - Ihor Katkov
Craft effective API with GraphQL and Absinthe - Ihor KatkovCraft effective API with GraphQL and Absinthe - Ihor Katkov
Craft effective API with GraphQL and Absinthe - Ihor Katkov
 
Elixir in a service of government - Alex Troush
Elixir in a service of government - Alex TroushElixir in a service of government - Alex Troush
Elixir in a service of government - Alex Troush
 
Pattern matching in Elixir by example - Alexander Khokhlov
Pattern matching in Elixir by example - Alexander KhokhlovPattern matching in Elixir by example - Alexander Khokhlov
Pattern matching in Elixir by example - Alexander Khokhlov
 
Ecto and Phoenix: Doing web with Elixir - Yurii Bodarev
Ecto and Phoenix: Doing web with Elixir - Yurii BodarevEcto and Phoenix: Doing web with Elixir - Yurii Bodarev
Ecto and Phoenix: Doing web with Elixir - Yurii Bodarev
 
Handling external APIs with Elixir - Alex Rozumii
Handling external APIs with Elixir - Alex RozumiiHandling external APIs with Elixir - Alex Rozumii
Handling external APIs with Elixir - Alex Rozumii
 

Recently uploaded

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 

Recently uploaded (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 

Experimental.flow - Yurii Bodarev

  • 1. Experimental.Flow An overview of experimental Elixir Flow module that allows developers to express processing steps for collections, like Stream, but utilizing the power of parallel execution.
  • 2. Resources ElixirConf 2016 - Keynote by José Valim www.youtube.com/watch?v=srtMWzyqdp8 Kyiv Elixir Meetup 3 - Flow-Based Programming with Elixir, Anton Mishchuk www.youtube.com/watch?v=yDaPaCxAVq8 www.slideshare.net/AntonMishchuk/flowbased-programming-with- elixir
  • 4. Task Implement word counting algorithm using Eager, Lazy and Concurrent approaches • Eager – Enum • Lazy – Stream • Concurrent - Flow
  • 5. Eager + High processing speed (for small collections) - May require large amounts of memory Good for fast processing of small collections
  • 6. Eager (Enum) def process_eager(path_to_file) do path_to_file |> File.read!() |> String.split() |> Enum.reduce(%{}, &words_to_map/2) end
  • 7. Helper functions defp words_to_map(word, map) do word |> String.replace(~r/W/u, "") |> filter_map(map) end defp filter_map("", map), do: map defp filter_map(word, map) do word = String.downcase(word) Map.update(map, word, 1, &(&1 + 1)) end
  • 8. Lazy (Stream) + Allows us to “control” memory consumption - Processing overhead Allows us to work with large datasets without loading them all into memory
  • 9. Lazy (Stream) def process_lazy(path_to_file) do path_to_file |> File.stream!() |> Stream.flat_map(&String.split/1) |> Enum.reduce(%{}, &words_to_map/2) end
  • 10. Concurrent (Flow) + Concurrency + Allows us to “control” memory consumption - Processing overhead Allows us to process large or infinite collections concurrently on multicore machines
  • 11. GenStage is a new Elixir behaviour for exchanging events with back-pressure between Elixir processes producer producer consumer producer consumer consumer
  • 12. GenStage: demand-driven message exchange producer producer consumer consumer Asks 10 Sends 10 max Sends 10 max Asks 10
  • 13. Dispatcher defines how the events are dispatched to multiple consumers P C C C Dispatcher
  • 14. DemandDispatcher - dispatches events according to a demand P C C C 1, 2, 3, 4, 5, 6, 7 1, 4, 7 2, 5 3, 6
  • 15. PartitionDispatcher - dispatches events according to a hash P C C C “a”, “b”, “c”, “a”, “d”, “c”, “a” “c”, “c” “a”, “a”, “a”, “d” “b”
  • 16. Concurrent (Flow) def process_flow(path_to_file) do path_to_file |> File.stream!() |> Flow.from_enumerable() |> Flow.flat_map(&String.split/1) |> Flow.map(&String.replace(&1, ~r/W/u, "")) |> Flow.filter_map(fn w -> w != "" end, &String.downcase/1) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, map -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{}) end
  • 17. Concurrent (Flow) def process_flow(path_to_file) do path_to_file |> File.stream!() |> Flow.from_enumerable() |> Flow.flat_map(&String.split/1) |> Flow.map(&String.replace(&1, ~r/W/u, "")) |> Flow.filter_map(fn w -> w != "" end, &String.downcase/1) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, map -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{}) end P
  • 18. Concurrent (Flow) def process_flow(path_to_file) do path_to_file |> File.stream!() |> Flow.from_enumerable() |> Flow.flat_map(&String.split/1) |> Flow.map(&String.replace(&1, ~r/W/u, "")) |> Flow.filter_map(fn w -> w != "" end, &String.downcase/1) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, map -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{}) end P PC PC DemandDispatcher
  • 19. Concurrent (Flow) def process_flow(path_to_file) do path_to_file |> File.stream!() |> Flow.from_enumerable() |> Flow.flat_map(&String.split/1) |> Flow.map(&String.replace(&1, ~r/W/u, "")) |> Flow.filter_map(fn w -> w != "" end, &String.downcase/1) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, map -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{}) end P PC PC DemandDispatcher PC PC PartitionDispatcher
  • 20. Concurrent (Flow) def process_flow(path_to_file) do path_to_file |> File.stream!() |> Flow.from_enumerable() |> Flow.flat_map(&String.split/1) |> Flow.map(&String.replace(&1, ~r/W/u, "")) |> Flow.filter_map(fn w -> w != "" end, &String.downcase/1) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, map -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{}) end P PC PC DemandDispatcher PartitionDispatcher PC PC C CReducers %{} %{}
  • 21. Concurrent (Flow) def process_flow(path_to_file) do path_to_file |> File.stream!() |> Flow.from_enumerable() |> Flow.flat_map(&String.split/1) |> Flow.map(&String.replace(&1, ~r/W/u, "")) |> Flow.filter_map(fn w -> w != "" end, &String.downcase/1) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, map -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{}) end
  • 22. Concurrent (Flow): multiple sources streams = for file <- File.ls!(path_to_dir) do File.stream!(path_to_dir <> "/" <> file, read_ahead: 100_000) end
  • 23. Concurrent (Flow): multiple sources streams |> Flow.from_enumerables() |> Flow.flat_map(&String.split/1) |> Flow.map(&String.replace(&1, ~r/W/u, "")) |> Flow.filter_map(fn w -> w != "" end, &String.downcase/1) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, map -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{})
  • 24. Concurrent (Flow): multiple sources streams |> Flow.from_enumerables() |> Flow.flat_map(&String.split/1) |> Flow.map(&String.replace(&1, ~r/W/u, "")) |> Flow.filter_map(fn w -> w != "" end, &String.downcase/1) |> Flow.partition() |> Flow.reduce(fn -> %{} end, fn word, map -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{}) FS P P FSFS P C %{} C %{} 2 cores 3 files
  • 25. Configuration (demand, the number of stages) Flow.partition(stages: 8) • :stages - the number of partitions (reducer stages) • :hash - the hashing function • :max_demand - the maximum demand for this subscription • :min_demand - the minimum demand for this subscription • …
  • 26. Experimental.Flow.Window Splits a flow into windows that are materialized at certain triggers. window = Flow.Window.global |> Flow.Window.trigger_every(10, :keep) window = Flow.Window.global |> Flow.Window.trigger_every(10, :reset)
  • 27. Experimental.Flow.Window Flow.from_enumerable(1..100) |> Flow.partition(window: window, stages: 1) |> Flow.reduce(fn -> 0 end, & &1 + &2) |> Flow.emit(:state) |> Enum.to_list() keep> [55, 210, 465, 820, 1275, 1830, 2485, 3240, 4095, 5050, 5050] reset> [55, 155, 255, 355, 455, 555, 655, 755, 855, 955, 0]