kotlin-styled-next/src/jsTest/kotlin/benchmark/InjectCssNPlusOne.kt (95 lines of code) (raw):

package benchmark import TestScope import addCss import kotlinx.css.CssBuilder import kotlinx.css.height import kotlinx.css.px import kotlinx.css.width import measureTimeJS import react.Props import react.dom.flushSync import react.fc import styled.GlobalStyles import styled.css import styled.sheets.CSSOMSheet import styled.sheets.RemoveMode import styled.sheets.RuleType import styled.styledDiv import web.dom.document import kotlin.random.Random import kotlin.test.Test import kotlin.time.Duration class InjectCssNPlusOne : BenchmarkBase() { private fun TestScope.preloadElements(n: Int) { val component = fc<Props> { val random = Random(152) (1..n).forEach { styledDiv { css { height = 100.px width = 100.px } addCss(it, random) } } } flushSync { getRootInfo().renderComponent(component) } assertChildrenCount(n) assertCssNotEmpty() } /** * Measure performance of style recalculation caused by CSS injection. * This metric becomes more important for pages with big and complex DOM and CSSOM. */ private suspend fun TestScope.injectRulesOneByOne(): Duration { val duration = measureTimeJS { repeat(100) { GlobalStyles.scheduleToInject(".dummy_rule$it", CssBuilder().apply { height = 0.px }) GlobalStyles.injectScheduled() document.body.scrollTop += 1 } } clear() return duration } @Test fun injectRulesOneByOne500Elements() = runBenchmark("injectRulesOneByOne500Elements") { preloadElements(500) injectRulesOneByOne() } @Test fun injectRulesOneByOne1000Elements() = runBenchmark("injectRulesOneByOne1000Elements") { preloadElements(1000) injectRulesOneByOne() } @Test fun injectRulesOneByOne2000Elements() = runBenchmark("injectRulesOneByOne2000Elements") { preloadElements(2000) injectRulesOneByOne() } private fun disableSheetPartitioning() { GlobalStyles.sheet = CSSOMSheet(RuleType.REGULAR, RemoveMode.Instantly, maxRulesPerSheet = null) } private fun enableSheetPartitioning() { GlobalStyles.sheet = CSSOMSheet(RuleType.REGULAR, RemoveMode.Instantly) } private fun runBenchmarkWithoutPartitioning( name: String, repeat: Int = 5, run: suspend TestScope.() -> Duration ) { disableSheetPartitioning() runBenchmark(name, repeat, run) enableSheetPartitioning() } @Test fun injectRulesOneByOne200Elements_partitioningDisabled() = runBenchmarkWithoutPartitioning("injectRulesOneByOne500Elements_partitioningDisabled") { preloadElements(200) injectRulesOneByOne() } @Test fun injectRulesOneByOne500Elements_partitioningDisabled() = runBenchmarkWithoutPartitioning("injectRulesOneByOne1000Elements_partitioningDisabled") { preloadElements(500) injectRulesOneByOne() } }