jesperancinha / good-story

An investigation and comparison between Kotlin and Java on an engineering level. Since beauty is in the eye of the beholder, this repository is not meant to evaluate Java or Kotlin on an aesthetic level.
Apache License 2.0
22 stars 0 forks source link

Kotlin Coroutines can dispatch on LOOM threads #74

Closed apatrida closed 1 year ago

apatrida commented 1 year ago

Nice article!

Have you considered dispatching Kotlin coroutines onto Loom VirtualThreads?

Example idea: https://kt.academy/article/dispatcher-loom

Here just create a simple dispatcher...

val Dispatchers.LOOM: CoroutineDispatcher
    get() = Executors.newVirtualThreadPerTaskExecutor().asCoroutineDispatcher()

And change your async { ... } call to use this dispatcher as

async(Dispatchers.LOOM) { ... }

Note your controlTest can have both a Thread { ... } version and a Thread.startVirtualThread { ... } version since nothing stops Kotlin from using LOOM virtual threads directly.

A lot of this code in the samples can be shared between them as Kotlin has no problem accessing Java classes, and most concepts in Kotlin are readable from Java as well. Unless you are worried about performance of basic code between the two, the total codebase could be reduced.

sample run-local with Java, Kotlin coroutines, Kotlin w/Loom async coroutines

Time Method Time Complexity Space Complexity Repetitions Java Duration Kotlin Duration Kotlin-Loom Duration Machine
2023-01-15T15:03:16.502528 wait0Nanos - Wait 0 Nanos - Running - Yielding - Virtual Thread n/a n/a 2 8 -1 -1 Prototype
2023-01-15T15:03:16.508950 wait100Mills - Wait 100 Mills - Running - Parking - Yield - Virtual Thread n/a n/a 2 101 -1 -1 Prototype
2023-01-15T15:03:16.509022 saveWordsNio - Write to 1 file - Yield - Virtual Thread n/a n/a 2 112 -1 -1 Prototype
2023-01-15T15:03:16.509055 saveWordsNio - Write to 1 file - Pinning - Yield - Virtual Thread n/a n/a 2 222 -1 -1 Prototype
2023-01-15T15:03:16.509082 findAllUniqueWords - All Unique Words n/a n/a 10000 1464 2839 2292 Prototype
2023-01-15T15:03:16.509110 findAllUniqueWordsWithCount - All Words with count n/a n/a 10000 1031 2081 1261 Prototype
2023-01-15T15:03:16.509137 revertText - Reverted Text O(n) O(1) 10000 324 866 594 Prototype
2023-01-15T15:03:16.509170 contentSplitIterateSubtractAndSum - Double iteration of an array of words O(n^2) O(1) 10000 373 1496 1120 Prototype
2023-01-15T15:03:16.509198 repetitionCount - Repetition count O(n^2) O(n) 10000 2238 2734 721 Prototype
2023-01-15T15:03:16.509223 createAvlTree - Create AVL Tree O(log n) O(n) 10000 1197 749 178 Prototype
2023-01-15T15:03:16.509249 findPrimeSecret - Secret word in Sieve of Eratosthenes O(n * log(log n)) O(n) 10000 556 1632 519 Prototype
2023-01-15T15:03:16.509277 createSplayTree - Create Splay Tree O(log n) O(n) 10000 153 604 215 Prototype
2023-01-15T15:03:16.509303 quickSort - Quick sort O(n * log n) O(log n) 10000 1057 3616 2815 Prototype
2023-01-15T15:03:16.509334 makeTextFromWordFlow - Make text from word Flow n/a n/a 10000 889 519 147 Prototype
2023-01-15T15:03:16.509367 createIntersectionWordList - Intersection Text Algorithm O(n) O(n) 10000 83 956 482 Prototype
2023-01-15T15:03:16.509397 controlTest - N/A n/a n/a 10000 742 596 722 Prototype
2023-01-15T15:03:16.509424 generalTest - N/A n/a n/a 10000 182 59 173 Prototype
2023-01-15T15:03:16.509450 findAllUniqueWords - wait0Nanos n/a n/a 2 -1 12 21 Prototype
2023-01-15T15:03:16.509475 controlTest-Loom - N/A n/a n/a 10000 -1 -1 10 Prototype

That last controlTest-Loom is just Kotlin controlTest changed to use VirtualThread

@DelicateCoroutinesApi
        suspend fun controlTestWithVirtualThreads(repeats: Int) {
            log.info("----====>>>> Starting LOOM controlTest <<<<====----")
            val startTimeT = LocalDateTime.now()
            val aiThread = AtomicInteger(0)
            withContext(Dispatchers.IO) {
                (1..repeats).map {
                    Thread.startVirtualThread { aiThread.getAndIncrement() }
                }.forEach { it.join() }
            }
            val endTimeT = LocalDateTime.now()
            log.info("Imma be the main Thread")
            log.info(aiThread.get().toString())
            log.info("It took me {} ms to finish", Duration.between(startTimeT, endTimeT).toMillis())     }
jesperancinha commented 1 year ago

Hi @apatrida, thank you so much for your contribution. I didn't knew that it was possible to dispatch coroutines onto Loom Virtual Threads. It is indeed a good addition to this repository. Thank you for letting me know!