shooting the rapids: getting the best from java 8 streams
TRANSCRIPT
![Page 1: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/1.jpg)
Shooting the Rapids: Getting the Best from Java 8
Streams
Kirk Pepperdine@kcpeppe
Maurice Naftalin@mauricenaftalin
![Page 2: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/2.jpg)
About Kirk
• Specialises in performance tuning• speaks frequently about performance• author of performance tuning workshop
• Co-founder jClarity• performance diagnositic tooling
• Java Champion (since 2006)
![Page 3: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/3.jpg)
About Kirk
• Specialises in performance tuning• speaks frequently about performance• author of performance tuning workshop
• Co-founder jClarity• performance diagnositic tooling
• Java Champion (since 2006)
![Page 4: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/4.jpg)
About Maurice
![Page 5: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/5.jpg)
About Maurice
![Page 6: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/6.jpg)
About Maurice
Co-author Author
![Page 7: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/7.jpg)
About Maurice
Co-author Author
JavaChampion
JavaOneRock Star
![Page 8: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/8.jpg)
Agenda
![Page 9: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/9.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
![Page 10: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/10.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources
![Page 11: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/11.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources• Tragedy Of The Commons
![Page 12: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/12.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources• Tragedy Of The Commons• Justifying the Overhead
![Page 13: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/13.jpg)
Example: Processing GC Logfile
⋮2.869: Application time: 1.0001540 seconds5.342: Application time: 0.0801231 seconds8.382: Application time: 1.1013574 seconds⋮
![Page 14: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/14.jpg)
Example: Processing GC Logfile
⋮2.869: Application time: 1.0001540 seconds5.342: Application time: 0.0801231 seconds8.382: Application time: 1.1013574 seconds⋮
![Page 15: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/15.jpg)
sum=2.181635
Example: Processing GC Logfile
⋮2.869: Application time: 1.0001540 seconds5.342: Application time: 0.0801231 seconds8.382: Application time: 1.1013574 seconds⋮
![Page 16: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/16.jpg)
Example: Processing GC Logfile
⋮2.869: Application time: 1.0001540 seconds5.342: Application time: 0.0801231 seconds8.382: Application time: 1.1013574 seconds⋮
DoubleSummaryStatistics {count=3, sum=2.181635, min=0.080123, average=0.727212, max=1.101357}
![Page 17: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/17.jpg)
Application time: (\\d+\\.\\d+)
Example: Processing GC Logfile
⋮2.869: Application time: 1.0001540 seconds5.342: Application time: 0.0801231 seconds8.382: Application time: 1.1013574 seconds⋮
Regex:
![Page 18: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/18.jpg)
Application time: (\\d+\\.\\d+)Pattern stoppedTimePattern = Pattern.compile(" ");
⋮ Matcher matcher = stoppedTimePattern.matcher(logRecord); String value = matcher.group(1);
Example: Processing GC Logfile
![Page 19: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/19.jpg)
Processing GC Logfile: Old School Code
Pattern stoppedTimePattern = Pattern.compile("Application time: (\\d+\\.\\d+)");
String logRecord; double value = 0; while ( ( logRecord = logFileReader.readLine()) != null) {
Matcher matcher = stoppedTimePattern.matcher(logRecord); if ( matcher.find()) {
value += (Double.parseDouble( matcher.group(1))); }
}
![Page 20: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/20.jpg)
Predicate<Matcher> matches = new Predicate<Matcher>() { @Override public boolean test(Matcher matcher) { return matcher.find(); }};
What is a Lambda?
matchermatcher.find()
matchermatcher.find()
![Page 21: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/21.jpg)
Predicate<Matcher> matches = new Predicate<Matcher>() { @Override public boolean test(Matcher matcher) { return matcher.find(); }};
Predicate<Matcher> matches =
What is a Lambda?
matchermatcher.find()
matchermatcher.find()
![Page 22: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/22.jpg)
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()
![Page 23: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/23.jpg)
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()
![Page 24: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/24.jpg)
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()
->
matchermatcher.find()
![Page 25: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/25.jpg)
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()->
matchermatcher.find()
![Page 26: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/26.jpg)
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()->
matchermatcher.find()
![Page 27: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/27.jpg)
Processing Logfile: Stream Code
DoubleSummaryStatistics summaryStatistics =
logFileReader.lines()
.map(input -> stoppedTimePattern.matcher(input))
.filter(matcher -> matcher.find())
.map(matcher -> matcher.group(1))
.mapToDouble(s -> Double.parseDouble(s))
.summaryStatistics();
![Page 28: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/28.jpg)
Processing Logfile: Stream Code
DoubleSummaryStatistics summaryStatistics =
logFileReader.lines()
.map(input -> stoppedTimePattern.matcher(input))
.filter(matcher -> matcher.find())
.map(matcher -> matcher.group(1))
.mapToDouble(s -> Double.parseDouble(s))
.summaryStatistics();
data source
![Page 29: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/29.jpg)
Processing Logfile: Stream Code
DoubleSummaryStatistics summaryStatistics =
logFileReader.lines()
.map(input -> stoppedTimePattern.matcher(input))
.filter(matcher -> matcher.find())
.map(matcher -> matcher.group(1))
.mapToDouble(s -> Double.parseDouble(s))
.summaryStatistics();
start streaming
![Page 30: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/30.jpg)
Processing Logfile: Stream Code
DoubleSummaryStatistics summaryStatistics =
logFileReader.lines()
.map(input -> stoppedTimePattern.matcher(input))
.filter(matcher -> matcher.find())
.map(matcher -> matcher.group(1))
.mapToDouble(s -> Double.parseDouble(s))
.summaryStatistics();
map to Matcher
![Page 31: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/31.jpg)
Processing Logfile: Stream Code
DoubleSummaryStatistics summaryStatistics =
logFileReader.lines()
.map(input -> stoppedTimePattern.matcher(input))
.filter(matcher -> matcher.find())
.map(matcher -> matcher.group(1))
.mapToDouble(s -> Double.parseDouble(s))
.summaryStatistics();
filter outuninteresting bits
![Page 32: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/32.jpg)
Processing Logfile: Stream Code
DoubleSummaryStatistics summaryStatistics =
logFileReader.lines()
.map(input -> stoppedTimePattern.matcher(input))
.filter(matcher -> matcher.find())
.map(matcher -> matcher.group(1))
.mapToDouble(s -> Double.parseDouble(s))
.summaryStatistics();
extract group
![Page 33: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/33.jpg)
Processing Logfile: Stream Code
DoubleSummaryStatistics summaryStatistics =
logFileReader.lines()
.map(input -> stoppedTimePattern.matcher(input))
.filter(matcher -> matcher.find())
.map(matcher -> matcher.group(1))
.mapToDouble(s -> Double.parseDouble(s))
.summaryStatistics();
map String to Double
![Page 34: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/34.jpg)
Processing Logfile: Stream Code
DoubleSummaryStatistics summaryStatistics =
logFileReader.lines()
.map(input -> stoppedTimePattern.matcher(input))
.filter(matcher -> matcher.find())
.map(matcher -> matcher.group(1))
.mapToDouble(s -> Double.parseDouble(s))
.summaryStatistics(); aggregate results
![Page 35: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/35.jpg)
What is a Stream?
• A sequence of values• source and intermediate operations set the stream up lazily:
Stream<String> groupStream = logFileReader.lines()
.map(stoppedTimePattern::matcher)
.filter(Matcher::find)
.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble);
Source
![Page 36: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/36.jpg)
What is a Stream?
• A sequence of values• source and intermediate operations set the stream up lazily:
Stream<String> groupStream = logFileReader.lines()
.map(stoppedTimePattern::matcher)
.filter(Matcher::find)
.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble);
IntermediateOperations
![Page 37: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/37.jpg)
What is a Stream?
• The terminal operation pulls the values down the stream:
SummaryStatistics statistics = logFileReader.lines()
.map(stoppedTimePattern::matcher)
.filter(Matcher::find)
.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble)
.summaryStatistics();TerminalOperation
![Page 38: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/38.jpg)
Visualising Sequential Streams
x2x0 x1 x3x0 x1 x2 x3
Source Map Filter Reduction
Intermediate Operations
Terminal Operation
“Values in Motion”
![Page 39: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/39.jpg)
Visualising Sequential Streams
x2x0 x1 x3x1 x2 x3 ✔
Source Map Filter Reduction
Intermediate Operations
Terminal Operation
“Values in Motion”
![Page 40: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/40.jpg)
Visualising Sequential Streams
x2x0 x1 x3 x1x2 x3 ❌✔
Source Map Filter Reduction
Intermediate Operations
Terminal Operation
“Values in Motion”
![Page 41: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/41.jpg)
Visualising Sequential Streams
x2x0 x1 x3 x1x2x3 ❌✔
Source Map Filter Reduction
Intermediate Operations
Terminal Operation
“Values in Motion”
![Page 42: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/42.jpg)
Old School: 80200msSequential: 25800ms
(>9m lines, MacBook Pro, Haswell i7, 4 cores, hyperthreaded)
Stream code is faster because operations are fused
How Does That Perform?
![Page 43: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/43.jpg)
Can We Do Better?
Parallel streams make use of multiple cores• split the data into segments• each segment processed by its own thread
- on its own core – if possible
![Page 44: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/44.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 45: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/45.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 46: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/46.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 47: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/47.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 48: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/48.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 49: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/49.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 50: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/50.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 51: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/51.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 52: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/52.jpg)
Splitting the Data
Implemented by a Spliterator:
![Page 53: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/53.jpg)
x2
Visualizing Parallel Streams
x0x1
x3
x0
x1x2x3
![Page 54: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/54.jpg)
x2
Visualizing Parallel Streams
x0
x1
x3
x0
x1
x2x3
![Page 55: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/55.jpg)
x2
Visualizing Parallel Streams
x1
x3
x0
x1
x3
✔
❌
![Page 56: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/56.jpg)
x2
Visualizing Parallel Streams
x1 y3
x0
x1
x3
✔
❌
![Page 57: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/57.jpg)
Stream CodeDoubleSummaryStatistics summaryStatistics =
logFileReader.lines().parallel()
.map(stoppedTimePattern::matcher)
.filter(Matcher::find)
.map(matcher -> matcher.group(1))
.mapToDouble(Double::parseDouble)
.summaryStatistics();
![Page 58: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/58.jpg)
Results of Going Parallel:
• No benefit from using parallel streams while streaming data
![Page 59: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/59.jpg)
Agenda
![Page 60: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/60.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
![Page 61: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/61.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources
![Page 62: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/62.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources• Tragedy Of The Commons
![Page 63: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/63.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources• Tragedy Of The Commons• Justifying the Overhead
![Page 64: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/64.jpg)
Poorly Splitting Sources
![Page 65: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/65.jpg)
• Some sources split much worse than others– LinkedList vs. ArrayList
Poorly Splitting Sources
![Page 66: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/66.jpg)
• Some sources split much worse than others– LinkedList vs. ArrayList
• Streaming I/O is bad. – kills the advantage of going parallel
Poorly Splitting Sources
![Page 67: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/67.jpg)
• Some sources split much worse than others– LinkedList vs. ArrayList
• Streaming I/O is bad. – kills the advantage of going parallel
Poorly Splitting Sources
![Page 68: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/68.jpg)
Streaming I/O Bottleneck
x2x0 x1 x3x0 x1 x2 x3
![Page 69: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/69.jpg)
Streaming I/O Bottleneck
✔
❌x2x1x0 x1 x3
![Page 70: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/70.jpg)
5.342: … nds
LineSpliterator
2.869: Applicati … seconds \n 8.382: … nds 9.337:App … nds\n \n \n
spliterator coverage
![Page 71: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/71.jpg)
5.342: … nds
LineSpliterator
2.869: Applicati … seconds \n 8.382: … nds 9.337:App … nds\n \n \n
spliterator coverage
MappedByteBuffer
![Page 72: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/72.jpg)
5.342: … nds
LineSpliterator
2.869: Applicati … seconds \n 8.382: … nds 9.337:App … nds\n \n \n
spliterator coverage
MappedByteBuffer mid
![Page 73: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/73.jpg)
5.342: … nds
LineSpliterator
2.869: Applicati … seconds \n 8.382: … nds 9.337:App … nds\n \n \n
spliterator coverage
MappedByteBuffer mid
![Page 74: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/74.jpg)
5.342: … nds
LineSpliterator
2.869: Applicati … seconds \n 8.382: … nds 9.337:App … nds\n \n \n
spliterator coveragenew spliterator coverage
MappedByteBuffer mid
![Page 75: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/75.jpg)
5.342: … nds
LineSpliterator
2.869: Applicati … seconds \n 8.382: … nds 9.337:App … nds\n \n \n
spliterator coveragenew spliterator coverage
MappedByteBuffer mid
Included in JDK9 as FileChannelLinesSpliterator
![Page 76: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/76.jpg)
StreamingIO: 56sSpliterator: 88s
(>9m lines, MacBook Pro, Haswell i7, 4 cores, hyperthreaded)
Stream code is faster because operations are fused
LineSpliterator – results
![Page 77: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/77.jpg)
When to Use Parallel Streams?
![Page 78: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/78.jpg)
When to Use Parallel Streams?• Task must be recursively decomposable
– subtasks for each data segment must be independent
![Page 79: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/79.jpg)
When to Use Parallel Streams?• Task must be recursively decomposable
– subtasks for each data segment must be independent
• Source must be well-splitting
![Page 80: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/80.jpg)
When to Use Parallel Streams?• Task must be recursively decomposable
– subtasks for each data segment must be independent
• Source must be well-splitting• Enough hardware to support all VM needs
– there may be other business afoot
![Page 81: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/81.jpg)
When to Use Parallel Streams?• Task must be recursively decomposable
– subtasks for each data segment must be independent
• Source must be well-splitting• Enough hardware to support all VM needs
– there may be other business afoot
• Overhead of splitting must be justified– intermediate operations need to be expensive– and CPU-bound
![Page 82: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/82.jpg)
When to Use Parallel Streams?• Task must be recursively decomposable
– subtasks for each data segment must be independent
• Source must be well-splitting• Enough hardware to support all VM needs
– there may be other business afoot
• Overhead of splitting must be justified– intermediate operations need to be expensive– and CPU-bound
http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html
![Page 83: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/83.jpg)
Agenda
![Page 84: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/84.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
![Page 85: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/85.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources
![Page 86: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/86.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources• Tragedy Of The Commons
![Page 87: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/87.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources• Tragedy Of The Commons• Justifying the Overhead
![Page 88: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/88.jpg)
Tragedy of the Commons
![Page 89: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/89.jpg)
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…
![Page 90: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/90.jpg)
Agenda
![Page 91: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/91.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
![Page 92: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/92.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources
![Page 93: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/93.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources• Tragedy Of The Commons
![Page 94: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/94.jpg)
Agenda
• Introduction– lambdas, streams, and a logfile processing problem
• Optimizing stream sources• Tragedy Of The Commons• Justifying the Overhead
![Page 95: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/95.jpg)
Justifying the Overhead
CPNQ performance model:
C - number of submittersP - number of CPUsN - number of elementsQ - cost of the operation
![Page 96: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/96.jpg)
Justifying the Overhead
Need to amortize setup costs– N*Q needs to be large– Q can often only be estimated– N often should be >10,000 elements
If P is the number of processors, the formula assumes that intermediate tasks are CPU bound
![Page 97: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/97.jpg)
Don’t Have Too Many Threads!
• Too many threads cause frequent handoffs• It costs ~80,000 cycles to handoff data between threads• You can do a lot of processing in 80,000 cycles!
![Page 98: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/98.jpg)
Fork/Join
![Page 99: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/99.jpg)
Fork/Join• Parallel streams implemented by Fork/Join framework
• added in Java 7, but difficult to code• parallel streams are more usable
![Page 100: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/100.jpg)
Fork/Join• Parallel streams implemented by Fork/Join framework
• added in Java 7, but difficult to code• parallel streams are more usable
![Page 101: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/101.jpg)
Fork/Join• Parallel streams implemented by Fork/Join framework
• added in Java 7, but difficult to code• parallel streams are more usable
• Each segment of data is submitted as a ForkJoinTask • ForkJoinTask.invoke() spawns a new task• ForkJoinTask.join() retrieves the result
![Page 102: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/102.jpg)
Fork/Join• Parallel streams implemented by Fork/Join framework
• added in Java 7, but difficult to code• parallel streams are more usable
• Each segment of data is submitted as a ForkJoinTask • ForkJoinTask.invoke() spawns a new task• ForkJoinTask.join() retrieves the result
• How Fork/Join works and performs is important to your latency picture
![Page 103: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/103.jpg)
Common Fork/Join Pool
Fork/Join by default uses a common thread pool- default number of worker threads == number of logical cores - 1- (submitting thread is pressed into service)
- can configure the pool via system properties:
- or create our own pool…
java.util.concurrent.ForkJoinPool.common.parallelism java.util.concurrent.ForkJoinPool.common.threadFactory java.util.concurrent.ForkJoinPool.common.exceptionHandler
![Page 104: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/104.jpg)
Custom Fork/Join Pool
When used inside a ForkJoinPool, the ForkJoinTask.fork() method uses the current pool:
ForkJoinPool ourOwnPool = new ForkJoinPool(10);
ourOwnPool.invoke(() -> stream.parallel(). ⋮
![Page 105: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/105.jpg)
Don’t Have Too Few Threads!
• Fork/Join pool uses a work queue• If tasks are CPU bound, no use increasing the size of the
thread pool• But if not CPU bound, they are sitting in queue
accumulating dead time• Can make thread pool bigger to reduce dead time• Little’s Law tells us
Number of tasks in the system =Arrival rate * Average service time
![Page 106: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/106.jpg)
Little’s Law Example
System receives 400 Txs and it takes 100ms to clear a request- Number of tasks in system = 0.100 * 400 = 40
On an 8 core machine with a CPU bound task- implies 32 tasks are sitting in queue accumulating dead time
- Average response time 600 ms of which 500ms is dead time- ~83% of service time is in waiting
![Page 107: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/107.jpg)
public final V invoke() { ForkJoinPool.common.getMonitor().submitTask(this); int s; if ((s = doInvoke() & DONE_MASK) != NORMAL) reportException(s); ForkJoinPool.common.getMonitor().retireTask(this); return getRawResult();}
ForkJoinPool Observability
ForkJoinPool comes with no visibility- need to instrument ForkJoinTask.invoke()
– gather data from ForkJoinPool to feed into Little’s Law
![Page 108: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/108.jpg)
Conclusions
Sequential stream performance comparable to imperative codeGoing parallel is worthwhile IF- task is suitable
- data source is suitable
- environment is suitable
Need to monitor JDK to understanding bottlenecks- Fork/Join pool is not well instrumented
![Page 109: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/109.jpg)
Questions?
![Page 110: Shooting the Rapids: Getting the Best from Java 8 Streams](https://reader034.vdocument.in/reader034/viewer/2022042707/58ef60f21a28ab09308b45a7/html5/thumbnails/110.jpg)
Questions?