From 17094bbd8c712c1112079b88486b8c6a48ebf0d5 Mon Sep 17 00:00:00 2001 From: Ruslan Ibragimov Date: Sat, 13 Mar 2021 16:48:58 +0300 Subject: [PATCH] Kotlin-lazy FTW --- README.md | 134 +++----- common-deep/build.gradle.kts | 1 + .../src/test/kotlin/GenerateKotlinLazy.kt | 9 + common-deep/src/test/kotlin/TestRunner.kt | 104 ++++++ kotlin-lazy-deep/build.gradle.kts | 20 ++ .../src/main/kotlin/io/heapy/klazy/Main.kt | 317 ++++++++++++++++++ kotlin-lazy/build.gradle.kts | 20 ++ .../src/main/kotlin/io/heapy/klazy/Main.kt | 20 ++ settings.gradle.kts | 3 + 9 files changed, 533 insertions(+), 95 deletions(-) create mode 100644 common-deep/src/test/kotlin/GenerateKotlinLazy.kt create mode 100644 common-deep/src/test/kotlin/TestRunner.kt create mode 100644 kotlin-lazy-deep/build.gradle.kts create mode 100644 kotlin-lazy-deep/src/main/kotlin/io/heapy/klazy/Main.kt create mode 100644 kotlin-lazy/build.gradle.kts create mode 100644 kotlin-lazy/src/main/kotlin/io/heapy/klazy/Main.kt diff --git a/README.md b/README.md index f72e624..932ee6f 100644 --- a/README.md +++ b/README.md @@ -12,115 +12,59 @@ Processing". ``` # Build ./gradlew clean build installDist distTar -``` - -``` -# Get the file sizes -find . -name '*.tar' |xargs ls -lh |grep -v original |grep -v common -``` +# Run +TestRunner in common-deep/src/test/kotlin ``` -# Execution time - -# JVM Baseline -time (for i in {1..10}; do ./jvm/build/install/jvm/bin/jvm; done) - -# 2 classes - -time (for i in {1..10}; do ./baseline/build/install/baseline/bin/baseline; done) -time (for i in {1..10}; do ./bootique/build/install/bootique/bin/bootique; done) -time (for i in {1..10}; do ./cayennedi/build/install/cayennedi/bin/cayennedi; done) -time (for i in {1..10}; do ./dagger/build/install/dagger/bin/dagger; done) -time (for i in {1..10}; do ./guice/build/install/guice/bin/guice; done) -time (for i in {1..10}; do ./komodo/build/install/komodo/bin/komodo; done) -time (for i in {1..10}; do ./owb/build/install/owb/bin/owb; done) -time (for i in {1..10}; do ./spring/build/install/spring/bin/spring; done) -time (for i in {1..10}; do ./springboot/build/install/springboot/bin/springboot; done) -time (for i in {1..10}; do ./koin/build/install/koin/bin/koin; done) -time (for i in {1..10}; do ./koin-reflect/build/install/koin-reflect/bin/koin-reflect; done) -time (for i in {1..10}; do ./kodein/build/install/kodein/bin/kodein; done) -# 100 classes +## Test machine -time (for i in {1..10}; do ./baseline-deep/build/install/baseline-deep/bin/baseline-deep; done) -time (for i in {1..10}; do ./bootique-deep/build/install/bootique-deep/bin/bootique-deep; done) -time (for i in {1..10}; do ./cayennedi-deep/build/install/cayennedi-deep/bin/cayennedi-deep; done) -time (for i in {1..10}; do ./dagger-deep/build/install/dagger-deep/bin/dagger-deep; done) -time (for i in {1..10}; do ./guice-deep/build/install/guice-deep/bin/guice-deep; done) -time (for i in {1..10}; do ./komodo-deep/build/install/komodo-deep/bin/komodo-deep; done) -time (for i in {1..10}; do ./owb-deep/build/install/owb-deep/bin/owb-deep; done) -time (for i in {1..10}; do ./spring-deep/build/install/spring-deep/bin/spring-deep; done) -time (for i in {1..10}; do ./springboot-deep/build/install/springboot-deep/bin/springboot-deep; done) -time (for i in {1..10}; do ./koin-deep/build/install/koin-deep/bin/koin-deep; done) -time (for i in {1..10}; do ./koin-reflect-deep/build/install/koin-reflect-deep/bin/koin-reflect-deep; done) -time (for i in {1..10}; do ./kodein-deep/build/install/kodein-deep/bin/kodein-deep; done) ``` +MacBook Pro (16-inch, 2019) +Processor: 2,6 GHz 6-Core Intel Core i7 +Memory: 32 GB 2667 MHz DDR4 +openjdk 11.0.10 2021-01-19 LTS +OpenJDK Runtime Environment Corretto-11.0.10.9.1 (build 11.0.10+9-LTS) +OpenJDK 64-Bit Server VM Corretto-11.0.10.9.1 (build 11.0.10+9-LTS, mixed mode) ``` -# Lines of code for 2 classes -cloc ./baseline/src -cloc ./bootique/src -cloc ./cayennedi/src -cloc ./dagger/src/main/java -cloc ./guice/src -cloc ./komodo/src -cloc ./owb/src -cloc ./spring/src -cloc ./springboot/src -cloc ./koin/src -cloc ./kodein/src - -# Lines of code for 100 classes - -cloc ./baseline-deep/src -cloc ./bootique-deep/src -cloc ./cayennedi-deep/src -cloc ./dagger-deep/src/main/java -cloc ./guice-deep/src -cloc ./komodo-deep/src -cloc ./owb-deep/src -cloc ./spring-deep/src -cloc ./springboot-deep/src -cloc ./koin-deep/src -cloc ./kodein-deep/src -``` - -# Results for JVM (JDK 11) +## Results for JVM (JDK 11) |DI|Jar w/Deps Size, Mb|:arrow_down: Exec time, s|LoC| |----|----|----|----| -|JVM Baseline|TODO|TODO|-| +|jvm|1.69|111|2| ## Results for 2 classes (JDK 11) - -|DI|Jar w/Deps Size, Mb|:arrow_down: Exec time, s|LoC| +|DI|Jar w/Deps Size, Mb|:arrow_down: Exec time, ms|LoC| |----|----|----|----| -|Baseline|1.7|1.35|7| -|Dagger|1.7|1.41|37| -|Cayenne DI|1.8|2.05|37| -|Koin|1.8|2.56|16| -|Koin-Reflect|TODO|TODO|TODO| -|Kodein|2.4|2.93|17| -|Bootique|4.2|4.31|52| -|Guice|5.3|6.51|33| -|Komodo|6.4|7.56|17| -|Spring|5.5|8.36|23| -|OpenWebBeans|3.0|10.02|35| -|Spring Boot|9.2|26.94|42| +|kotlin-lazy|1.69|118|16| +|baseline|1.69|130|7| +|dagger|1.73|130|37| +|cayennedi|1.76|158|37| +|koin|1.85|160|16| +|koin-reflect|1.88|170|17| +|kodein|2.36|180|17| +|bootique|4.18|229|52| +|guice|5.42|331|33| +|spring|5.60|356|23| +|komodo|6.41|392|17| +|owb|3.05|421|35| +|springboot|9.73|916|42| ## Results for 100 classes (JDK 11) -|DI|Jar w/Deps Size, Mb|:arrow_down: Exec time, s|LoC| +|DI|Jar w/Deps Size, Mb|:arrow_down: Exec time, ms|LoC| |----|----|----|----| -|Baseline|1.8|2.28|107| -|Dagger|2.0|2.70|534| -|Cayenne DI|2.0|3.70|1444| -|Koin|2.1|3.92|113| -|Koin-Reflect|TODO|TODO|TODO| -|Kodein|2.9|5.58|114| -|Bootique|4.3|5.79|549| -|Guice|5.4|8.70|530| -|Spring|5.5|12.81|420| -|Komodo|6.6|12.87|114| -|OpenWebBeans|3.2|16.16|532| -|Spring Boot|9.4|30.42|439| +|baseline-deep|1.83|142|107| +|kotlin-lazy-deep|1.91|158|313| +|dagger-deep|1.96|163|534| +|cayennedi-deep|1.95|212|1444| +|koin-deep|2.13|216|113| +|koin-reflect-deep|2.51|241|114| +|bootique-deep|4.31|280|549| +|kodein-deep|2.92|284|114| +|guice-deep|5.56|407|530| +|spring-deep|5.73|469|420| +|komodo-deep|6.64|531|114| +|owb-deep|3.18|584|532| +|springboot-deep|9.85|1054|439| diff --git a/common-deep/build.gradle.kts b/common-deep/build.gradle.kts index 0439aa5..8e70e01 100644 --- a/common-deep/build.gradle.kts +++ b/common-deep/build.gradle.kts @@ -8,4 +8,5 @@ repositories { dependencies { api(kotlin("stdlib-jdk8")) + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.2") } diff --git a/common-deep/src/test/kotlin/GenerateKotlinLazy.kt b/common-deep/src/test/kotlin/GenerateKotlinLazy.kt new file mode 100644 index 0000000..984c552 --- /dev/null +++ b/common-deep/src/test/kotlin/GenerateKotlinLazy.kt @@ -0,0 +1,9 @@ +fun main() { + (1..101).forEach { + println(""" + open val s$it: Service$it by lazy { + DefaultService$it(s${it + 1}) + } + """.trimIndent()) + } +} diff --git a/common-deep/src/test/kotlin/TestRunner.kt b/common-deep/src/test/kotlin/TestRunner.kt new file mode 100644 index 0000000..2f05c36 --- /dev/null +++ b/common-deep/src/test/kotlin/TestRunner.kt @@ -0,0 +1,104 @@ +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import java.nio.file.Files +import java.nio.file.Paths +import java.time.Duration +import java.util.Locale +import kotlin.system.measureNanoTime + +val projects = listOf( + "baseline", + "bootique", + "cayennedi", + "dagger", + "guice", +// "helidon", + "kodein", + "koin", + "koin-reflect", + "komodo", + "kotlin-lazy", +// "micronaut", + "owb", +// "quarkus", + "spring", +// "spring-fu", +// "spring-index", +// "spring-scan", +// "spring-scan-large", +// "spring-xml", + "springboot", +// "springboot-index", +) + +data class TestResult( + val project: String, + val fileSize: String, // MB + val loc: Int, + val execTime: Long // ms +) + +val om = jacksonObjectMapper() + +fun main() { + val jvm = listOf("jvm").map(::calculate).sortedBy { it.execTime }.toTable() + val table = projects.map(::calculate).sortedBy { it.execTime }.toTable() + val tableDeep = projects.map { "$it-deep" }.map(::calculate).sortedBy { it.execTime }.toTable() + + println(jvm) + println(table) + println(tableDeep) +} + +fun calculate(prj: String): TestResult { + val iterations = 50 + + val artifactPath = Paths.get("$prj/build/distributions/$prj.tar") + val size = Files.size(artifactPath) + + val clocProc = ProcessBuilder() + .command("/usr/local/bin/cloc", "--json", "/Users/mbp/dev/pet/di-comparison/$prj/src") + .start() + val clocText = clocProc.inputStream.reader().readText() + val clocResult = om.readValue(clocText) + + val nanos = measureNanoTime { + (1..iterations).forEach { iter -> + println("$prj-$iter") + ProcessBuilder() + .command("/Users/mbp/dev/pet/di-comparison/$prj/build/install/$prj/bin/$prj") + .start() + .waitFor() + } + } + + return TestResult( + project = prj, + fileSize = "%1$,.2f".format(Locale.US, size.toDouble() / 1024 / 1024), + loc = clocResult.sum.code, + execTime = Duration.ofNanos(nanos / iterations).toMillis() + ) +} + +@JsonIgnoreProperties(ignoreUnknown = true) +data class ClocResult( + @JsonProperty("SUM") + val sum: ClocSumResult +) + +@JsonIgnoreProperties(ignoreUnknown = true) +data class ClocSumResult( + val code: Int +) + +fun List.toTable(): String { + return buildString { + appendLine("|DI|Jar w/Deps Size, Mb|:arrow_down: Exec time, ms|LoC|") + appendLine("|----|----|----|----|") + this@toTable.forEach { result -> + appendLine("|${result.project}|${result.fileSize}|${result.execTime}|${result.loc}|") + } + } +} diff --git a/kotlin-lazy-deep/build.gradle.kts b/kotlin-lazy-deep/build.gradle.kts new file mode 100644 index 0000000..85eca5e --- /dev/null +++ b/kotlin-lazy-deep/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + kotlin("jvm").version("1.4.31") + application +} + +application { + mainClass.set("io.heapy.klazy.MainKt") +} + +tasks.withType().configureEach { + kotlinOptions.jvmTarget = "11" +} + +repositories { + mavenCentral() +} + +dependencies { + implementation(project(":common-deep")) +} diff --git a/kotlin-lazy-deep/src/main/kotlin/io/heapy/klazy/Main.kt b/kotlin-lazy-deep/src/main/kotlin/io/heapy/klazy/Main.kt new file mode 100644 index 0000000..fd7e36d --- /dev/null +++ b/kotlin-lazy-deep/src/main/kotlin/io/heapy/klazy/Main.kt @@ -0,0 +1,317 @@ +package io.heapy.klazy + +import io.heapy.sample.common2.* + +fun main() { + println(Main().s.name()) +} + +open class Main { + open val s: Service by lazy { + DefaultService(s1) + } + open val s1: Service1 by lazy { + DefaultService1(s2) + } + open val s2: Service2 by lazy { + DefaultService2(s3) + } + open val s3: Service3 by lazy { + DefaultService3(s4) + } + open val s4: Service4 by lazy { + DefaultService4(s5) + } + open val s5: Service5 by lazy { + DefaultService5(s6) + } + open val s6: Service6 by lazy { + DefaultService6(s7) + } + open val s7: Service7 by lazy { + DefaultService7(s8) + } + open val s8: Service8 by lazy { + DefaultService8(s9) + } + open val s9: Service9 by lazy { + DefaultService9(s10) + } + open val s10: Service10 by lazy { + DefaultService10(s11) + } + open val s11: Service11 by lazy { + DefaultService11(s12) + } + open val s12: Service12 by lazy { + DefaultService12(s13) + } + open val s13: Service13 by lazy { + DefaultService13(s14) + } + open val s14: Service14 by lazy { + DefaultService14(s15) + } + open val s15: Service15 by lazy { + DefaultService15(s16) + } + open val s16: Service16 by lazy { + DefaultService16(s17) + } + open val s17: Service17 by lazy { + DefaultService17(s18) + } + open val s18: Service18 by lazy { + DefaultService18(s19) + } + open val s19: Service19 by lazy { + DefaultService19(s20) + } + open val s20: Service20 by lazy { + DefaultService20(s21) + } + open val s21: Service21 by lazy { + DefaultService21(s22) + } + open val s22: Service22 by lazy { + DefaultService22(s23) + } + open val s23: Service23 by lazy { + DefaultService23(s24) + } + open val s24: Service24 by lazy { + DefaultService24(s25) + } + open val s25: Service25 by lazy { + DefaultService25(s26) + } + open val s26: Service26 by lazy { + DefaultService26(s27) + } + open val s27: Service27 by lazy { + DefaultService27(s28) + } + open val s28: Service28 by lazy { + DefaultService28(s29) + } + open val s29: Service29 by lazy { + DefaultService29(s30) + } + open val s30: Service30 by lazy { + DefaultService30(s31) + } + open val s31: Service31 by lazy { + DefaultService31(s32) + } + open val s32: Service32 by lazy { + DefaultService32(s33) + } + open val s33: Service33 by lazy { + DefaultService33(s34) + } + open val s34: Service34 by lazy { + DefaultService34(s35) + } + open val s35: Service35 by lazy { + DefaultService35(s36) + } + open val s36: Service36 by lazy { + DefaultService36(s37) + } + open val s37: Service37 by lazy { + DefaultService37(s38) + } + open val s38: Service38 by lazy { + DefaultService38(s39) + } + open val s39: Service39 by lazy { + DefaultService39(s40) + } + open val s40: Service40 by lazy { + DefaultService40(s41) + } + open val s41: Service41 by lazy { + DefaultService41(s42) + } + open val s42: Service42 by lazy { + DefaultService42(s43) + } + open val s43: Service43 by lazy { + DefaultService43(s44) + } + open val s44: Service44 by lazy { + DefaultService44(s45) + } + open val s45: Service45 by lazy { + DefaultService45(s46) + } + open val s46: Service46 by lazy { + DefaultService46(s47) + } + open val s47: Service47 by lazy { + DefaultService47(s48) + } + open val s48: Service48 by lazy { + DefaultService48(s49) + } + open val s49: Service49 by lazy { + DefaultService49(s50) + } + open val s50: Service50 by lazy { + DefaultService50(s51) + } + open val s51: Service51 by lazy { + DefaultService51(s52) + } + open val s52: Service52 by lazy { + DefaultService52(s53) + } + open val s53: Service53 by lazy { + DefaultService53(s54) + } + open val s54: Service54 by lazy { + DefaultService54(s55) + } + open val s55: Service55 by lazy { + DefaultService55(s56) + } + open val s56: Service56 by lazy { + DefaultService56(s57) + } + open val s57: Service57 by lazy { + DefaultService57(s58) + } + open val s58: Service58 by lazy { + DefaultService58(s59) + } + open val s59: Service59 by lazy { + DefaultService59(s60) + } + open val s60: Service60 by lazy { + DefaultService60(s61) + } + open val s61: Service61 by lazy { + DefaultService61(s62) + } + open val s62: Service62 by lazy { + DefaultService62(s63) + } + open val s63: Service63 by lazy { + DefaultService63(s64) + } + open val s64: Service64 by lazy { + DefaultService64(s65) + } + open val s65: Service65 by lazy { + DefaultService65(s66) + } + open val s66: Service66 by lazy { + DefaultService66(s67) + } + open val s67: Service67 by lazy { + DefaultService67(s68) + } + open val s68: Service68 by lazy { + DefaultService68(s69) + } + open val s69: Service69 by lazy { + DefaultService69(s70) + } + open val s70: Service70 by lazy { + DefaultService70(s71) + } + open val s71: Service71 by lazy { + DefaultService71(s72) + } + open val s72: Service72 by lazy { + DefaultService72(s73) + } + open val s73: Service73 by lazy { + DefaultService73(s74) + } + open val s74: Service74 by lazy { + DefaultService74(s75) + } + open val s75: Service75 by lazy { + DefaultService75(s76) + } + open val s76: Service76 by lazy { + DefaultService76(s77) + } + open val s77: Service77 by lazy { + DefaultService77(s78) + } + open val s78: Service78 by lazy { + DefaultService78(s79) + } + open val s79: Service79 by lazy { + DefaultService79(s80) + } + open val s80: Service80 by lazy { + DefaultService80(s81) + } + open val s81: Service81 by lazy { + DefaultService81(s82) + } + open val s82: Service82 by lazy { + DefaultService82(s83) + } + open val s83: Service83 by lazy { + DefaultService83(s84) + } + open val s84: Service84 by lazy { + DefaultService84(s85) + } + open val s85: Service85 by lazy { + DefaultService85(s86) + } + open val s86: Service86 by lazy { + DefaultService86(s87) + } + open val s87: Service87 by lazy { + DefaultService87(s88) + } + open val s88: Service88 by lazy { + DefaultService88(s89) + } + open val s89: Service89 by lazy { + DefaultService89(s90) + } + open val s90: Service90 by lazy { + DefaultService90(s91) + } + open val s91: Service91 by lazy { + DefaultService91(s92) + } + open val s92: Service92 by lazy { + DefaultService92(s93) + } + open val s93: Service93 by lazy { + DefaultService93(s94) + } + open val s94: Service94 by lazy { + DefaultService94(s95) + } + open val s95: Service95 by lazy { + DefaultService95(s96) + } + open val s96: Service96 by lazy { + DefaultService96(s97) + } + open val s97: Service97 by lazy { + DefaultService97(s98) + } + open val s98: Service98 by lazy { + DefaultService98(s99) + } + open val s99: Service99 by lazy { + DefaultService99(s100) + } + open val s100: Service100 by lazy { + DefaultService100(s101) + } + open val s101: Service101 by lazy { + DefaultService101() + } +} + diff --git a/kotlin-lazy/build.gradle.kts b/kotlin-lazy/build.gradle.kts new file mode 100644 index 0000000..d019afd --- /dev/null +++ b/kotlin-lazy/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + kotlin("jvm").version("1.4.31") + application +} + +application { + mainClass.set("io.heapy.klazy.MainKt") +} + +tasks.withType().configureEach { + kotlinOptions.jvmTarget = "11" +} + +repositories { + mavenCentral() +} + +dependencies { + implementation(project(":common")) +} diff --git a/kotlin-lazy/src/main/kotlin/io/heapy/klazy/Main.kt b/kotlin-lazy/src/main/kotlin/io/heapy/klazy/Main.kt new file mode 100644 index 0000000..24ad573 --- /dev/null +++ b/kotlin-lazy/src/main/kotlin/io/heapy/klazy/Main.kt @@ -0,0 +1,20 @@ +package io.heapy.klazy + +import io.heapy.di.service.Service +import io.heapy.di.service.ServiceImpl +import io.heapy.di.service.SubService +import io.heapy.di.service.SubServiceImpl + +fun main() { + println(Main().service.doIt()) +} + +open class Main { + open val service: Service by lazy { + ServiceImpl(subService) + } + + open val subService: SubService by lazy { + SubServiceImpl() + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 6a5540d..d3ad328 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -54,6 +54,9 @@ include("spring-xml-deep") include("spring-scan") include("spring-scan-deep") +include("spring-scan-large") +include("spring-scan-large-deep") + include("quarkus") include("quarkus-deep")