SlideShare a Scribd company logo
The State of Fibers for the JVM
Why all your JVM coroutines are cool, but broken,
and Project Loom is gonna fix that!
(Kilim threads, Quasar fibers, Kotlin coroutines, etc.)
and ...
Volkan Yazıcı
https://vlkan.com
@yazicivo
Lightweight Threads
Virtual
2018-03-08
2018-08-25
2019-12-10
Agenda
1) Motivation
2) History
3) Continuations
4) Processes, threads, and fibers
5) Project Loom
6) Structured concurrency
7) Scoped variables
Motivation: I/O
Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
Without I/O, you don’t exist!
● println()
● file access
● network socket access
● database access
● etc.
In 1958, ...
Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
The legend of Melvin Conway
Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
Subroutine Coroutine⊂ Coroutine
“Coroutines” – Melvin Conway, 1958
“Generalization of subroutine” – Donald Knuth, 1968
subroutines coroutines
call
allocate frame,
pass params
allocate frame,
pass params
return
free frame,
return result
free frame,
return result
suspend No Yes
resume No Yes
Subroutine A Subroutine B
…
call B
…
B start
end
call B
B start
end
Subroutine A Coroutine C
…
call C
…
C start
end
suspend
suspend
resume C
resume C
Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
Where did all the coroutines go?
Algol-60
… introduced code blocks and the begin and end pairs for
delimiting them. ALGOL 60 was the first language implementing
nested function definitions with lexical scope.
– Wikipedia “ALGOL 60”
Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
One “continuation” to rule them all...
“Continuation Sandwich”
● The earliest description by Adriaan van Wijngaarden in 1964.
● “… a data structure that represents the computational process at a given point in the
process's execution; ...” – Wikipedia “Continuation”
● “Say you're in the kitchen in front of the refrigerator, thinking about a sandwich.
You take a continuation right there and stick it in your pocket. Then you get some
turkey and bread out of the refrigerator and make yourself a sandwich, which is now
sitting on the counter. You invoke the continuation in your pocket, and you find
yourself standing in front of the refrigerator again, thinking about a sandwich. But
fortunately, there's a sandwich on the counter, and all the materials used to make it
are gone. So you eat it.” – Luke Palmer, 2004
A glimpse of “continuation”
(define the-continuation #f)
(define (test)
(let ((i 0))
; call/cc calls its first function argument, passing
; a continuation variable representing this point in
; the program as the argument to that function.
(call/cc (lambda (k) (set! the-continuation k)))
; The next time the-continuation is called, we start here.
(set! i (+ i 1))
i))
> (test)
1
> (the-continuation)
2
> (the-continuation)
3
> ; stores the current continuation (which will print 4 next) away
> (define another-continuation the-continuation)
> (test) ; resets the-continuation
1
> (the-continuation)
2
> (another-continuation) ; uses the previously stored continuation
4
See Oleg Kiselyo’s An argument against call/cc and Undelimited continuations are not functions articles.
A glimpse of “delimited continuation”
; The reset delimits the continuation that shift captures (named by k in this example).
; The use of shift will bind k to the continuation (+ 1 []),
; where [] represents the part of the computation that is to be filled with a value.
(* 2 (reset (+ 1 (shift k (k 5)))))
(reset (* 2 (shift k (k (k 4)))))
; invokes (k 4) first (which returns 8),
; and then (k 8) (which returns 16).
; At this point, the shift expression has terminated,
; and the rest of the reset expression is discarded.
; Therefore, the final result is 16.
Unlike regular continuations, delimited continuations return a value, and thus may be
reused and composed.
What is so important about continuations?
Using continuations you can implement
● longjmp (C)
● exceptions (C++, Java, etc.)
● generators (Icon, Python, etc.)
● backtracking (Prolog, etc.)
● and… guess what else?
continuation + scheduler = ?
public SearchResponse search(SearchRequest request) {
// Check caches.
SearchResponse cachedResponse = cache.find(reqest);
if (cachedResponse != null) {
return cachedResponse;
}
// Check redirects.
SearchResponse redirectedResponse = redirectService.find(request);
if (redirectedResponse != null) {
return redirectedResponse;
}
// Perform plain search enriched with suggestions.
SearchRequest enrichedRequest = suggestionService.enrich(request);
return plainSearch(enrichedRequest);
}
public void search(
SearchRequest request,
Consumer<SearchResponse> callback) {
// Check caches.
return cache.find(request, cachedResponse -> {
if (cachedResponse != null) {
callback.accept(cachedResponse);
} else {
// Check redirects.
redirectService.find(request, redirectedResponse -> {
if (redirectedResponse != null) {
return callback.accept(redirectedResponse);
} else {
// Perform plain search enriched with suggestions.
suggestionService.enrich(request, enrichedRequest -> {
plainSearch(enrichedRequest, searchResponse -> {
callback.accept(searchResponse);
});
});
}
});
}
});
}
Callbacks (non-blocking)
public Mono<SearchResponse> search(SearchRequest request) {
return Flux
.concat(cache.find(request),
redirectService.find(request),
suggestionService
.find(request)
.flatMap(this::plainSearch))
.take(1)
.singleOrEmpty();
}
Reactor (non-blocking)
Blocking calls
How do we compose I/O?
(without changing neither the language, nor the VM byte code)
public SearchResponse search(SearchRequest request) {
// Check caches.
SearchResponse cachedResponse = cache.find(reqest);
if (cachedResponse != null) {
return cachedResponse;
}
// Check redirects.
SearchResponse redirectedResponse = redirectService.find(request);
if (redirectedResponse != null) {
return redirectedResponse;
}
// Perform plain search enriched with suggestions.
SearchRequest enrichedRequest = suggestionService.enrich(request);
return plainSearch(enrichedRequest);
}
executed
instructions
time
Blocking calls
thread
activity
running
blocked
Blocking what?
public Mono<SearchResponse> search(SearchRequest request) {
return Flux
.concat(cache.find(request),
redirectService.find(request),
suggestionService
.find(request)
.flatMap(this::plainSearch))
.take(1)
.singleOrEmpty();
}
Reactor (non-blocking)
callchain
How does asynchronous I/O get composed?
Why all this reactive hassle?
Thread-1 Thread-2 Thread-3 Thread-100...
Request-1 Request-2 Request-3 Request-100...
Thread-1
Request-1 Request-2 Request-3 Request-100...
Callchain-1
Callchain-2
Callchain-3
Callchain-100
...
Reactor(non-blocking)
Blockingcalls
If spawning and context
switching costs of threads
would be equal to the ones
in callchains, would you
still favor the latter?
Process-vs-thread
Data1
Code1
(single-threaded)
OS Process
Registers1
Stack1
CPU1
CPU2
CPUK
...
OS Scheduler
Files1
Data2
Code2
Registers2
Stack2
Files2
Registers1
Stack1
Data
Code
CPU1
CPU2
CPUK
...
OS Scheduler
Registers2
Stack2
Registers3
Stack3
...
RegistersN
StackN
(multi-threaded)
OS Process
Files
Both processes and threads denote a
continuation: a sequence of instructions
that can be suspended and resumed.
process = continuation + scheduler
thread = continuation + schedulerCheaper!
What is a fiber?
OS Process
CPU1
CPU2
CPUK
...
OS Scheduler
Registers1
Stack1
Data
Code
Registers2
Stack2
Registers3
Stack3
RegistersN
StackN
Files
...
Both processes and threads denote a
continuation: a sequence of instructions
that can be suspended and resumed.
process = continuation + scheduler
thread = continuation + schedulerCheaper!
fiber = continuation + schedulerCheaper!
kernel
user
...
User-level scheduler
M321
kernel both share memory
M >> N
● Yes, it can, but it (natively) doesn’t.
● Lisp(call/cc)
, BEAM(Erlang VM)
, Haskell, Go, JavaScript(async, await)
(natively) do.
● Quasar, Kilim, etc. provides continuations and fibers for JVM.
● What if someone calls Thread.sleep()?
● What if a coroutine calls a non-coroutine method?
What if that non-coroutine method is blocking?
● What about Kotlin coroutines?
Does JVM support fibers?
in essence, “continuations”
What about actors(Erlang, Akka)
/ channels(Go, Kotlin)
?
m1
m2
m3...mN
fiber { BlockingQueue<V>(bufferSize) } = Channel<V>(bufferSize)
A glimpse of Quasar & Kilim
Quasar
Kilim
So what is the problem?
Asynchronous task composition
Reactive Streams FibersCallbacks
● Language-agnostic
● Difficult to write
(callbackhell.com)
● Difficult to debug & profile
● Misses batteries
● Viral
● Language-agnostic
● Includes batteries
● Widely supported
● Need to learn a new language
● Difficult to write & get right
● Difficult to debug & profile
● Difficult to optimize (by compiler)
● Viral
● Just works
● Language-specific
● Requires explicit marking
● Misses batteries
Reflective calls are always considered suspendable. This is because the target
method is computed at runtime, so there’s no general way of telling if it’s going to call a suspendable method
or not before execution.
Java 8 lambdas too are always considered suspendable. This is because they can’t
declare checked exceptions, they are ultimately linked (via invokedynamic) to synthethic static methods that
can’t be annotated and it is difficult to tell at instrumentation time if lambdas implement a suspendable
interface.
Quasar will reject with an error any attempt to mark special methods
(that is, constructors and class initializers) as suspendable. This is because
suspending in an initializer could expose objects or classes before they’re fully initialized and this is an error-
prone, difficult-to-troubleshoot situation that can always (and must) be avoided.
Enter Loom…
http://cr.openjdk.java.net/~rpressler/loom/Loom-Proposal.html
Project Loom proposal
by Ron Pressler
The proposal
● Quasar: lightweight threads (fibers) for the JVM
● Comsat: fiber-aware impl’s of servlets, JAX-RS/Spring REST services, HTTP clients and JDBC
● SpaceBase: in-memory spatial and geo-spatial database
● Galaxy: distributed in-memory data grid that horizontally scales
In 2012, founded Parallel Universe with the following F/OSS product line:
Who is Ron Pressler anyway?
http://www.paralleluniverse.co/
http://openjdk.java.net/census#loom
Lead at Project Loom
(since 2017)
● One of Java's most important contributions when it was first released, over twenty
years ago, was the easy access to threads and synchronization primitives.
● … today's requirements is that the software unit of concurrency offered by the
runtime — the thread — cannot match the scale of the domain's unit of
concurrency, …
● … asynchronous APIs ... were created
● not because they are easier to write and to understand
● for they are actually harder
● not because they are easier to debug or profile
● they are harder (they don't even produce meaningful stacktraces)
● not because they compose better than synchronous APIs
● they compose less elegantly
● not because they fit better with the rest of
the language or integrate well with existing code
● they are a much worse fit
● but just because the implementation of the software unit of concurrency in
Java — the thread — is insufficient from a footprint and performance
perspective.
Proposal highlights
The key project deliverable
See Ron Pressler's detailed post in the loom-dev mailing list.
Lightweight threads
Asymmetric
one-shot (non-reentrant)
stackful
multi-prompt
delimited
continuations.
Are we there yet?
● OIO rewrite
● Continuations
● Strand → Fiber → Lightweight thread → Virtual thread
● Structured concurrency
● Scoped variables
A word on “legacy”...
Structured concurrency
... ... ... ... ...
The curse of control flow constructs
sequence goto if loop call
Quoting from Martin Sustrik's "Structured Concurrency" talk in FOSDEM'19.
Is GOTO harmful?
(So are threads!)
Quoting from Nathaniel J. Smith's "Notes on structured concurrency" blog post.
What does structured concurrency look like?
Quoting from Nathaniel J. Smith's "Notes on structured concurrency" blog post.
with open("my-file") as file_handle:
...
... ... ...
A glimpse of Trio
import trio
async def child1():
print(" child1: started! sleeping now...")
await trio.sleep(1)
print(" child1: exiting!")
async def child2():
print(" child2: started! sleeping now...")
await trio.sleep(1)
print(" child2: exiting!")
async def parent():
print("parent: started!")
async with trio.open_nursery() as nursery:
print("parent: spawning child1...")
nursery.start_soon(child1)
print("parent: spawning child2...")
nursery.start_soon(child2)
print("parent: waiting for children to finish...")
# -- we exit the nursery block here --
print("parent: all done!")
trio.run(parent)
parent: started!
parent: spawning child1...
parent: spawning child2...
parent: waiting for children to finish...
child2: started! sleeping now...
child1: started! sleeping now...
[... 1 second passes ...]
child1: exiting!
child2: exiting!
parent: all done!
A word on cancellation...
Scoped variables
public class ScopeDemo {
private static final Logger LOGGER = LoggerFactory.getLogger(ScopeDemo.class);
private final List<Runnable> tasks = new ArrayList<>();
private final ThreadLocal<StringBuilder> stringBuilderRef =
ThreadLocal.withInitial(StringBuilder::new);
public void addTask(Runnable task) {
tasks.add(task);
}
public static void main(String[] args) throws IOException {
try (InputStream inputStream = new FileInputStream("/etc/passwd")) {
int firstByte = inputStream.read();
{
int randomByte = (int) Math.abs(Math.random() * 0xFF);
firstByte += randomByte;
}
}
}
}
Don’t we already have scoped variables?
What is the scope of a ThreadLocal?
> x=1
> function g() {
echo $x;
x=2;
}
> function f() {
local x=3;
g;
}
> f
> echo $x
Static-vs-Dynamic scoping
What do these two statements output?
> color=null
> function terrier(nursery) {
echo “Terrier sees $color.”;
}
> function dog(nursery) {
echo “Dog sees $color.”
color=”black-and-white”;
nursery.schedule(terrier)
}
> function cat(nursery) {
echo “Cat sees $color.”
}
> with nursery {
color=”colorful”
nursery.schedule(dog)
nursery.schedule(cat)
}
Dynamic scoping and structured concurrency
What does this statement output?
Conclusions
● Loom will radically change I/O composition in JVM.
● Structured concurrency and scoped variables will supplement that ease.
Thank you!
(Questions?)
Volkan Yazıcı
https://vlkan.com
@yazicivo
Ad

More Related Content

What's hot (20)

Alternatives of JPA/Hibernate
Alternatives of JPA/HibernateAlternatives of JPA/Hibernate
Alternatives of JPA/Hibernate
Sunghyouk Bae
 
Performance and predictability
Performance and predictabilityPerformance and predictability
Performance and predictability
RichardWarburton
 
Swift and Kotlin Presentation
Swift and Kotlin PresentationSwift and Kotlin Presentation
Swift and Kotlin Presentation
Andrzej Sitek
 
Kotlin: Why Do You Care?
Kotlin: Why Do You Care?Kotlin: Why Do You Care?
Kotlin: Why Do You Care?
intelliyole
 
Kotlin in action
Kotlin in actionKotlin in action
Kotlin in action
Ciro Rizzo
 
Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011
Andrey Breslav
 
无锁编程
无锁编程无锁编程
无锁编程
vorfeed chen
 
The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018
Charles Nutter
 
Facebook C++网络库Wangle调研
Facebook C++网络库Wangle调研Facebook C++网络库Wangle调研
Facebook C++网络库Wangle调研
vorfeed chen
 
Fun with Functional Programming in Clojure
Fun with Functional Programming in ClojureFun with Functional Programming in Clojure
Fun with Functional Programming in Clojure
Codemotion
 
Jvm profiling under the hood
Jvm profiling under the hoodJvm profiling under the hood
Jvm profiling under the hood
RichardWarburton
 
Effective testing for spark programs Strata NY 2015
Effective testing for spark programs   Strata NY 2015Effective testing for spark programs   Strata NY 2015
Effective testing for spark programs Strata NY 2015
Holden Karau
 
[262] netflix 빅데이터 플랫폼
[262] netflix 빅데이터 플랫폼[262] netflix 빅데이터 플랫폼
[262] netflix 빅데이터 플랫폼
NAVER D2
 
Let's talk about Garbage Collection
Let's talk about Garbage CollectionLet's talk about Garbage Collection
Let's talk about Garbage Collection
Haim Yadid
 
Spring data requery
Spring data requerySpring data requery
Spring data requery
Sunghyouk Bae
 
Andrzej Ludwikowski - Event Sourcing - co może pójść nie tak?
Andrzej Ludwikowski -  Event Sourcing - co może pójść nie tak?Andrzej Ludwikowski -  Event Sourcing - co może pójść nie tak?
Andrzej Ludwikowski - Event Sourcing - co może pójść nie tak?
SegFaultConf
 
Implementing a JavaScript Engine
Implementing a JavaScript EngineImplementing a JavaScript Engine
Implementing a JavaScript Engine
Kris Mok
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
Bartosz Kosarzycki
 
Principios básicos de Garbage Collector en Java
Principios básicos de Garbage Collector en JavaPrincipios básicos de Garbage Collector en Java
Principios básicos de Garbage Collector en Java
Víctor Leonel Orozco López
 
Quick introduction to Java Garbage Collector (JVM GC)
Quick introduction to Java Garbage Collector (JVM GC)Quick introduction to Java Garbage Collector (JVM GC)
Quick introduction to Java Garbage Collector (JVM GC)
Marcos García
 
Alternatives of JPA/Hibernate
Alternatives of JPA/HibernateAlternatives of JPA/Hibernate
Alternatives of JPA/Hibernate
Sunghyouk Bae
 
Performance and predictability
Performance and predictabilityPerformance and predictability
Performance and predictability
RichardWarburton
 
Swift and Kotlin Presentation
Swift and Kotlin PresentationSwift and Kotlin Presentation
Swift and Kotlin Presentation
Andrzej Sitek
 
Kotlin: Why Do You Care?
Kotlin: Why Do You Care?Kotlin: Why Do You Care?
Kotlin: Why Do You Care?
intelliyole
 
Kotlin in action
Kotlin in actionKotlin in action
Kotlin in action
Ciro Rizzo
 
Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011
Andrey Breslav
 
The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018
Charles Nutter
 
Facebook C++网络库Wangle调研
Facebook C++网络库Wangle调研Facebook C++网络库Wangle调研
Facebook C++网络库Wangle调研
vorfeed chen
 
Fun with Functional Programming in Clojure
Fun with Functional Programming in ClojureFun with Functional Programming in Clojure
Fun with Functional Programming in Clojure
Codemotion
 
Jvm profiling under the hood
Jvm profiling under the hoodJvm profiling under the hood
Jvm profiling under the hood
RichardWarburton
 
Effective testing for spark programs Strata NY 2015
Effective testing for spark programs   Strata NY 2015Effective testing for spark programs   Strata NY 2015
Effective testing for spark programs Strata NY 2015
Holden Karau
 
[262] netflix 빅데이터 플랫폼
[262] netflix 빅데이터 플랫폼[262] netflix 빅데이터 플랫폼
[262] netflix 빅데이터 플랫폼
NAVER D2
 
Let's talk about Garbage Collection
Let's talk about Garbage CollectionLet's talk about Garbage Collection
Let's talk about Garbage Collection
Haim Yadid
 
Andrzej Ludwikowski - Event Sourcing - co może pójść nie tak?
Andrzej Ludwikowski -  Event Sourcing - co może pójść nie tak?Andrzej Ludwikowski -  Event Sourcing - co może pójść nie tak?
Andrzej Ludwikowski - Event Sourcing - co może pójść nie tak?
SegFaultConf
 
Implementing a JavaScript Engine
Implementing a JavaScript EngineImplementing a JavaScript Engine
Implementing a JavaScript Engine
Kris Mok
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
Bartosz Kosarzycki
 
Quick introduction to Java Garbage Collector (JVM GC)
Quick introduction to Java Garbage Collector (JVM GC)Quick introduction to Java Garbage Collector (JVM GC)
Quick introduction to Java Garbage Collector (JVM GC)
Marcos García
 

Similar to The State of Lightweight Threads for the JVM (20)

Kotlin Coroutines and Rx
Kotlin Coroutines and RxKotlin Coroutines and Rx
Kotlin Coroutines and Rx
Shaul Rosenzwieg
 
Blocks & GCD
Blocks & GCDBlocks & GCD
Blocks & GCD
rsebbe
 
Continuations in scala (incomplete version)
Continuations in scala (incomplete version)Continuations in scala (incomplete version)
Continuations in scala (incomplete version)
Fuqiang Wang
 
Structured concurrency with Kotlin Coroutines
Structured concurrency with Kotlin CoroutinesStructured concurrency with Kotlin Coroutines
Structured concurrency with Kotlin Coroutines
Vadims Savjolovs
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
async_io
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
JAX London
 
Could Virtual Threads cast away the usage of Kotlin Coroutines
Could Virtual Threads cast away the usage of Kotlin CoroutinesCould Virtual Threads cast away the usage of Kotlin Coroutines
Could Virtual Threads cast away the usage of Kotlin Coroutines
João Esperancinha
 
Concurrent Programming in Java
Concurrent Programming in JavaConcurrent Programming in Java
Concurrent Programming in Java
Ruben Inoto Soto
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from Oredev
Mattias Karlsson
 
The Future starts with a Promise
The Future starts with a PromiseThe Future starts with a Promise
The Future starts with a Promise
Alexandru Nedelcu
 
Clojure 1.1 And Beyond
Clojure 1.1 And BeyondClojure 1.1 And Beyond
Clojure 1.1 And Beyond
Mike Fogus
 
Concurrency with side-effects – cats way
Concurrency with side-effects – cats wayConcurrency with side-effects – cats way
Concurrency with side-effects – cats way
stasimus
 
Reactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysReactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDays
Manuel Bernhardt
 
Modern Java Concurrency
Modern Java ConcurrencyModern Java Concurrency
Modern Java Concurrency
Ben Evans
 
Back to the future with Java 7 (Geekout June/2011)
Back to the future with Java 7 (Geekout June/2011)Back to the future with Java 7 (Geekout June/2011)
Back to the future with Java 7 (Geekout June/2011)
Martijn Verburg
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in Practise
Christian Melchior
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019
Leonardo Borges
 
Need for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applicationsNeed for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applications
Konrad Malawski
 
Java On CRaC
Java On CRaCJava On CRaC
Java On CRaC
Simon Ritter
 
Profiling JavaScript Performance
Profiling JavaScript PerformanceProfiling JavaScript Performance
Profiling JavaScript Performance
FITC
 
Blocks & GCD
Blocks & GCDBlocks & GCD
Blocks & GCD
rsebbe
 
Continuations in scala (incomplete version)
Continuations in scala (incomplete version)Continuations in scala (incomplete version)
Continuations in scala (incomplete version)
Fuqiang Wang
 
Structured concurrency with Kotlin Coroutines
Structured concurrency with Kotlin CoroutinesStructured concurrency with Kotlin Coroutines
Structured concurrency with Kotlin Coroutines
Vadims Savjolovs
 
Javascript Promises/Q Library
Javascript Promises/Q LibraryJavascript Promises/Q Library
Javascript Promises/Q Library
async_io
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
JAX London
 
Could Virtual Threads cast away the usage of Kotlin Coroutines
Could Virtual Threads cast away the usage of Kotlin CoroutinesCould Virtual Threads cast away the usage of Kotlin Coroutines
Could Virtual Threads cast away the usage of Kotlin Coroutines
João Esperancinha
 
Concurrent Programming in Java
Concurrent Programming in JavaConcurrent Programming in Java
Concurrent Programming in Java
Ruben Inoto Soto
 
Java 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from OredevJava 7 Whats New(), Whats Next() from Oredev
Java 7 Whats New(), Whats Next() from Oredev
Mattias Karlsson
 
The Future starts with a Promise
The Future starts with a PromiseThe Future starts with a Promise
The Future starts with a Promise
Alexandru Nedelcu
 
Clojure 1.1 And Beyond
Clojure 1.1 And BeyondClojure 1.1 And Beyond
Clojure 1.1 And Beyond
Mike Fogus
 
Concurrency with side-effects – cats way
Concurrency with side-effects – cats wayConcurrency with side-effects – cats way
Concurrency with side-effects – cats way
stasimus
 
Reactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysReactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDays
Manuel Bernhardt
 
Modern Java Concurrency
Modern Java ConcurrencyModern Java Concurrency
Modern Java Concurrency
Ben Evans
 
Back to the future with Java 7 (Geekout June/2011)
Back to the future with Java 7 (Geekout June/2011)Back to the future with Java 7 (Geekout June/2011)
Back to the future with Java 7 (Geekout June/2011)
Martijn Verburg
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in Practise
Christian Melchior
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019
Leonardo Borges
 
Need for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applicationsNeed for Async: Hot pursuit for scalable applications
Need for Async: Hot pursuit for scalable applications
Konrad Malawski
 
Profiling JavaScript Performance
Profiling JavaScript PerformanceProfiling JavaScript Performance
Profiling JavaScript Performance
FITC
 
Ad

Recently uploaded (20)

Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep DiveDesigning Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
ScyllaDB
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-UmgebungenHCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
panagenda
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Technology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data AnalyticsTechnology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data Analytics
InData Labs
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
Build Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For DevsBuild Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For Devs
Brian McKeiver
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
Cybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure ADCybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure AD
VICTOR MAESTRE RAMIREZ
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep DiveDesigning Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
ScyllaDB
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-UmgebungenHCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
panagenda
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Technology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data AnalyticsTechnology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data Analytics
InData Labs
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
Build Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For DevsBuild Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For Devs
Brian McKeiver
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
Cybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure ADCybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure AD
VICTOR MAESTRE RAMIREZ
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Ad

The State of Lightweight Threads for the JVM

  • 1. The State of Fibers for the JVM Why all your JVM coroutines are cool, but broken, and Project Loom is gonna fix that! (Kilim threads, Quasar fibers, Kotlin coroutines, etc.) and ... Volkan Yazıcı https://vlkan.com @yazicivo Lightweight Threads Virtual 2018-03-08 2018-08-25 2019-12-10
  • 2. Agenda 1) Motivation 2) History 3) Continuations 4) Processes, threads, and fibers 5) Project Loom 6) Structured concurrency 7) Scoped variables
  • 3. Motivation: I/O Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
  • 4. Without I/O, you don’t exist! ● println() ● file access ● network socket access ● database access ● etc.
  • 5. In 1958, ... Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
  • 6. The legend of Melvin Conway Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
  • 7. Subroutine Coroutine⊂ Coroutine “Coroutines” – Melvin Conway, 1958 “Generalization of subroutine” – Donald Knuth, 1968 subroutines coroutines call allocate frame, pass params allocate frame, pass params return free frame, return result free frame, return result suspend No Yes resume No Yes Subroutine A Subroutine B … call B … B start end call B B start end Subroutine A Coroutine C … call C … C start end suspend suspend resume C resume C Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
  • 8. Where did all the coroutines go? Algol-60 … introduced code blocks and the begin and end pairs for delimiting them. ALGOL 60 was the first language implementing nested function definitions with lexical scope. – Wikipedia “ALGOL 60” Quoting from Gor Nishanov's 2016 "LLVM Coroutines: Bringing resumable functions to LLVM" talk.
  • 9. One “continuation” to rule them all...
  • 10. “Continuation Sandwich” ● The earliest description by Adriaan van Wijngaarden in 1964. ● “… a data structure that represents the computational process at a given point in the process's execution; ...” – Wikipedia “Continuation” ● “Say you're in the kitchen in front of the refrigerator, thinking about a sandwich. You take a continuation right there and stick it in your pocket. Then you get some turkey and bread out of the refrigerator and make yourself a sandwich, which is now sitting on the counter. You invoke the continuation in your pocket, and you find yourself standing in front of the refrigerator again, thinking about a sandwich. But fortunately, there's a sandwich on the counter, and all the materials used to make it are gone. So you eat it.” – Luke Palmer, 2004
  • 11. A glimpse of “continuation” (define the-continuation #f) (define (test) (let ((i 0)) ; call/cc calls its first function argument, passing ; a continuation variable representing this point in ; the program as the argument to that function. (call/cc (lambda (k) (set! the-continuation k))) ; The next time the-continuation is called, we start here. (set! i (+ i 1)) i)) > (test) 1 > (the-continuation) 2 > (the-continuation) 3 > ; stores the current continuation (which will print 4 next) away > (define another-continuation the-continuation) > (test) ; resets the-continuation 1 > (the-continuation) 2 > (another-continuation) ; uses the previously stored continuation 4 See Oleg Kiselyo’s An argument against call/cc and Undelimited continuations are not functions articles.
  • 12. A glimpse of “delimited continuation” ; The reset delimits the continuation that shift captures (named by k in this example). ; The use of shift will bind k to the continuation (+ 1 []), ; where [] represents the part of the computation that is to be filled with a value. (* 2 (reset (+ 1 (shift k (k 5))))) (reset (* 2 (shift k (k (k 4))))) ; invokes (k 4) first (which returns 8), ; and then (k 8) (which returns 16). ; At this point, the shift expression has terminated, ; and the rest of the reset expression is discarded. ; Therefore, the final result is 16. Unlike regular continuations, delimited continuations return a value, and thus may be reused and composed.
  • 13. What is so important about continuations? Using continuations you can implement ● longjmp (C) ● exceptions (C++, Java, etc.) ● generators (Icon, Python, etc.) ● backtracking (Prolog, etc.) ● and… guess what else?
  • 15. public SearchResponse search(SearchRequest request) { // Check caches. SearchResponse cachedResponse = cache.find(reqest); if (cachedResponse != null) { return cachedResponse; } // Check redirects. SearchResponse redirectedResponse = redirectService.find(request); if (redirectedResponse != null) { return redirectedResponse; } // Perform plain search enriched with suggestions. SearchRequest enrichedRequest = suggestionService.enrich(request); return plainSearch(enrichedRequest); } public void search( SearchRequest request, Consumer<SearchResponse> callback) { // Check caches. return cache.find(request, cachedResponse -> { if (cachedResponse != null) { callback.accept(cachedResponse); } else { // Check redirects. redirectService.find(request, redirectedResponse -> { if (redirectedResponse != null) { return callback.accept(redirectedResponse); } else { // Perform plain search enriched with suggestions. suggestionService.enrich(request, enrichedRequest -> { plainSearch(enrichedRequest, searchResponse -> { callback.accept(searchResponse); }); }); } }); } }); } Callbacks (non-blocking) public Mono<SearchResponse> search(SearchRequest request) { return Flux .concat(cache.find(request), redirectService.find(request), suggestionService .find(request) .flatMap(this::plainSearch)) .take(1) .singleOrEmpty(); } Reactor (non-blocking) Blocking calls How do we compose I/O? (without changing neither the language, nor the VM byte code)
  • 16. public SearchResponse search(SearchRequest request) { // Check caches. SearchResponse cachedResponse = cache.find(reqest); if (cachedResponse != null) { return cachedResponse; } // Check redirects. SearchResponse redirectedResponse = redirectService.find(request); if (redirectedResponse != null) { return redirectedResponse; } // Perform plain search enriched with suggestions. SearchRequest enrichedRequest = suggestionService.enrich(request); return plainSearch(enrichedRequest); } executed instructions time Blocking calls thread activity running blocked Blocking what?
  • 17. public Mono<SearchResponse> search(SearchRequest request) { return Flux .concat(cache.find(request), redirectService.find(request), suggestionService .find(request) .flatMap(this::plainSearch)) .take(1) .singleOrEmpty(); } Reactor (non-blocking) callchain How does asynchronous I/O get composed?
  • 18. Why all this reactive hassle? Thread-1 Thread-2 Thread-3 Thread-100... Request-1 Request-2 Request-3 Request-100... Thread-1 Request-1 Request-2 Request-3 Request-100... Callchain-1 Callchain-2 Callchain-3 Callchain-100 ... Reactor(non-blocking) Blockingcalls If spawning and context switching costs of threads would be equal to the ones in callchains, would you still favor the latter?
  • 19. Process-vs-thread Data1 Code1 (single-threaded) OS Process Registers1 Stack1 CPU1 CPU2 CPUK ... OS Scheduler Files1 Data2 Code2 Registers2 Stack2 Files2 Registers1 Stack1 Data Code CPU1 CPU2 CPUK ... OS Scheduler Registers2 Stack2 Registers3 Stack3 ... RegistersN StackN (multi-threaded) OS Process Files Both processes and threads denote a continuation: a sequence of instructions that can be suspended and resumed. process = continuation + scheduler thread = continuation + schedulerCheaper!
  • 20. What is a fiber? OS Process CPU1 CPU2 CPUK ... OS Scheduler Registers1 Stack1 Data Code Registers2 Stack2 Registers3 Stack3 RegistersN StackN Files ... Both processes and threads denote a continuation: a sequence of instructions that can be suspended and resumed. process = continuation + scheduler thread = continuation + schedulerCheaper! fiber = continuation + schedulerCheaper! kernel user ... User-level scheduler M321 kernel both share memory M >> N
  • 21. ● Yes, it can, but it (natively) doesn’t. ● Lisp(call/cc) , BEAM(Erlang VM) , Haskell, Go, JavaScript(async, await) (natively) do. ● Quasar, Kilim, etc. provides continuations and fibers for JVM. ● What if someone calls Thread.sleep()? ● What if a coroutine calls a non-coroutine method? What if that non-coroutine method is blocking? ● What about Kotlin coroutines? Does JVM support fibers? in essence, “continuations”
  • 22. What about actors(Erlang, Akka) / channels(Go, Kotlin) ? m1 m2 m3...mN fiber { BlockingQueue<V>(bufferSize) } = Channel<V>(bufferSize)
  • 23. A glimpse of Quasar & Kilim Quasar Kilim
  • 24. So what is the problem? Asynchronous task composition Reactive Streams FibersCallbacks ● Language-agnostic ● Difficult to write (callbackhell.com) ● Difficult to debug & profile ● Misses batteries ● Viral ● Language-agnostic ● Includes batteries ● Widely supported ● Need to learn a new language ● Difficult to write & get right ● Difficult to debug & profile ● Difficult to optimize (by compiler) ● Viral ● Just works ● Language-specific ● Requires explicit marking ● Misses batteries Reflective calls are always considered suspendable. This is because the target method is computed at runtime, so there’s no general way of telling if it’s going to call a suspendable method or not before execution. Java 8 lambdas too are always considered suspendable. This is because they can’t declare checked exceptions, they are ultimately linked (via invokedynamic) to synthethic static methods that can’t be annotated and it is difficult to tell at instrumentation time if lambdas implement a suspendable interface. Quasar will reject with an error any attempt to mark special methods (that is, constructors and class initializers) as suspendable. This is because suspending in an initializer could expose objects or classes before they’re fully initialized and this is an error- prone, difficult-to-troubleshoot situation that can always (and must) be avoided.
  • 27. ● Quasar: lightweight threads (fibers) for the JVM ● Comsat: fiber-aware impl’s of servlets, JAX-RS/Spring REST services, HTTP clients and JDBC ● SpaceBase: in-memory spatial and geo-spatial database ● Galaxy: distributed in-memory data grid that horizontally scales In 2012, founded Parallel Universe with the following F/OSS product line: Who is Ron Pressler anyway? http://www.paralleluniverse.co/ http://openjdk.java.net/census#loom Lead at Project Loom (since 2017)
  • 28. ● One of Java's most important contributions when it was first released, over twenty years ago, was the easy access to threads and synchronization primitives. ● … today's requirements is that the software unit of concurrency offered by the runtime — the thread — cannot match the scale of the domain's unit of concurrency, … ● … asynchronous APIs ... were created ● not because they are easier to write and to understand ● for they are actually harder ● not because they are easier to debug or profile ● they are harder (they don't even produce meaningful stacktraces) ● not because they compose better than synchronous APIs ● they compose less elegantly ● not because they fit better with the rest of the language or integrate well with existing code ● they are a much worse fit ● but just because the implementation of the software unit of concurrency in Java — the thread — is insufficient from a footprint and performance perspective. Proposal highlights
  • 29. The key project deliverable See Ron Pressler's detailed post in the loom-dev mailing list. Lightweight threads Asymmetric one-shot (non-reentrant) stackful multi-prompt delimited continuations.
  • 30. Are we there yet? ● OIO rewrite ● Continuations ● Strand → Fiber → Lightweight thread → Virtual thread ● Structured concurrency ● Scoped variables A word on “legacy”...
  • 32. ... ... ... ... ... The curse of control flow constructs sequence goto if loop call Quoting from Martin Sustrik's "Structured Concurrency" talk in FOSDEM'19.
  • 33. Is GOTO harmful? (So are threads!) Quoting from Nathaniel J. Smith's "Notes on structured concurrency" blog post.
  • 34. What does structured concurrency look like? Quoting from Nathaniel J. Smith's "Notes on structured concurrency" blog post. with open("my-file") as file_handle: ... ... ... ...
  • 35. A glimpse of Trio import trio async def child1(): print(" child1: started! sleeping now...") await trio.sleep(1) print(" child1: exiting!") async def child2(): print(" child2: started! sleeping now...") await trio.sleep(1) print(" child2: exiting!") async def parent(): print("parent: started!") async with trio.open_nursery() as nursery: print("parent: spawning child1...") nursery.start_soon(child1) print("parent: spawning child2...") nursery.start_soon(child2) print("parent: waiting for children to finish...") # -- we exit the nursery block here -- print("parent: all done!") trio.run(parent) parent: started! parent: spawning child1... parent: spawning child2... parent: waiting for children to finish... child2: started! sleeping now... child1: started! sleeping now... [... 1 second passes ...] child1: exiting! child2: exiting! parent: all done! A word on cancellation...
  • 37. public class ScopeDemo { private static final Logger LOGGER = LoggerFactory.getLogger(ScopeDemo.class); private final List<Runnable> tasks = new ArrayList<>(); private final ThreadLocal<StringBuilder> stringBuilderRef = ThreadLocal.withInitial(StringBuilder::new); public void addTask(Runnable task) { tasks.add(task); } public static void main(String[] args) throws IOException { try (InputStream inputStream = new FileInputStream("/etc/passwd")) { int firstByte = inputStream.read(); { int randomByte = (int) Math.abs(Math.random() * 0xFF); firstByte += randomByte; } } } } Don’t we already have scoped variables? What is the scope of a ThreadLocal?
  • 38. > x=1 > function g() { echo $x; x=2; } > function f() { local x=3; g; } > f > echo $x Static-vs-Dynamic scoping What do these two statements output?
  • 39. > color=null > function terrier(nursery) { echo “Terrier sees $color.”; } > function dog(nursery) { echo “Dog sees $color.” color=”black-and-white”; nursery.schedule(terrier) } > function cat(nursery) { echo “Cat sees $color.” } > with nursery { color=”colorful” nursery.schedule(dog) nursery.schedule(cat) } Dynamic scoping and structured concurrency What does this statement output?
  • 40. Conclusions ● Loom will radically change I/O composition in JVM. ● Structured concurrency and scoped variables will supplement that ease.