Multithreading in Scala Native, Scalar.pptx

Virtuslab 17 views 28 slides Jun 17, 2024
Slide 1
Slide 1 of 28
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28

About This Presentation

Wojciech Mazur's presentation on "Implementing multithreading in Scala Native" as featured at the 2024 Scalar conference in Warsaw.


Slide Content

Wojciech Mazur Implementing multithreading in Scala Native …or a story of 201 little pains

AboutMe.md Scala 3 Compiler Team at VirtusLab Lead of Scala Native team Open Community Build, Scala 3 migrations, Scala 3 compiler (spuriously)

Goals for SN multithreading Java Threads API Mostly-compliant JVM semantics Easy cross-compilation between JVM scala.concurrent*. , scala.collection.concurrent.* java.util.concurrent.*

Timeline August 2021 - First multithreading commits December 2021 - E nd of Scala Native founding September 2022 - Founding restored, multithreading work starts March 2023 - To be released soon, just a few more improvements March 2024 - Scala Native 0.5.0

Scala Native 0.5.0 Multithreading support (duh!) Initial 32-bit architecture support Initial source level debugging support SIP-51 (unfreezing Scala 2 standard library) ready Java Service Providers Interface - explicitly configured Continuations primitives - virtual threads to be added later

Scala Native 0.5.0 250+ PRs 120 000+ added lines of code 40 000+ modified lines of code 16 contributors

So what works already?

java.util.concurrent.locks java.lang.Thread scala.collection.concurrent scala.collection.parallel scala.concurrent java.util.concurrent java.util.concurrent.atomic scala.runtime

… and the unexpected

Why it took that long?

Thread-safe objects initialization Thread-safe garbage collection Threads parking/unparking Memory model for shared variables Concurrent collections Thread local storage Java Memory Model compliance Efficient thread-safe object allocations Handling GC during blocking calls Stopping threads for GC Synchronized objects access Thread-safe lazy vals Concurrent collections Atomic field updaters Virtual threads

Garbage Collector User / runtime threads

Garbage Collector

How to allocate new objects? How to reclaim unused memory?

Memory representation of GC heap 256 bytes 128 lines Synchronized

Memory representation of GC heap Synchronized

Marking reachable objects Thread stack Thread registers Global objects Custom address ranges

Stop the world T1 T2 T4 T3 T5 Some thread triggered GC. Start Stop-The-World event All threads stopped Execute GC. Resume threads

Safe points

How to stop the threads? Suspending Threads Cooperative Interruptible Suspend by sending signal to thread Blocking calls can fail: Requires recovery in user code Boehm GC Check if GC wants to stop threads Yields only in safe code locations Polling for stop event injected to user code JVM, .Net and Scala Native Immix

Yield points May trigger segmentation fault!

What if GC want’s to collect?

…or treat all external calls as potentially blocking By default inform GC only about potentially blocking calls

Object monitors

Critical section Only 1 object allowed Wait room queue Entry room queue Entry Exit Notified

Where to keep synchronization state? Embed in object Map[Object, ObjectMonitor] Don’t synchronize? slow, does not permit object GC JVM compliance broken Increased memory usage

Keeping state of object monitors? Most objects do not experience enter monitor concurrently Allocating monitor on first enter to object monitor is wasting memory

Initially monitor= NULL (thin, unlocked) Lock/unlock using CompareAndSwap If CAS fails or using wait - inflate Operate on bit set How object monitors work? Created by inflation of thin lock Lock/unlock using CompareAndSwap Access based on queue ordering or data race Can notify waiting threads Can nominate successor thread Operate on structure assigned to object Thin locks Fat locks