Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flatten: use loop and ArrayDeque instead of recursion #1801

Merged
merged 16 commits into from
Mar 29, 2024
Merged
10 changes: 6 additions & 4 deletions examples/jvm-perfs/benchmark.txt
hoc081098 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Benchmark Mode Cnt Score Error Units
BenchmarkClass.emptyStart avgt 10 ≈ 10⁻³ ms/op
BenchmarkClass.start400 avgt 10 0,272 ± 0,045 ms/op
BenchmarkClass.start400AndInject avgt 10 0,265 ± 0,022 ms/op
Benchmark Mode Cnt Score Error Units
BenchmarkClass.emptyStart avgt 10 ≈ 10⁻³ ms/op
BenchmarkClass.flatten avgt 10 146.838 ± 15.775 ms/op
BenchmarkClass.newFlatten avgt 10 0.880 ± 0.018 ms/op
BenchmarkClass.start400 avgt 10 0.282 ± 0.005 ms/op
BenchmarkClass.start400AndInject avgt 10 0.278 ± 0.004 ms/op
2 changes: 1 addition & 1 deletion examples/jvm-perfs/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ tasks.getByName<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>("compileKotlin"

val jmhVersion = "1.36"
//TODO get from existing version.gradle file
val koin_version = "3.5.2-RC1"
val koin_version = "3.5.3"
val coroutines_version = "1.7.3"

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,14 @@ open class BenchmarkClass {
}.koin
koinScenario(koin)
}

@Benchmark
fun flatten() {
org.koin.core.module.flatten(nestedModules)
}

@Benchmark
fun newFlatten() {
newFlatten(nestedModules)
}
}
hoc081098 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.koin.benchmark

import org.koin.core.annotation.KoinInternalApi
import org.koin.core.module.Module
import org.koin.core.qualifier.qualifier
import org.koin.dsl.module

private val level0Modules = List(100) {
module {}
}

private val level1Modules = List(100) {
val q = qualifier("q-$it")
module {
includes(level0Modules)
single(q) { A1() }
single(q) { A2() }
single(q) { A3() }
single(q) { A4() }
single(q) { A5() }
}
}

private val level2Modules = List(100) {
val q = qualifier("q-$it")
module {
includes(level0Modules)
includes(level1Modules[it])

single(q) { A6() }
single(q) { A7() }
single(q) { A8() }
single(q) { A9() }
single(q) { A10() }
}
}

private val level3Modules = List(100) {
val q = qualifier("q-$it")
module {
includes(level0Modules)
includes(level2Modules[it])

single(q) { A11() }
single(q) { A12() }
single(q) { A13() }
single(q) { A14() }
single(q) { A15() }
}
}

private val level4Modules = List(100) {
val q = qualifier("q-$it")
module {
includes(level0Modules)
includes(level3Modules[it])

single(q) { A16() }
single(q) { A17() }
single(q) { A18() }
single(q) { A19() }
single(q) { A20() }
}
}

internal val nestedModules: List<Module> = List(100) {
val q = qualifier("q-$it")
module {
includes(level0Modules)
includes(level1Modules)
includes(level2Modules)
includes(level3Modules)
includes(level4Modules)

single(q) { A16() }
single(q) { A17() }
single(q) { A18() }
single(q) { A19() }
single(q) { A20() }
}
}

@OptIn(KoinInternalApi::class)
internal fun newFlatten(modules: List<Module>): Set<Module> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity: can't you use the original function here instead of duplicating it?

val flatten = HashSet<Module>()
val stack = ArrayDeque<Module>(modules)

while (stack.isNotEmpty()) {
val current = stack.removeLast()
flatten.add(current)
hoc081098 marked this conversation as resolved.
Show resolved Hide resolved
current.includedModules.forEach {
if (it !in flatten) {
stack.addLast(it)
hoc081098 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

return flatten
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,19 @@ operator fun List<Module>.plus(module: Module): List<Module> = this + listOf(mod
* Run through the module list to flatten all modules & submodules
*/
@OptIn(KoinInternalApi::class)
fun flatten(modules: List<Module>): Set<Module> {
fun flat(modules: List<Module>, newModules: MutableSet<Module>){
modules.forEach{
newModules += it
flat(it.includedModules,newModules)
fun flatten(modules: List<Module>): Set<Module> {
hoc081098 marked this conversation as resolved.
Show resolved Hide resolved
val flatten = HashSet<Module>()
val stack = ArrayDeque<Module>(modules)

while (stack.isNotEmpty()) {
val current = stack.removeLast()
flatten.add(current)
current.includedModules.forEach {
hoc081098 marked this conversation as resolved.
Show resolved Hide resolved
if (it !in flatten) {
hoc081098 marked this conversation as resolved.
Show resolved Hide resolved
stack.addLast(it)
}
}
}
return mutableSetOf<Module>().apply { flat(modules,this) }

return flatten
}
Loading