Slide 1

Slide 1 text

Project Loom Broadening Concurrency

Slide 2

Slide 2 text

Mark Paluch Spring Data Project Lead @ VMware R2DBC Spec Lead Lettuce Redis Driver Maintainer Paramedic & SAR Dogs

Slide 3

Slide 3 text

Sept 2020, https://paluch.biz/blog/182-experimenting-with-project-loom-eap-and-spring-webmvc.html „We’ve been there, already“

Slide 4

Slide 4 text

Tomcat + Virtual Threads Tomcat + Kernel Threads

Slide 5

Slide 5 text

What is Project Loom • Initiative to introduce virtual threads to the Java Platform. Virtual threads are lightweight threads that dramatically reduce the effort of writing, maintaining, and observing high-throughput concurrent applications.

Slide 6

Slide 6 text

What is Project Loom • Initiative to introduce Introduction of virtual threads and concurrency API to the Java Platform. Virtual threads are lightweight threads that eliminate I/O wait. dramatically reduce the effort of writing, maintaining, and observing high-throughput concurrent applications.

Slide 7

Slide 7 text

What Project Loom actually is • Introduction of virtual threads and concurrency API to the Java Platform. Virtual threads are lightweight threads that eliminate I/O wait.

Slide 8

Slide 8 text

Dramatically reduce the effort of writing, maintaining, and observing concurrent applications • True if you run on a Virtual Thread • Future.get(), Thread.sleep(), Lock.lock() are good friends again • No need for future chaining, using complex reactive or asynchronous API • Not so, if you accidentally run on a Kernel Thread

Slide 9

Slide 9 text

Overview

Slide 10

Slide 10 text

Platform Thread • Renamed from Kernel Thread • new Thread(…)

Slide 11

Slide 11 text

Virtual Thread • Package-private subtype of java.lang.Thread • Provides customized behavior • Subject to be executed on carrier Thread

Slide 12

Slide 12 text

Carrier Threads • Separate Fork/Join Pool of Platform Threads • Default size: Runtime.availableProcessors() • Configurable through system properties (jdk.virtualThreadScheduler.parallelism, maxPoolSize, minRunnable)

Slide 13

Slide 13 text

Virtual Threads API • Extended Thread API Thread.ofVirtual().start(() -> {…}); Executors.newVirtualThreadPerTaskExecutor() Thread.currentThread().isVirtual() • Implemented almost entirely in Java

Slide 14

Slide 14 text

try(var e = Executors.newVirtualThreadPerTaskExecutor()){ for (int j = 0; j < 100; j++) { e.execute(() -> Thread.sleep(100)); } } // implicit wait

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Parking & Unparking • On each blocking operation • If blocked, capture stack and store it • Carrier thread free to perform other work (unpark next virtual thread)

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

Blocking in synchronized code • Leads to Carrier Thread Pinning • Carrier Thread bound to virtual thread until unblock • synchronized is a JVM behavior, cannot be controlled from Java code • I/O, Locks, Future.get() in synchronized leads to Thread Pinning

Slide 19

Slide 19 text

Thread Type Selection • I/O-heavy, shared-resources with Java Locks, Concurrency Utils • Virtual Threads • Computation-heavy, synchronized workloads • Platform Threads

Slide 20

Slide 20 text

Observability, Tooling, Trouble Shooting • Java Flight Recorder Events • Virtual Thread start/end, pinned, submission failed • Debugging: IntelliJ announced tooling support for later this year • Pinned thread monitoring • -Djdk.tracePinnedThreads=full|short

Slide 21

Slide 21 text

Demo

Slide 22

Slide 22 text

Virtual Thread Usage

Slide 23

Slide 23 text

Usage of Virtual Thread API • In every piece that could block or wait in Java • Thread.sleep • Locks, ConcurrentHashMap • I/O (Socket) • Rewrite of several components as pre-requisite for Loom to avoid thread pinning

Slide 24

Slide 24 text

Usage Pattern • Kernel Threads („Platform Threads“) • Expensive • Thread Pooling • Virtual Threads • Cheap • New Virtual Thread per Runnable

Slide 25

Slide 25 text

Benchmarks

Slide 26

Slide 26 text

JMH Benchmarks Benchmark Mode Cnt Score Error Units VirtualThreadsBenchmark.createVirtualThreads thrpt 5 14488555,637 ± 1127513,241 ops/s VirtualThreadsBenchmark.runAndAwait thrpt 5 455494,235 ± 22033,286 ops/s PlatformThreadsBenchmark.createPlatformThreads thrpt 5 19094,736 ± 677,739 ops/s PlatformThreadsBenchmark.runAndAwait thrpt 5 15807,802 ± 7337,906 ops/s

Slide 27

Slide 27 text

JMH Benchmarks Benchmark Mode Cnt Score Error Units VirtualThreadsBenchmark.createVirtualThreads thrpt 5 14488555,637 ± 1127513,241 ops/s VirtualThreadsBenchmark.runAndAwait thrpt 5 455494,235 ± 22033,286 ops/s PlatformThreadsBenchmark.createPlatformThreads thrpt 5 19094,736 ± 677,739 ops/s PlatformThreadsBenchmark.runAndAwait thrpt 5 15807,802 ± 7337,906 ops/s ThreadPoolExecutorBenchmark.runAndAwait thrpt 5 461335,862 ± 54427,010 ops/s

Slide 28

Slide 28 text

Conclusion

Slide 29

Slide 29 text

What does that mean? • If the CPU availability is the limit: You cannot increase concurrency • If the Runnable wait is the limit: You can increase concurrency

Slide 30

Slide 30 text

Loom Overhead • Hard to say. What’s the typical application?

Slide 31

Slide 31 text

Scalability Boundaries • I/O in synchronized Code • Connection Pool Sizes • Databases • HTTP/JMS/… Connection Pools • File handles • number of open files

Slide 32

Slide 32 text

Pitfalls • System.out.println(…) • Attempts to obtain a lock on the I/O • Measurement and benchmark correctness („What do you measure?“) • Visible and invisible Thread Pinning

Slide 33

Slide 33 text

Client/Server Workloads • Workload to be served by virtual thread (carrier threads must be available) • System must have sufficient resources to serve the request (e.g. connection pools). Also a constraint for platform thread usage. • Request to server via I/O • During wait, virtual thread is parked • Client must not pin kernel thread (see carrier thread availability)

Slide 34

Slide 34 text

Computation Workloads • Incoming request/event to be served by virtual thread (carrier threads must be available) • System performs a computation based on in-memory resources • Response is returned

Slide 35

Slide 35 text

Call to Action • Investigate: What is limiting your application scalability? • Investigate: What workloads do you run? • Experiment: Run your application on Virtual Threads and benchmark it! • Observe: What libraries lead to thread pinning?

Slide 36

Slide 36 text

Maybe. „Will Loom help with concurrency and scalability in my app?“

Slide 37

Slide 37 text

Thank You. github.com/mp911de @mp911de paluch.biz