Skip to content

Commit

Permalink
Merge branch 'improve-benchmark' into split-modules-and-decouple
Browse files Browse the repository at this point in the history
  • Loading branch information
ShreckYe committed Nov 19, 2024
2 parents 6eb83a7 + 920627f commit 9a93c0e
Showing 1 changed file with 58 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.huanshankeji.exposed.benchmark

import com.huanshankeji.kotlinx.coroutine.awaitAny
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import kotlinx.benchmark.*
import kotlinx.coroutines.*
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.experimental.suspendedTransactionAsync
import org.jetbrains.exposed.sql.transactions.transaction
import java.util.concurrent.Executors
import kotlin.concurrent.thread

@State(Scope.Benchmark)
Expand All @@ -26,23 +25,25 @@ class TransactionBenchmark : WithContainerizedDatabaseBenchmark() {
repeat(`10K`) { transaction(database) {} }
}

private suspend fun awaitAsync10KTransactions() =
coroutineScope {
List(`10K`) { async { transaction(database) {} } }.awaitAll()
}

@Benchmark
fun singleThreadConcurrent10KTransactions() = runBlocking {
awaitAsync10KTransactions()
}
@Suppress("SuspendFunctionOnCoroutineScope")
private suspend inline fun CoroutineScope.awaitAsync10K(crossinline block: () -> Unit) =
List(`10K`) { async { block() } }.awaitAll()

@Suppress("SuspendFunctionOnCoroutineScope")
private suspend fun CoroutineScope.awaitAsync10KTransactions() =
awaitAsync10K { transaction(database) {} }

@Benchmark
fun multiThreadConcurrent10KTransactions() = runBlocking {
withContext(Dispatchers.Default) {
fun singleThreadConcurrent10KTransactions() =
@OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class)
runBlocking(newSingleThreadContext("single thread")) {
awaitAsync10KTransactions()
}
}


@Benchmark
fun multiThreadConcurrent10KTransactionsWithSharedDatabase() =
runBlocking { awaitAsync10KTransactions() }


@Benchmark
Expand All @@ -52,12 +53,18 @@ class TransactionBenchmark : WithContainerizedDatabaseBenchmark() {

@Benchmark
fun _10KSuspendedTransactionAsyncs() = runBlocking {
List(`10K`) { suspendedTransactionAsync(db = database) {} }.awaitAny()
List(`10K`) { suspendedTransactionAsync(db = database) {} }.awaitAll()
}

private fun numProcessors() =
Runtime.getRuntime().availableProcessors().also {
println("Number of processors: $it")
}

@Benchmark
fun multiThreadMultiConnectionEach10KLocalTransactions() {
List(Runtime.getRuntime().availableProcessors()) {
// Note that on a device with heterogeneous architecture some threads may finish earlier than others.
List(numProcessors()) {
thread {
val database = databaseConnect()
repeat(`10K`) { transaction(database) {} }
Expand All @@ -66,4 +73,37 @@ class TransactionBenchmark : WithContainerizedDatabaseBenchmark() {
it.join()
}
}


val databaseThreadLocal = ThreadLocal<Database>()
lateinit var dispatcherWithThreadLocalDatabases: ExecutorCoroutineDispatcher

@Setup
fun setUpThreadLocalDatabases() {
dispatcherWithThreadLocalDatabases = Executors.newFixedThreadPool(numProcessors()) {
Thread {
it.run()
databaseThreadLocal.set(databaseConnect())
}
}.asCoroutineDispatcher()
}

@TearDown
fun teardownDispatcherWithThreadLocalDatabases() {
dispatcherWithThreadLocalDatabases.close()
}

@Benchmark
fun multiThreadConcurrent10KTransactionsWithThreadLocalDatabases() {
runBlocking(dispatcherWithThreadLocalDatabases) {
awaitAsync10K { transaction(databaseThreadLocal.get()) {} }
}
}

@Benchmark
fun multiThreadConcurrent10KTransactionsWithImplicitThreadLocalDatabases() {
runBlocking(dispatcherWithThreadLocalDatabases) {
awaitAsync10K { transaction {} }
}
}
}

0 comments on commit 9a93c0e

Please sign in to comment.