Shooting the Rapids

Maurice Naftalin
Maurice NaftalinComputer Software Consultant and Professional à Incept5
Shooting the Rapids:
Getting the Best from Java 8
Streams
Kirk Pepperdine @kcpeppe
Maurice Naftalin @mauricenaftalin
Devoxx Belgium, Nov. 2015
• Specialises in performance tuning
• speaks frequently about performance
• author of performance tuning workshop
• Co-founder
• performance diagnostic tooling
• Java Champion (since 2006)
About Kirk
• Specialises in performance tuning
• speaks frequently about performance
• author of performance tuning workshop
• Co-founder
• performance diagnostic tooling
• Java Champion (since 2006)
About Kirk
About Maurice
About Maurice
About Maurice
Co-author Author
About Maurice
Co-author Author
Java
Champion
JavaOne
Rock Star
Subjects Covered in this Talk
• Background – lambdas and streams
• Performance of our example
• Effect of parallelizing
• Splitting input data efficiently
• When to go parallel
• Parallel streams in the real world
Benchmark Alert
Predicate<Matcher> matches = new Predicate<Matcher>() {

@Override

public boolean test(Matcher matcher) {

return matcher.find();

}

};
What is a Lambda?
matcher
matcher.find()
matcher
matcher.find()
Predicate<Matcher> matches = new Predicate<Matcher>() {

@Override

public boolean test(Matcher matcher) {

return matcher.find();

}

};
Predicate<Matcher> matches =
What is a Lambda?
matcher
matcher.find()
matcher
matcher.find()
Predicate<Matcher> matches = new Predicate<Matcher>() {

@Override

public boolean test(Matcher matcher) {

return matcher.find();

}

};
Predicate<Matcher> matches =
What is a Lambda?
matcher
Predicate<Matcher> matches =
matcher.find()
matcher
matcher.find()
Predicate<Matcher> matches = new Predicate<Matcher>() {

@Override

public boolean test(Matcher matcher) {

return matcher.find();

}

};
Predicate<Matcher> matches =
What is a Lambda?
matcherPredicate<Matcher> matches =
matcher.find()
matcher
matcher.find()
Predicate<Matcher> matches = new Predicate<Matcher>() {

@Override

public boolean test(Matcher matcher) {

return matcher.find();

}

};
Predicate<Matcher> matches =
What is a Lambda?
matcherPredicate<Matcher> matches =
matcher.find()
->
matcher
matcher.find()
Predicate<Matcher> matches = new Predicate<Matcher>() {

@Override

public boolean test(Matcher matcher) {

return matcher.find();

}

};
Predicate<Matcher> matches =
What is a Lambda?
matcherPredicate<Matcher> matches = matcher.find()->
matcher
matcher.find()
Predicate<Matcher> matches = new Predicate<Matcher>() {

@Override

public boolean test(Matcher matcher) {

return matcher.find();

}

};
Predicate<Matcher> matches =
What is a Lambda?
matcherPredicate<Matcher> matches =
A lambda is a function
from arguments to result
matcher.find()->
matcher
matcher.find()
Example: Processing GC Logfile
⋮
2.869: Application time: 1.0001540 seconds
5.342: Application time: 0.0801231 seconds
8.382: Application time: 1.1013574 seconds
⋮
Example: Processing GC Logfile
⋮
2.869: Application time: 1.0001540 seconds
5.342: Application time: 0.0801231 seconds
8.382: Application time: 1.1013574 seconds
⋮
DoubleSummaryStatistics
{count=3, sum=2.181635, min=0.080123, average=0.727212, max=1.101357}
Old School Code
DoubleSummaryStatistic summary = new DoubleSummaryStatistic();
Pattern stoppedTimePattern =
Pattern.compile("Application time: (d+.d+)");


while ( ( logRecord = logFileReader.readLine()) != null) {

Matcher matcher = stoppedTimePattern.matcher(logRecord);

if ( matcher.find()) {
double value = Double.parseDouble( matcher.group(1));

summary.add( value);

}

}
Old School Code
DoubleSummaryStatistic summary = new DoubleSummaryStatistic();
Pattern stoppedTimePattern =
Pattern.compile("Application time: (d+.d+)");


while ( ( logRecord = logFileReader.readLine()) != null) {

Matcher matcher = stoppedTimePattern.matcher(logRecord);

if ( matcher.find()) {
double value = Double.parseDouble( matcher.group(1));

summary.add( value);

}

}
Let’s look at the features in this code
Data Source
DoubleSummaryStatistic summary = new DoubleSummaryStatistic();
Pattern stoppedTimePattern =
Pattern.compile("Application time: (d+.d+)");


while ( ( logRecord = logFileReader.readLine()) != null) {

Matcher matcher = stoppedTimePattern.matcher(logRecord);

if ( matcher.find()) {
double value = Double.parseDouble( matcher.group(1));

summary.add( value);

}

}
Map to Matcher
DoubleSummaryStatistic summary = new DoubleSummaryStatistic();
Pattern stoppedTimePattern =
Pattern.compile("Application time: (d+.d+)");


while ( ( logRecord = logFileReader.readLine()) != null) {

Matcher matcher = stoppedTimePattern.matcher(logRecord);

if ( matcher.find()) {
double value = Double.parseDouble( matcher.group(1));

summary.add( value);

}

}
Filter
DoubleSummaryStatistic summary = new DoubleSummaryStatistic();
Pattern stoppedTimePattern =
Pattern.compile("Application time: (d+.d+)");


while ( ( logRecord = logFileReader.readLine()) != null) {

Matcher matcher = stoppedTimePattern.matcher(logRecord);

if ( matcher.find()) {
double value = Double.parseDouble( matcher.group(1));

summary.add( value);

}

}
Map to Double
DoubleSummaryStatistic summary = new DoubleSummaryStatistic();
Pattern stoppedTimePattern =
Pattern.compile("Application time: (d+.d+)");


while ( ( logRecord = logFileReader.readLine()) != null) {

Matcher matcher = stoppedTimePattern.matcher(logRecord);

if ( matcher.find()) {
double value = Double.parseDouble( matcher.group(1));

summary.add( value);

}

}
Collect Results (Reduce)
DoubleSummaryStatistic summary = new DoubleSummaryStatistic();
Pattern stoppedTimePattern =
Pattern.compile("Application time: (d+.d+)");


while ( ( logRecord = logFileReader.readLine()) != null) {

Matcher matcher = stoppedTimePattern.matcher(logRecord);

if ( matcher.find()) {
double value = Double.parseDouble( matcher.group(1));

summary.add( value);

}

}
Java 8 Streams
• A sequence of values,“in motion”
• source and intermediate operations set the stream up lazily
• a terminal operation “pulls” values eagerly down the stream
collection.stream()
.intermediateOp
⋮
.intermediateOp
.terminalOp
Stream Sources
• New method Collection.stream()
• Many other sources:
• Arrays.stream(Object[])
• Streams.of(Object...)
• Stream.iterate(Object,UnaryOperator)
• Files.lines()
• BufferedReader.lines()
• Random.ints()
• JarFile.stream()
• …
Imperative to Stream
DoubleSummaryStatistics statistics =

Files.lines(new File(“gc.log”).toPath())

.map(stoppedTimePattern::matcher)

.filter(Matcher::find)

.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble)
.summaryStatistics();
Stream Source
DoubleSummaryStatistics statistics =

Files.lines(new File(“gc.log”).toPath())

.map(stoppedTimePattern::matcher)

.filter(Matcher::find)

.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble)
.summaryStatistics();
Intermediate Operations
DoubleSummaryStatistics statistics =

Files.lines(new File(“gc.log”).toPath())

.map(stoppedTimePattern::matcher)

.filter(Matcher::find)

.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble)
.summaryStatistics();
Method References
DoubleSummaryStatistics statistics =

Files.lines(new File(“gc.log”).toPath())

.map(stoppedTimePattern::matcher)

.filter(Matcher::find)

.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble)
.summaryStatistics();
Terminal Operation
DoubleSummaryStatistics statistics =

Files.lines(new File(“gc.log”).toPath())

.map(stoppedTimePattern::matcher)

.filter(Matcher::find)

.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble)
.summaryStatistics();
Visualising Sequential Streams
x2x0 x1 x3x0 x1 x2 x3
Source Map Filter Reduction
Intermediate
Operations
Terminal
Operation
“Values in Motion”
Visualising Sequential Streams
x2x0 x1 x3x1 x2 x3 ✔
Source Map Filter Reduction
Intermediate
Operations
Terminal
Operation
“Values in Motion”
Visualising Sequential Streams
x2x0 x1 x3 x1x2 x3 ❌✔
Source Map Filter Reduction
Intermediate
Operations
Terminal
Operation
“Values in Motion”
Visualising Sequential Streams
x2x0 x1 x3 x1x2x3 ❌✔
Source Map Filter Reduction
Intermediate
Operations
Terminal
Operation
“Values in Motion”
Old School: 13.3 secs
Sequential: 13.8 secs
- Should be the same workload
- Stream code is cleaner, easier to read
How Does It Perform?
24M line file, MacBook Pro, Haswell i7, 4 cores, hyperthreaded, Java 9.0
Can We Do Better?
• We might be able to if the workload is parallelizable
• split stream into many segments
• process each segment
• combine results
• Requirements exactly match Fork/Join workflow
x2
Visualizing Parallel Streams
x0
x1
x3
x0
x1
x2
x3
x2
Visualizing Parallel Streams
x0
x1
x3
x0
x1
x2
x3
x2
Visualizing Parallel Streams
x1
x3
x0
x1
x3
✔
❌
x2
Visualizing Parallel Streams
x1 y3
x0
x1
x3
✔
❌
Splitting Stream Sources
• Stream source is a Spliterator
• can both iterate over data and – where possible – split it
Splitting the Data
Splitting the Data
Splitting the Data
Splitting the Data
Splitting the Data
Splitting the Data
Splitting the Data
Splitting the Data
Splitting the Data
Parallel Streams
DoubleSummaryStatistics statistics =

Files.lines(new File(“gc.log”).toPath())
.parallel()

.map(stoppedTimePattern::matcher)

.filter(Matcher::find)

.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble)
.summaryStatistics();
About Fork/Join
• Introduced in Java 7
• draws from a common pool of ForkJoinWorkerThread
• default pool size == HW cores – 1
• assumes workload will be CPU bound
• On its own, not an easy coding idiom
• parallel streams provide an abstraction layer
• Spliterator defines how to split stream
• framework code submits sub-tasks to the common Fork/Join pool
Old School: 13.3 secs
Sequential: 13.8 secs
Parallel: 9.5 secs
- 1.45x faster
- but not 8x faster (????)
How Does That Perform?
24M lines, 2.8GHz 8-core i7, 16GB, OS X, Java 9.0
In Fact!!!!
• Different benchmarks yield a mixed bag of results
• some were better
• some were the same
• some were worse!
Open Questions
• Under what conditions are things better
• or worse
• When should we parallelize
• and when is serial better
Open Questions
• Under what conditions are things better
• or worse
• When should we parallelize
• and when is serial better
Answer depends upon where the bottleneck is
Where is Our Bottleneck?
• I/O operations
• not a surprise, we’re reading from a file
• Java 9 uses FileChannelLineSpliterator
• 2x better than Java 8’s implementation
76.0% 0 + 5941 sun.nio.ch.FileDispatcherImpl.pread0
Poorly Splitting Sources
• Some sources split worse than others
• LinkedList vs ArrayList
• Streaming I/O is problematic
• more threads == more pressure on contended resource
• thrashing and other ill effects
• Workload size doesn’t cover the overheads
Streaming I/O Bottleneck
x2x0 x1 x3x0 x1 x2 x3
Streaming I/O Bottleneck
✔
❌
x2x1x0 x1 x3
5.342: … nds
LineSpliterator
2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n
spliterator coverage
5.342: … nds
LineSpliterator
2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n
spliterator coverage
MappedByteBuffer
5.342: … nds
LineSpliterator
2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n
spliterator coverage
MappedByteBuffer mid
5.342: … nds
LineSpliterator
2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n
spliterator coverage
MappedByteBuffer mid
5.342: … nds
LineSpliterator
2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n
spliterator coveragenew spliterator coverage
MappedByteBuffer mid
5.342: … nds
LineSpliterator
2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n
spliterator coveragenew spliterator coverage
MappedByteBuffer mid
Included in JDK9 as FileChannelLinesSpliterator
In-memory Comparison
• Read GC log into an ArrayList prior to processing
Old School: 9.4 secs
Sequential: 9.9 secs
Parallel: 2.7 secs
- 4.25x faster
- better but still not 8x faster
In-memory Comparison
24M lines, 2.8GHz 8 core i7, 16GB, OS X, JDK 9.0
Justifying the Overhead
CPNQ performance model:
C - number of submitters
P - number of CPUs
N - number of elements
Q - cost of the operation
cost of intermediate operations is N * Q
overhead of setting up F/J framework is ~100µs
Amortizing Setup Costs
• N*Q needs to be large
• Q can often only be estimated
• N may only be known at run time
• Rule of thumb, N > 10,000
• P is the number of processors
• P == number for cores for CPU bound
• P < number of cores otherwise
Other Gotchas
• Frequent hand-offs place pressure on thread schedulers
• effect is magnified when a hypervisor is involved
• estimated 80,000 cycles to handoff data between threads
• you can do a lot of processing in 80,000 cycles
• Too many threads places pressure on thread schedulers
• responsible for other ill effects (TTSP)
• too few threads may leave hardware under-utilized
Simulated Server Environment
ExecutorService threadPool = Executors.newFixedThreadPool(10);
threadPool.execute(() -> {
try {
long timer = System.currentTimeMillis();
value = Files.lines( new File(“gc.log").toPath()).parallel()
.map(applicationStoppedTimePattern::matcher)
.filter(Matcher::find)
.map( matcher -> matcher.group(2))
.mapToDouble(Double::parseDouble)
.summaryStatistics().getSum();
} catch (Exception ex) {}
});
Work Flow and Results
• First task to arrive will consume all ForkJoinWorkerThread
• downstream tasks wait for a ForkJoinWorkerThread
• downstream tasks start intermixing with initial task
• Initial task collects dead time as it competes for threads
• all other tasks collect dead time as they either
• compete or wait for a ForkJoinWorkerThread
Work Flow and Results
• First task to arrive will consume all ForkJoinWorkerThread
• downstream tasks wait for a ForkJoinWorkerThread
• downstream tasks start intermixing with initial task
• Initial task collects dead time as it competes for threads
• all other tasks collect dead time as they either
• compete or wait for a ForkJoinWorkerThread
System is stressed beyond capacity
Intermediate Operation Bottleneck
68.6% 1384 + 0 java.util.regex.Pattern$Curly.match
26.6% 521 + 15 java.util.stream.ReferencePipeline$3$1.accept
Intermediate Operation Bottleneck
• Bottleneck is in pattern matching
• but, streaming infrastructure isn’t far behind!
68.6% 1384 + 0 java.util.regex.Pattern$Curly.match
26.6% 521 + 15 java.util.stream.ReferencePipeline$3$1.accept
Tragedy of the Commons
Garrett Hardin, ecologist (1968):
Imagine the grazing of animals on a common ground. Each
flock owner gains if they add to their own flock. But
every animal added to the total degrades the commons a
small amount.
Tragedy of the Commons
Tragedy of the Commons
You have a finite amount of hardware
– it might be in your best interest to grab it all
– but if everyone behaves the same way…
Simulated Server Environment
Simulated Server Environment
• Submit 10 tasks to Fork-Join (via Executor thread-pool)
• first result comes out in 32 seconds
• compared to 9.5 seconds for individually submitted task
• high system time reflects task is I/O bounded
In-MemoryVariation
In-MemoryVariation
• Preload log file
In-MemoryVariation
• Preload log file
• Submit 10 tasks to Fork-Join (via Executor thread-pool)
• first result comes out in 23 seconds
• compared to 4.5 seconds for individually submitted task
• task is CPU bound
Conclusions
Sequential stream performance comparable to imperative code
Going parallel is worthwhile IF
- task is suitable
- expensive enough to amortize setup costs
- no inter-task communication needed
- data source is suitable
- environment is suitable
Need to monitor JDK to understanding bottlenecks
- Fork/Join pool is not well instrumented
Resources
http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html
Resources
http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html
1 sur 89

Recommandé

Good and Wicked Fairies, and the Tragedy of the Commons: Understanding the Pe... par
Good and Wicked Fairies, and the Tragedy of the Commons: Understanding the Pe...Good and Wicked Fairies, and the Tragedy of the Commons: Understanding the Pe...
Good and Wicked Fairies, and the Tragedy of the Commons: Understanding the Pe...Maurice Naftalin
613 vues144 diapositives
Shooting the Rapids: Getting the Best from Java 8 Streams par
Shooting the Rapids: Getting the Best from Java 8 StreamsShooting the Rapids: Getting the Best from Java 8 Streams
Shooting the Rapids: Getting the Best from Java 8 StreamsMaurice Naftalin
587 vues110 diapositives
Parallel-Ready Java Code: Managing Mutation in an Imperative Language par
Parallel-Ready Java Code: Managing Mutation in an Imperative LanguageParallel-Ready Java Code: Managing Mutation in an Imperative Language
Parallel-Ready Java Code: Managing Mutation in an Imperative LanguageMaurice Naftalin
1.3K vues212 diapositives
Let's Get to the Rapids par
Let's Get to the RapidsLet's Get to the Rapids
Let's Get to the RapidsMaurice Naftalin
536 vues95 diapositives
Journey's End – Collection and Reduction in the Stream API par
Journey's End – Collection and Reduction in the Stream APIJourney's End – Collection and Reduction in the Stream API
Journey's End – Collection and Reduction in the Stream APIMaurice Naftalin
583 vues157 diapositives
Writing Hadoop Jobs in Scala using Scalding par
Writing Hadoop Jobs in Scala using ScaldingWriting Hadoop Jobs in Scala using Scalding
Writing Hadoop Jobs in Scala using ScaldingToni Cebrián
2.9K vues93 diapositives

Contenu connexe

Tendances

Effective testing for spark programs Strata NY 2015 par
Effective testing for spark programs   Strata NY 2015Effective testing for spark programs   Strata NY 2015
Effective testing for spark programs Strata NY 2015Holden Karau
13.5K vues38 diapositives
Scalding: Twitter's Scala DSL for Hadoop/Cascading par
Scalding: Twitter's Scala DSL for Hadoop/CascadingScalding: Twitter's Scala DSL for Hadoop/Cascading
Scalding: Twitter's Scala DSL for Hadoop/Cascadingjohnynek
10.4K vues34 diapositives
HBase RowKey design for Akka Persistence par
HBase RowKey design for Akka PersistenceHBase RowKey design for Akka Persistence
HBase RowKey design for Akka PersistenceKonrad Malawski
2.3K vues75 diapositives
Apache Spark Structured Streaming for Machine Learning - StrataConf 2016 par
Apache Spark Structured Streaming for Machine Learning - StrataConf 2016Apache Spark Structured Streaming for Machine Learning - StrataConf 2016
Apache Spark Structured Streaming for Machine Learning - StrataConf 2016Holden Karau
1.2K vues44 diapositives
Kotlin @ Coupang Backed - JetBrains Day seoul 2018 par
Kotlin @ Coupang Backed - JetBrains Day seoul 2018Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Kotlin @ Coupang Backed - JetBrains Day seoul 2018Sunghyouk Bae
2.3K vues68 diapositives
Weaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo par
Weaving Dataflows with Silk - ScalaMatsuri 2014, TokyoWeaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo
Weaving Dataflows with Silk - ScalaMatsuri 2014, TokyoTaro L. Saito
3K vues37 diapositives

Tendances(20)

Effective testing for spark programs Strata NY 2015 par Holden Karau
Effective testing for spark programs   Strata NY 2015Effective testing for spark programs   Strata NY 2015
Effective testing for spark programs Strata NY 2015
Holden Karau13.5K vues
Scalding: Twitter's Scala DSL for Hadoop/Cascading par johnynek
Scalding: Twitter's Scala DSL for Hadoop/CascadingScalding: Twitter's Scala DSL for Hadoop/Cascading
Scalding: Twitter's Scala DSL for Hadoop/Cascading
johnynek10.4K vues
HBase RowKey design for Akka Persistence par Konrad Malawski
HBase RowKey design for Akka PersistenceHBase RowKey design for Akka Persistence
HBase RowKey design for Akka Persistence
Konrad Malawski2.3K vues
Apache Spark Structured Streaming for Machine Learning - StrataConf 2016 par Holden Karau
Apache Spark Structured Streaming for Machine Learning - StrataConf 2016Apache Spark Structured Streaming for Machine Learning - StrataConf 2016
Apache Spark Structured Streaming for Machine Learning - StrataConf 2016
Holden Karau1.2K vues
Kotlin @ Coupang Backed - JetBrains Day seoul 2018 par Sunghyouk Bae
Kotlin @ Coupang Backed - JetBrains Day seoul 2018Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Sunghyouk Bae2.3K vues
Weaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo par Taro L. Saito
Weaving Dataflows with Silk - ScalaMatsuri 2014, TokyoWeaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo
Weaving Dataflows with Silk - ScalaMatsuri 2014, Tokyo
Taro L. Saito3K vues
Beyond parallelize and collect - Spark Summit East 2016 par Holden Karau
Beyond parallelize and collect - Spark Summit East 2016Beyond parallelize and collect - Spark Summit East 2016
Beyond parallelize and collect - Spark Summit East 2016
Holden Karau2K vues
Ge aviation spark application experience porting analytics into py spark ml p... par Databricks
Ge aviation spark application experience porting analytics into py spark ml p...Ge aviation spark application experience porting analytics into py spark ml p...
Ge aviation spark application experience porting analytics into py spark ml p...
Databricks1.1K vues
ITSubbotik - как скрестить ежа с ужом или подводные камни внедрения функциона... par Vyacheslav Lapin
ITSubbotik - как скрестить ежа с ужом или подводные камни внедрения функциона...ITSubbotik - как скрестить ежа с ужом или подводные камни внедрения функциона...
ITSubbotik - как скрестить ежа с ужом или подводные камни внедрения функциона...
Vyacheslav Lapin207 vues
Reactive Streams / Akka Streams - GeeCON Prague 2014 par Konrad Malawski
Reactive Streams / Akka Streams - GeeCON Prague 2014Reactive Streams / Akka Streams - GeeCON Prague 2014
Reactive Streams / Akka Streams - GeeCON Prague 2014
Konrad Malawski5.5K vues
Algebird : Abstract Algebra for big data analytics. Devoxx 2014 par Samir Bessalah
Algebird : Abstract Algebra for big data analytics. Devoxx 2014Algebird : Abstract Algebra for big data analytics. Devoxx 2014
Algebird : Abstract Algebra for big data analytics. Devoxx 2014
Samir Bessalah5.7K vues
2014 akka-streams-tokyo-japanese par Konrad Malawski
2014 akka-streams-tokyo-japanese2014 akka-streams-tokyo-japanese
2014 akka-streams-tokyo-japanese
Konrad Malawski25.5K vues
Kotlin @ Coupang Backend 2017 par Sunghyouk Bae
Kotlin @ Coupang Backend 2017Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017
Sunghyouk Bae1.8K vues
Unit testing of spark applications par Knoldus Inc.
Unit testing of spark applicationsUnit testing of spark applications
Unit testing of spark applications
Knoldus Inc.13.5K vues
Storm - As deep into real-time data processing as you can get in 30 minutes. par Dan Lynn
Storm - As deep into real-time data processing as you can get in 30 minutes.Storm - As deep into real-time data processing as you can get in 30 minutes.
Storm - As deep into real-time data processing as you can get in 30 minutes.
Dan Lynn22.7K vues
あなたのScalaを爆速にする7つの方法 par x1 ichi
あなたのScalaを爆速にする7つの方法あなたのScalaを爆速にする7つの方法
あなたのScalaを爆速にする7つの方法
x1 ichi9.1K vues
Storm: The Real-Time Layer - GlueCon 2012 par Dan Lynn
Storm: The Real-Time Layer  - GlueCon 2012Storm: The Real-Time Layer  - GlueCon 2012
Storm: The Real-Time Layer - GlueCon 2012
Dan Lynn11.8K vues
Distributed Realtime Computation using Apache Storm par the100rabh
Distributed Realtime Computation using Apache StormDistributed Realtime Computation using Apache Storm
Distributed Realtime Computation using Apache Storm
the100rabh741 vues
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016 par Holden Karau
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016
Improving PySpark Performance - Spark Beyond the JVM @ PyData DC 2016
Holden Karau639 vues

En vedette

erlang at hover.in , Devcamp Blr 09 par
erlang at hover.in , Devcamp Blr 09erlang at hover.in , Devcamp Blr 09
erlang at hover.in , Devcamp Blr 09Bhasker Kode
4.5K vues40 diapositives
Metasepi team meeting #6: "Snatch-driven development" par
Metasepi team meeting #6: "Snatch-driven development"Metasepi team meeting #6: "Snatch-driven development"
Metasepi team meeting #6: "Snatch-driven development"Kiwamu Okabe
4.2K vues39 diapositives
Présentation Kivy (et projets associés) à Pycon-fr 2013 par
Présentation Kivy (et projets associés) à Pycon-fr 2013Présentation Kivy (et projets associés) à Pycon-fr 2013
Présentation Kivy (et projets associés) à Pycon-fr 2013Gabriel Pettier
6.8K vues43 diapositives
Managing gang of chaotic developers is complex at Agile Tour Riga 2012 par
Managing gang of chaotic developers is complex at Agile Tour Riga 2012Managing gang of chaotic developers is complex at Agile Tour Riga 2012
Managing gang of chaotic developers is complex at Agile Tour Riga 2012Piotr Burdylo
1.7K vues59 diapositives
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009 par
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009Alexandre Morgaut
5K vues36 diapositives
Vert.x - JDD 2013 (English) par
Vert.x - JDD 2013 (English)Vert.x - JDD 2013 (English)
Vert.x - JDD 2013 (English)Bartek Zdanowski
7.3K vues28 diapositives

En vedette(20)

erlang at hover.in , Devcamp Blr 09 par Bhasker Kode
erlang at hover.in , Devcamp Blr 09erlang at hover.in , Devcamp Blr 09
erlang at hover.in , Devcamp Blr 09
Bhasker Kode4.5K vues
Metasepi team meeting #6: "Snatch-driven development" par Kiwamu Okabe
Metasepi team meeting #6: "Snatch-driven development"Metasepi team meeting #6: "Snatch-driven development"
Metasepi team meeting #6: "Snatch-driven development"
Kiwamu Okabe4.2K vues
Présentation Kivy (et projets associés) à Pycon-fr 2013 par Gabriel Pettier
Présentation Kivy (et projets associés) à Pycon-fr 2013Présentation Kivy (et projets associés) à Pycon-fr 2013
Présentation Kivy (et projets associés) à Pycon-fr 2013
Gabriel Pettier6.8K vues
Managing gang of chaotic developers is complex at Agile Tour Riga 2012 par Piotr Burdylo
Managing gang of chaotic developers is complex at Agile Tour Riga 2012Managing gang of chaotic developers is complex at Agile Tour Riga 2012
Managing gang of chaotic developers is complex at Agile Tour Riga 2012
Piotr Burdylo1.7K vues
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009 par Alexandre Morgaut
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009
Wakanda: a new end-to-end JavaScript platform - JSConf Berlin 2009
Agile Management 2013 - Nie tylko it par Piotr Burdylo
Agile Management 2013 - Nie tylko itAgile Management 2013 - Nie tylko it
Agile Management 2013 - Nie tylko it
Piotr Burdylo4.6K vues
There's a Monster in My Closet: Architecture of a MongoDB-powered Event Proce... par thegdb
There's a Monster in My Closet: Architecture of a MongoDB-powered Event Proce...There's a Monster in My Closet: Architecture of a MongoDB-powered Event Proce...
There's a Monster in My Closet: Architecture of a MongoDB-powered Event Proce...
thegdb3.9K vues
A Scalable I/O Manager for GHC par Johan Tibell
A Scalable I/O Manager for GHCA Scalable I/O Manager for GHC
A Scalable I/O Manager for GHC
Johan Tibell2.2K vues
O'Reilly ETech Conference: Laszlo RIA par Oliver Steele
O'Reilly ETech Conference: Laszlo RIAO'Reilly ETech Conference: Laszlo RIA
O'Reilly ETech Conference: Laszlo RIA
Oliver Steele1.7K vues
Federated CDNs: What every service provider should know par Patrick Hurley
Federated CDNs: What every service provider should knowFederated CDNs: What every service provider should know
Federated CDNs: What every service provider should know
Patrick Hurley3.3K vues
Jensimmons html5live-responsivedesign par Jen Simmons
Jensimmons html5live-responsivedesignJensimmons html5live-responsivedesign
Jensimmons html5live-responsivedesign
Jen Simmons1.9K vues
Monadologie par league
MonadologieMonadologie
Monadologie
league3.6K vues
Be careful when entering a casino (Agile by Example 2012) par Piotr Burdylo
Be careful when entering a casino (Agile by Example 2012)Be careful when entering a casino (Agile by Example 2012)
Be careful when entering a casino (Agile by Example 2012)
Piotr Burdylo1.2K vues
Sneaking Scala through the Back Door par Dianne Marsh
Sneaking Scala through the Back DoorSneaking Scala through the Back Door
Sneaking Scala through the Back Door
Dianne Marsh10.7K vues

Similaire à Shooting the Rapids

AI與大數據數據處理 Spark實戰(20171216) par
AI與大數據數據處理 Spark實戰(20171216)AI與大數據數據處理 Spark實戰(20171216)
AI與大數據數據處理 Spark實戰(20171216)Paul Chao
1.1K vues127 diapositives
NET Systems Programming Learned the Hard Way.pptx par
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxpetabridge
282 vues43 diapositives
Solr @ Etsy - Apache Lucene Eurocon par
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconGiovanni Fernandez-Kincade
1.6K vues56 diapositives
Distributed Real-Time Stream Processing: Why and How 2.0 par
Distributed Real-Time Stream Processing:  Why and How 2.0Distributed Real-Time Stream Processing:  Why and How 2.0
Distributed Real-Time Stream Processing: Why and How 2.0Petr Zapletal
5.5K vues98 diapositives
Spark Summit EU talk by Herman van Hovell par
Spark Summit EU talk by Herman van HovellSpark Summit EU talk by Herman van Hovell
Spark Summit EU talk by Herman van HovellSpark Summit
2.3K vues50 diapositives
Hadoop and HBase experiences in perf log project par
Hadoop and HBase experiences in perf log projectHadoop and HBase experiences in perf log project
Hadoop and HBase experiences in perf log projectMao Geng
832 vues41 diapositives

Similaire à Shooting the Rapids(20)

AI與大數據數據處理 Spark實戰(20171216) par Paul Chao
AI與大數據數據處理 Spark實戰(20171216)AI與大數據數據處理 Spark實戰(20171216)
AI與大數據數據處理 Spark實戰(20171216)
Paul Chao1.1K vues
NET Systems Programming Learned the Hard Way.pptx par petabridge
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
petabridge282 vues
Distributed Real-Time Stream Processing: Why and How 2.0 par Petr Zapletal
Distributed Real-Time Stream Processing:  Why and How 2.0Distributed Real-Time Stream Processing:  Why and How 2.0
Distributed Real-Time Stream Processing: Why and How 2.0
Petr Zapletal5.5K vues
Spark Summit EU talk by Herman van Hovell par Spark Summit
Spark Summit EU talk by Herman van HovellSpark Summit EU talk by Herman van Hovell
Spark Summit EU talk by Herman van Hovell
Spark Summit2.3K vues
Hadoop and HBase experiences in perf log project par Mao Geng
Hadoop and HBase experiences in perf log projectHadoop and HBase experiences in perf log project
Hadoop and HBase experiences in perf log project
Mao Geng832 vues
No more struggles with Apache Spark workloads in production par Chetan Khatri
No more struggles with Apache Spark workloads in productionNo more struggles with Apache Spark workloads in production
No more struggles with Apache Spark workloads in production
Chetan Khatri168 vues
Finagle and Java Service Framework at Pinterest par Pavan Chitumalla
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
Pavan Chitumalla546 vues
Big data week presentation par Joseph Adler
Big data week presentationBig data week presentation
Big data week presentation
Joseph Adler1.1K vues
What is new in java 8 concurrency par kshanth2101
What is new in java 8 concurrencyWhat is new in java 8 concurrency
What is new in java 8 concurrency
kshanth2101458 vues
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scala par Chetan Khatri
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scalaAutomate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scala
Automate ml workflow_transmogrif_ai-_chetan_khatri_berlin-scala
Chetan Khatri88 vues
Distributed Real-Time Stream Processing: Why and How: Spark Summit East talk ... par Spark Summit
Distributed Real-Time Stream Processing: Why and How: Spark Summit East talk ...Distributed Real-Time Stream Processing: Why and How: Spark Summit East talk ...
Distributed Real-Time Stream Processing: Why and How: Spark Summit East talk ...
Spark Summit2.2K vues
Distributed Stream Processing - Spark Summit East 2017 par Petr Zapletal
Distributed Stream Processing - Spark Summit East 2017Distributed Stream Processing - Spark Summit East 2017
Distributed Stream Processing - Spark Summit East 2017
Petr Zapletal883 vues
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla par Spark Summit
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-MallaKerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Spark Summit1.2K vues
JavaOne 2016: Code Generation with JavaCompiler for Fun, Speed and Business P... par Juan Cruz Nores
JavaOne 2016: Code Generation with JavaCompiler for Fun, Speed and Business P...JavaOne 2016: Code Generation with JavaCompiler for Fun, Speed and Business P...
JavaOne 2016: Code Generation with JavaCompiler for Fun, Speed and Business P...
Juan Cruz Nores2K vues
Real-Time Spark: From Interactive Queries to Streaming par Databricks
Real-Time Spark: From Interactive Queries to StreamingReal-Time Spark: From Interactive Queries to Streaming
Real-Time Spark: From Interactive Queries to Streaming
Databricks5.2K vues

Dernier

HarshithAkkapelli_Presentation.pdf par
HarshithAkkapelli_Presentation.pdfHarshithAkkapelli_Presentation.pdf
HarshithAkkapelli_Presentation.pdfharshithakkapelli
11 vues16 diapositives
Neo4j : Graphes de Connaissance, IA et LLMs par
Neo4j : Graphes de Connaissance, IA et LLMsNeo4j : Graphes de Connaissance, IA et LLMs
Neo4j : Graphes de Connaissance, IA et LLMsNeo4j
46 vues20 diapositives
WebAssembly par
WebAssemblyWebAssembly
WebAssemblyJens Siebert
32 vues18 diapositives
DevsRank par
DevsRankDevsRank
DevsRankdevsrank786
10 vues1 diapositive
DSD-INT 2023 - Delft3D User Days - Welcome - Day 3 - Afternoon par
DSD-INT 2023 - Delft3D User Days - Welcome - Day 3 - AfternoonDSD-INT 2023 - Delft3D User Days - Welcome - Day 3 - Afternoon
DSD-INT 2023 - Delft3D User Days - Welcome - Day 3 - AfternoonDeltares
11 vues43 diapositives
ict act 1.pptx par
ict act 1.pptxict act 1.pptx
ict act 1.pptxsanjaniarun08
12 vues17 diapositives

Dernier(20)

Neo4j : Graphes de Connaissance, IA et LLMs par Neo4j
Neo4j : Graphes de Connaissance, IA et LLMsNeo4j : Graphes de Connaissance, IA et LLMs
Neo4j : Graphes de Connaissance, IA et LLMs
Neo4j46 vues
DSD-INT 2023 - Delft3D User Days - Welcome - Day 3 - Afternoon par Deltares
DSD-INT 2023 - Delft3D User Days - Welcome - Day 3 - AfternoonDSD-INT 2023 - Delft3D User Days - Welcome - Day 3 - Afternoon
DSD-INT 2023 - Delft3D User Days - Welcome - Day 3 - Afternoon
Deltares11 vues
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI... par Marc Müller
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...
Dev-Cloud Conference 2023 - Continuous Deployment Showdown: Traditionelles CI...
Marc Müller31 vues
MariaDB stored procedures and why they should be improved par Federico Razzoli
MariaDB stored procedures and why they should be improvedMariaDB stored procedures and why they should be improved
MariaDB stored procedures and why they should be improved
Geospatial Synergy: Amplifying Efficiency with FME & Esri ft. Peak Guest Spea... par Safe Software
Geospatial Synergy: Amplifying Efficiency with FME & Esri ft. Peak Guest Spea...Geospatial Synergy: Amplifying Efficiency with FME & Esri ft. Peak Guest Spea...
Geospatial Synergy: Amplifying Efficiency with FME & Esri ft. Peak Guest Spea...
Safe Software391 vues
Upgrading Incident Management with Icinga - Icinga Camp Milan 2023 par Icinga
Upgrading Incident Management with Icinga - Icinga Camp Milan 2023Upgrading Incident Management with Icinga - Icinga Camp Milan 2023
Upgrading Incident Management with Icinga - Icinga Camp Milan 2023
Icinga36 vues
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J... par Deltares
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...
Deltares7 vues
Applying Platform Engineering Thinking to Observability.pdf par Natan Yellin
Applying Platform Engineering Thinking to Observability.pdfApplying Platform Engineering Thinking to Observability.pdf
Applying Platform Engineering Thinking to Observability.pdf
Natan Yellin12 vues
DSD-INT 2023 Modelling litter in the Yarra and Maribyrnong Rivers (Australia)... par Deltares
DSD-INT 2023 Modelling litter in the Yarra and Maribyrnong Rivers (Australia)...DSD-INT 2023 Modelling litter in the Yarra and Maribyrnong Rivers (Australia)...
DSD-INT 2023 Modelling litter in the Yarra and Maribyrnong Rivers (Australia)...
Deltares9 vues
A first look at MariaDB 11.x features and ideas on how to use them par Federico Razzoli
A first look at MariaDB 11.x features and ideas on how to use themA first look at MariaDB 11.x features and ideas on how to use them
A first look at MariaDB 11.x features and ideas on how to use them
DSD-INT 2023 HydroMT model building and river-coast coupling in Python - Bove... par Deltares
DSD-INT 2023 HydroMT model building and river-coast coupling in Python - Bove...DSD-INT 2023 HydroMT model building and river-coast coupling in Python - Bove...
DSD-INT 2023 HydroMT model building and river-coast coupling in Python - Bove...
Deltares15 vues
DSD-INT 2023 SFINCS Modelling in the U.S. Pacific Northwest - Parker par Deltares
DSD-INT 2023 SFINCS Modelling in the U.S. Pacific Northwest - ParkerDSD-INT 2023 SFINCS Modelling in the U.S. Pacific Northwest - Parker
DSD-INT 2023 SFINCS Modelling in the U.S. Pacific Northwest - Parker
Deltares8 vues
What Can Employee Monitoring Software Do?​ par wAnywhere
What Can Employee Monitoring Software Do?​What Can Employee Monitoring Software Do?​
What Can Employee Monitoring Software Do?​
wAnywhere18 vues

Shooting the Rapids

  • 1. Shooting the Rapids: Getting the Best from Java 8 Streams Kirk Pepperdine @kcpeppe Maurice Naftalin @mauricenaftalin Devoxx Belgium, Nov. 2015
  • 2. • Specialises in performance tuning • speaks frequently about performance • author of performance tuning workshop • Co-founder • performance diagnostic tooling • Java Champion (since 2006) About Kirk
  • 3. • Specialises in performance tuning • speaks frequently about performance • author of performance tuning workshop • Co-founder • performance diagnostic tooling • Java Champion (since 2006) About Kirk
  • 8. Subjects Covered in this Talk • Background – lambdas and streams • Performance of our example • Effect of parallelizing • Splitting input data efficiently • When to go parallel • Parallel streams in the real world
  • 10. Predicate<Matcher> matches = new Predicate<Matcher>() {
 @Override
 public boolean test(Matcher matcher) {
 return matcher.find();
 }
 }; What is a Lambda? matcher matcher.find() matcher matcher.find()
  • 11. Predicate<Matcher> matches = new Predicate<Matcher>() {
 @Override
 public boolean test(Matcher matcher) {
 return matcher.find();
 }
 }; Predicate<Matcher> matches = What is a Lambda? matcher matcher.find() matcher matcher.find()
  • 12. Predicate<Matcher> matches = new Predicate<Matcher>() {
 @Override
 public boolean test(Matcher matcher) {
 return matcher.find();
 }
 }; Predicate<Matcher> matches = What is a Lambda? matcher Predicate<Matcher> matches = matcher.find() matcher matcher.find()
  • 13. Predicate<Matcher> matches = new Predicate<Matcher>() {
 @Override
 public boolean test(Matcher matcher) {
 return matcher.find();
 }
 }; Predicate<Matcher> matches = What is a Lambda? matcherPredicate<Matcher> matches = matcher.find() matcher matcher.find()
  • 14. Predicate<Matcher> matches = new Predicate<Matcher>() {
 @Override
 public boolean test(Matcher matcher) {
 return matcher.find();
 }
 }; Predicate<Matcher> matches = What is a Lambda? matcherPredicate<Matcher> matches = matcher.find() -> matcher matcher.find()
  • 15. Predicate<Matcher> matches = new Predicate<Matcher>() {
 @Override
 public boolean test(Matcher matcher) {
 return matcher.find();
 }
 }; Predicate<Matcher> matches = What is a Lambda? matcherPredicate<Matcher> matches = matcher.find()-> matcher matcher.find()
  • 16. Predicate<Matcher> matches = new Predicate<Matcher>() {
 @Override
 public boolean test(Matcher matcher) {
 return matcher.find();
 }
 }; Predicate<Matcher> matches = What is a Lambda? matcherPredicate<Matcher> matches = A lambda is a function from arguments to result matcher.find()-> matcher matcher.find()
  • 17. Example: Processing GC Logfile ⋮ 2.869: Application time: 1.0001540 seconds 5.342: Application time: 0.0801231 seconds 8.382: Application time: 1.1013574 seconds ⋮
  • 18. Example: Processing GC Logfile ⋮ 2.869: Application time: 1.0001540 seconds 5.342: Application time: 0.0801231 seconds 8.382: Application time: 1.1013574 seconds ⋮ DoubleSummaryStatistics {count=3, sum=2.181635, min=0.080123, average=0.727212, max=1.101357}
  • 19. Old School Code DoubleSummaryStatistic summary = new DoubleSummaryStatistic(); Pattern stoppedTimePattern = Pattern.compile("Application time: (d+.d+)"); 
 while ( ( logRecord = logFileReader.readLine()) != null) {
 Matcher matcher = stoppedTimePattern.matcher(logRecord);
 if ( matcher.find()) { double value = Double.parseDouble( matcher.group(1));
 summary.add( value);
 }
 }
  • 20. Old School Code DoubleSummaryStatistic summary = new DoubleSummaryStatistic(); Pattern stoppedTimePattern = Pattern.compile("Application time: (d+.d+)"); 
 while ( ( logRecord = logFileReader.readLine()) != null) {
 Matcher matcher = stoppedTimePattern.matcher(logRecord);
 if ( matcher.find()) { double value = Double.parseDouble( matcher.group(1));
 summary.add( value);
 }
 } Let’s look at the features in this code
  • 21. Data Source DoubleSummaryStatistic summary = new DoubleSummaryStatistic(); Pattern stoppedTimePattern = Pattern.compile("Application time: (d+.d+)"); 
 while ( ( logRecord = logFileReader.readLine()) != null) {
 Matcher matcher = stoppedTimePattern.matcher(logRecord);
 if ( matcher.find()) { double value = Double.parseDouble( matcher.group(1));
 summary.add( value);
 }
 }
  • 22. Map to Matcher DoubleSummaryStatistic summary = new DoubleSummaryStatistic(); Pattern stoppedTimePattern = Pattern.compile("Application time: (d+.d+)"); 
 while ( ( logRecord = logFileReader.readLine()) != null) {
 Matcher matcher = stoppedTimePattern.matcher(logRecord);
 if ( matcher.find()) { double value = Double.parseDouble( matcher.group(1));
 summary.add( value);
 }
 }
  • 23. Filter DoubleSummaryStatistic summary = new DoubleSummaryStatistic(); Pattern stoppedTimePattern = Pattern.compile("Application time: (d+.d+)"); 
 while ( ( logRecord = logFileReader.readLine()) != null) {
 Matcher matcher = stoppedTimePattern.matcher(logRecord);
 if ( matcher.find()) { double value = Double.parseDouble( matcher.group(1));
 summary.add( value);
 }
 }
  • 24. Map to Double DoubleSummaryStatistic summary = new DoubleSummaryStatistic(); Pattern stoppedTimePattern = Pattern.compile("Application time: (d+.d+)"); 
 while ( ( logRecord = logFileReader.readLine()) != null) {
 Matcher matcher = stoppedTimePattern.matcher(logRecord);
 if ( matcher.find()) { double value = Double.parseDouble( matcher.group(1));
 summary.add( value);
 }
 }
  • 25. Collect Results (Reduce) DoubleSummaryStatistic summary = new DoubleSummaryStatistic(); Pattern stoppedTimePattern = Pattern.compile("Application time: (d+.d+)"); 
 while ( ( logRecord = logFileReader.readLine()) != null) {
 Matcher matcher = stoppedTimePattern.matcher(logRecord);
 if ( matcher.find()) { double value = Double.parseDouble( matcher.group(1));
 summary.add( value);
 }
 }
  • 26. Java 8 Streams • A sequence of values,“in motion” • source and intermediate operations set the stream up lazily • a terminal operation “pulls” values eagerly down the stream collection.stream() .intermediateOp ⋮ .intermediateOp .terminalOp
  • 27. Stream Sources • New method Collection.stream() • Many other sources: • Arrays.stream(Object[]) • Streams.of(Object...) • Stream.iterate(Object,UnaryOperator) • Files.lines() • BufferedReader.lines() • Random.ints() • JarFile.stream() • …
  • 28. Imperative to Stream DoubleSummaryStatistics statistics =
 Files.lines(new File(“gc.log”).toPath())
 .map(stoppedTimePattern::matcher)
 .filter(Matcher::find)
 .map(matcher -> matcher.group(1)) .mapToDouble(Double::parseDouble) .summaryStatistics();
  • 29. Stream Source DoubleSummaryStatistics statistics =
 Files.lines(new File(“gc.log”).toPath())
 .map(stoppedTimePattern::matcher)
 .filter(Matcher::find)
 .map(matcher -> matcher.group(1)) .mapToDouble(Double::parseDouble) .summaryStatistics();
  • 30. Intermediate Operations DoubleSummaryStatistics statistics =
 Files.lines(new File(“gc.log”).toPath())
 .map(stoppedTimePattern::matcher)
 .filter(Matcher::find)
 .map(matcher -> matcher.group(1)) .mapToDouble(Double::parseDouble) .summaryStatistics();
  • 31. Method References DoubleSummaryStatistics statistics =
 Files.lines(new File(“gc.log”).toPath())
 .map(stoppedTimePattern::matcher)
 .filter(Matcher::find)
 .map(matcher -> matcher.group(1)) .mapToDouble(Double::parseDouble) .summaryStatistics();
  • 32. Terminal Operation DoubleSummaryStatistics statistics =
 Files.lines(new File(“gc.log”).toPath())
 .map(stoppedTimePattern::matcher)
 .filter(Matcher::find)
 .map(matcher -> matcher.group(1)) .mapToDouble(Double::parseDouble) .summaryStatistics();
  • 33. Visualising Sequential Streams x2x0 x1 x3x0 x1 x2 x3 Source Map Filter Reduction Intermediate Operations Terminal Operation “Values in Motion”
  • 34. Visualising Sequential Streams x2x0 x1 x3x1 x2 x3 ✔ Source Map Filter Reduction Intermediate Operations Terminal Operation “Values in Motion”
  • 35. Visualising Sequential Streams x2x0 x1 x3 x1x2 x3 ❌✔ Source Map Filter Reduction Intermediate Operations Terminal Operation “Values in Motion”
  • 36. Visualising Sequential Streams x2x0 x1 x3 x1x2x3 ❌✔ Source Map Filter Reduction Intermediate Operations Terminal Operation “Values in Motion”
  • 37. Old School: 13.3 secs Sequential: 13.8 secs - Should be the same workload - Stream code is cleaner, easier to read How Does It Perform? 24M line file, MacBook Pro, Haswell i7, 4 cores, hyperthreaded, Java 9.0
  • 38. Can We Do Better? • We might be able to if the workload is parallelizable • split stream into many segments • process each segment • combine results • Requirements exactly match Fork/Join workflow
  • 42. x2 Visualizing Parallel Streams x1 y3 x0 x1 x3 ✔ ❌
  • 43. Splitting Stream Sources • Stream source is a Spliterator • can both iterate over data and – where possible – split it
  • 53. Parallel Streams DoubleSummaryStatistics statistics =
 Files.lines(new File(“gc.log”).toPath()) .parallel()
 .map(stoppedTimePattern::matcher)
 .filter(Matcher::find)
 .map(matcher -> matcher.group(1)) .mapToDouble(Double::parseDouble) .summaryStatistics();
  • 54. About Fork/Join • Introduced in Java 7 • draws from a common pool of ForkJoinWorkerThread • default pool size == HW cores – 1 • assumes workload will be CPU bound • On its own, not an easy coding idiom • parallel streams provide an abstraction layer • Spliterator defines how to split stream • framework code submits sub-tasks to the common Fork/Join pool
  • 55. Old School: 13.3 secs Sequential: 13.8 secs Parallel: 9.5 secs - 1.45x faster - but not 8x faster (????) How Does That Perform? 24M lines, 2.8GHz 8-core i7, 16GB, OS X, Java 9.0
  • 56. In Fact!!!! • Different benchmarks yield a mixed bag of results • some were better • some were the same • some were worse!
  • 57. Open Questions • Under what conditions are things better • or worse • When should we parallelize • and when is serial better
  • 58. Open Questions • Under what conditions are things better • or worse • When should we parallelize • and when is serial better Answer depends upon where the bottleneck is
  • 59. Where is Our Bottleneck? • I/O operations • not a surprise, we’re reading from a file • Java 9 uses FileChannelLineSpliterator • 2x better than Java 8’s implementation 76.0% 0 + 5941 sun.nio.ch.FileDispatcherImpl.pread0
  • 60. Poorly Splitting Sources • Some sources split worse than others • LinkedList vs ArrayList • Streaming I/O is problematic • more threads == more pressure on contended resource • thrashing and other ill effects • Workload size doesn’t cover the overheads
  • 61. Streaming I/O Bottleneck x2x0 x1 x3x0 x1 x2 x3
  • 63. 5.342: … nds LineSpliterator 2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n spliterator coverage
  • 64. 5.342: … nds LineSpliterator 2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n spliterator coverage MappedByteBuffer
  • 65. 5.342: … nds LineSpliterator 2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n spliterator coverage MappedByteBuffer mid
  • 66. 5.342: … nds LineSpliterator 2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n spliterator coverage MappedByteBuffer mid
  • 67. 5.342: … nds LineSpliterator 2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n spliterator coveragenew spliterator coverage MappedByteBuffer mid
  • 68. 5.342: … nds LineSpliterator 2.869:Applicati … seconds n 8.382: … nds 9.337:App … ndsn n n spliterator coveragenew spliterator coverage MappedByteBuffer mid Included in JDK9 as FileChannelLinesSpliterator
  • 69. In-memory Comparison • Read GC log into an ArrayList prior to processing
  • 70. Old School: 9.4 secs Sequential: 9.9 secs Parallel: 2.7 secs - 4.25x faster - better but still not 8x faster In-memory Comparison 24M lines, 2.8GHz 8 core i7, 16GB, OS X, JDK 9.0
  • 71. Justifying the Overhead CPNQ performance model: C - number of submitters P - number of CPUs N - number of elements Q - cost of the operation cost of intermediate operations is N * Q overhead of setting up F/J framework is ~100µs
  • 72. Amortizing Setup Costs • N*Q needs to be large • Q can often only be estimated • N may only be known at run time • Rule of thumb, N > 10,000 • P is the number of processors • P == number for cores for CPU bound • P < number of cores otherwise
  • 73. Other Gotchas • Frequent hand-offs place pressure on thread schedulers • effect is magnified when a hypervisor is involved • estimated 80,000 cycles to handoff data between threads • you can do a lot of processing in 80,000 cycles • Too many threads places pressure on thread schedulers • responsible for other ill effects (TTSP) • too few threads may leave hardware under-utilized
  • 74. Simulated Server Environment ExecutorService threadPool = Executors.newFixedThreadPool(10); threadPool.execute(() -> { try { long timer = System.currentTimeMillis(); value = Files.lines( new File(“gc.log").toPath()).parallel() .map(applicationStoppedTimePattern::matcher) .filter(Matcher::find) .map( matcher -> matcher.group(2)) .mapToDouble(Double::parseDouble) .summaryStatistics().getSum(); } catch (Exception ex) {} });
  • 75. Work Flow and Results • First task to arrive will consume all ForkJoinWorkerThread • downstream tasks wait for a ForkJoinWorkerThread • downstream tasks start intermixing with initial task • Initial task collects dead time as it competes for threads • all other tasks collect dead time as they either • compete or wait for a ForkJoinWorkerThread
  • 76. Work Flow and Results • First task to arrive will consume all ForkJoinWorkerThread • downstream tasks wait for a ForkJoinWorkerThread • downstream tasks start intermixing with initial task • Initial task collects dead time as it competes for threads • all other tasks collect dead time as they either • compete or wait for a ForkJoinWorkerThread System is stressed beyond capacity
  • 77. Intermediate Operation Bottleneck 68.6% 1384 + 0 java.util.regex.Pattern$Curly.match 26.6% 521 + 15 java.util.stream.ReferencePipeline$3$1.accept
  • 78. Intermediate Operation Bottleneck • Bottleneck is in pattern matching • but, streaming infrastructure isn’t far behind! 68.6% 1384 + 0 java.util.regex.Pattern$Curly.match 26.6% 521 + 15 java.util.stream.ReferencePipeline$3$1.accept
  • 79. Tragedy of the Commons Garrett Hardin, ecologist (1968): Imagine the grazing of animals on a common ground. Each flock owner gains if they add to their own flock. But every animal added to the total degrades the commons a small amount.
  • 80. Tragedy of the Commons
  • 81. Tragedy of the Commons You have a finite amount of hardware – it might be in your best interest to grab it all – but if everyone behaves the same way…
  • 83. Simulated Server Environment • Submit 10 tasks to Fork-Join (via Executor thread-pool) • first result comes out in 32 seconds • compared to 9.5 seconds for individually submitted task • high system time reflects task is I/O bounded
  • 86. In-MemoryVariation • Preload log file • Submit 10 tasks to Fork-Join (via Executor thread-pool) • first result comes out in 23 seconds • compared to 4.5 seconds for individually submitted task • task is CPU bound
  • 87. Conclusions Sequential stream performance comparable to imperative code Going parallel is worthwhile IF - task is suitable - expensive enough to amortize setup costs - no inter-task communication needed - data source is suitable - environment is suitable Need to monitor JDK to understanding bottlenecks - Fork/Join pool is not well instrumented