Why would we want to limitedParallelism? Is due to the following question: if you use up all threads will operating system (OS) create cooperative environment for other processes that are running?.
Experiment aimed to roughly answer this
Experiment: load up CPU and try to use other apps in the meantime.
When I tried this on 16-core/32-thread AMD Ryzen 9 7945HX on Linux it seems at least Linux OS was creating a cooperative environment between the threads to not show perceivable slow down in other processes while the CPU was shown to be running at 100% per htop. Hence, as of now I don’t think it’s worth artificially lowering the parallelism and rather let OS take care of scheduling threads.
code-example loading up CPU for 30 seconds
GT-Sandbox-Snapshot: example loading up all the CPU cores for 30 seconds doing computation in a loop
Code
package com.glassthought.sandboximport kotlinx.coroutines.*import kotlin.system.measureTimeMillisfun main(): Unit = runBlocking(CoroutineName("main-runBlocking")) { val availableProcessors = Runtime.getRuntime().availableProcessors() println("Starting CPU stress test on $availableProcessors cores...") println("This will run for 30 seconds. System may become less responsive.") val duration = 30_000L // 30 seconds in milliseconds val elapsedTime = measureTimeMillis { // Create a list of jobs, one for each processor val jobs = List(availableProcessors) { coreIndex -> // Use Dispatchers.Default which has a thread pool sized to CPU cores // Each coroutine will pin to a thread and consume CPU launch(Dispatchers.Default + CoroutineName("cpu-loader-$coreIndex")) { println("Core $coreIndex: Starting intensive computation...") val startTime = System.currentTimeMillis() var counter = 0L var sum = 0.0 // Tight loop that runs for 30 seconds while (System.currentTimeMillis() - startTime < duration) { // Perform some CPU-intensive operations counter++ sum += Math.sqrt(counter.toDouble()) // Add some more operations to ensure CPU usage if (counter % 1000000 == 0L) { // Occasionally perform more complex calculations for (i in 1..100) { sum += Math.sin(sum) * Math.cos(counter.toDouble()) } } // Check for cancellation periodically (every million iterations) if (counter % 10000000 == 0L) { yield() // Allow coroutine cancellation if needed } } println("Core $coreIndex: Completed. Counter=$counter, Sum=$sum") } } // Wait for all jobs to complete jobs.joinAll() } println("\nCPU stress test completed in ${elapsedTime}ms") println("All $availableProcessors cores were loaded for approximately 30 seconds")}
Command to reproduce:
gt.sandbox.checkout.commit 552c189a3d508ae510c9 \&& cd "${GT_SANDBOX_REPO}" \&& cmd.run.announce "./gradlew run --quiet"
package gt.sandboximport gt.sandbox.internal.output.Outimport kotlinx.coroutines.*val out = Out.standard()suspend fun fetchData(s: String) { out.println("Fetching data... $s") delay(1000) // This suspends the coroutine for 1 second without blocking the thread out.println("Data fetched $s")}fun main(): Unit = runBlocking { val availableCores = Runtime.getRuntime().availableProcessors() out.println("Number of available cores: $availableCores") for (i in 1..(availableCores* 2) + 2) { launch(Dispatchers.IO) { fetchData("task $i") } }}
Command to reproduce:
gt.sandbox.checkout.commit 95c0ae2 \&& cd "${GT_SANDBOX_REPO}" \&& cmd.run.announce "./gradlew run"
Recorded output of command:
> Task :app:checkKotlinGradlePluginConfigurationErrors SKIPPED> Task :app:processResources NO-SOURCE> Task :app:compileKotlin> Task :app:compileJava NO-SOURCE> Task :app:classes UP-TO-DATE> Task :app:run[2024-06-09T04:23:29.630413Z][ms-elapsed-since-start: 47][tname:main/tid:1] Number of available cores: 10[2024-06-09T04:23:29.651359Z][ms-elapsed-since-start: 59][tname:DefaultDispatcher-worker-1/tid:21] Fetching data... task 1[2024-06-09T04:23:29.651570Z][ms-elapsed-since-start: 59][tname:DefaultDispatcher-worker-3/tid:23] Fetching data... task 2[2024-06-09T04:23:29.651777Z][ms-elapsed-since-start: 59][tname:DefaultDispatcher-worker-5/tid:25] Fetching data... task 3[2024-06-09T04:23:29.651815Z][ms-elapsed-since-start: 59][tname:DefaultDispatcher-worker-2/tid:22] Fetching data... task 4[2024-06-09T04:23:29.651846Z][ms-elapsed-since-start: 59][tname:DefaultDispatcher-worker-4/tid:24] Fetching data... task 5[2024-06-09T04:23:29.652016Z][ms-elapsed-since-start: 60][tname:DefaultDispatcher-worker-8/tid:28] Fetching data... task 6[2024-06-09T04:23:29.652160Z][ms-elapsed-since-start: 60][tname:DefaultDispatcher-worker-7/tid:27] Fetching data... task 7[2024-06-09T04:23:29.652243Z][ms-elapsed-since-start: 60][tname:DefaultDispatcher-worker-6/tid:26] Fetching data... task 8[2024-06-09T04:23:29.652418Z][ms-elapsed-since-start: 60][tname:DefaultDispatcher-worker-11/tid:31] Fetching data... task 9[2024-06-09T04:23:29.652762Z][ms-elapsed-since-start: 60][tname:DefaultDispatcher-worker-10/tid:30] Fetching data... task 10[2024-06-09T04:23:29.652811Z][ms-elapsed-since-start: 60][tname:DefaultDispatcher-worker-14/tid:34] Fetching data... task 11[2024-06-09T04:23:29.652945Z][ms-elapsed-since-start: 60][tname:DefaultDispatcher-worker-13/tid:33] Fetching data... task 12[2024-06-09T04:23:29.653149Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-18/tid:38] Fetching data... task 13[2024-06-09T04:23:29.653555Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-9/tid:29] Fetching data... task 15[2024-06-09T04:23:29.653556Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-21/tid:41] Fetching data... task 14[2024-06-09T04:23:29.653623Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-7/tid:27] Fetching data... task 16[2024-06-09T04:23:29.653651Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-9/tid:29] Fetching data... task 17[2024-06-09T04:23:29.653676Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-13/tid:33] Fetching data... task 18[2024-06-09T04:23:29.653717Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-7/tid:27] Fetching data... task 20[2024-06-09T04:23:29.653692Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-21/tid:41] Fetching data... task 19[2024-06-09T04:23:29.653867Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-21/tid:41] Fetching data... task 22[2024-06-09T04:23:29.653732Z][ms-elapsed-since-start: 61][tname:DefaultDispatcher-worker-9/tid:29] Fetching data... task 21[2024-06-09T04:23:30.661370Z][ms-elapsed-since-start: 1069][tname:DefaultDispatcher-worker-17/tid:37] Data fetched task 7[2024-06-09T04:23:30.661588Z][ms-elapsed-since-start: 1069][tname:DefaultDispatcher-worker-15/tid:35] Data fetched task 4[2024-06-09T04:23:30.662263Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-15/tid:35] Data fetched task 8[2024-06-09T04:23:30.661870Z][ms-elapsed-since-start: 1069][tname:DefaultDispatcher-worker-19/tid:39] Data fetched task 2[2024-06-09T04:23:30.662439Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-15/tid:35] Data fetched task 3[2024-06-09T04:23:30.662540Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-19/tid:39] Data fetched task 6[2024-06-09T04:23:30.662606Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-15/tid:35] Data fetched task 1[2024-06-09T04:23:30.662685Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-19/tid:39] Data fetched task 10[2024-06-09T04:23:30.662824Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-19/tid:39] Data fetched task 11[2024-06-09T04:23:30.662870Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-24/tid:45] Data fetched task 13[2024-06-09T04:23:30.662972Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-19/tid:39] Data fetched task 15[2024-06-09T04:23:30.663027Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-24/tid:45] Data fetched task 14[2024-06-09T04:23:30.661376Z][ms-elapsed-since-start: 1069][tname:DefaultDispatcher-worker-18/tid:38] Data fetched task 9[2024-06-09T04:23:30.663206Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-24/tid:45] Data fetched task 17[2024-06-09T04:23:30.663273Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-18/tid:38] Data fetched task 18[2024-06-09T04:23:30.663533Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-6/tid:26] Data fetched task 19[2024-06-09T04:23:30.663124Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-19/tid:39] Data fetched task 16[2024-06-09T04:23:30.662265Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-17/tid:37] Data fetched task 5[2024-06-09T04:23:30.662858Z][ms-elapsed-since-start: 1070][tname:DefaultDispatcher-worker-15/tid:35] Data fetched task 12[2024-06-09T04:23:30.663355Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-24/tid:45] Data fetched task 20[2024-06-09T04:23:30.663540Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-18/tid:38] Data fetched task 22[2024-06-09T04:23:30.663689Z][ms-elapsed-since-start: 1071][tname:DefaultDispatcher-worker-6/tid:26] Data fetched task 21BUILD SUCCESSFUL in 1s2 actionable tasks: 2 executed