Use more efficient collections where possible (#483)

These avoid boxing, virtual calls, or both. Not all usages have been updated, just the easy targets.
This commit is contained in:
Jake Wharton
2024-09-25 09:20:56 -04:00
committed by GitHub
parent 964af72cb5
commit e2f598859e
7 changed files with 41 additions and 28 deletions

View File

@ -1,4 +1,5 @@
[versions]
compose = "1.6.11"
kotlin = "2.0.20"
kotlinx-coroutines = "1.9.0"
mordant = "3.0.0"
@ -11,7 +12,8 @@ kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotl
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
compose-runtime = "org.jetbrains.compose.runtime:runtime:1.6.11"
compose-collection = { module = "org.jetbrains.compose.collection-internal:collection", version.ref = "compose" }
compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose" }
maven-publish-gradlePlugin = "com.vanniktech:gradle-maven-publish-plugin:0.29.0"
dokka-gradlePlugin = "org.jetbrains.dokka:dokka-gradle-plugin:1.9.20"

View File

@ -23,6 +23,7 @@ kotlin {
dependencies {
api libs.compose.runtime
api libs.kotlinx.coroutines.core
implementation libs.compose.collection
implementation libs.finalizationHook
implementation libs.mordant.core
implementation libs.codepoints

View File

@ -1,5 +1,7 @@
package com.jakewharton.mosaic
import androidx.collection.MutableIntList
import androidx.collection.mutableIntListOf
import com.jakewharton.mosaic.ui.AnsiLevel
import com.jakewharton.mosaic.ui.Color
import com.jakewharton.mosaic.ui.TextStyle
@ -39,7 +41,7 @@ internal class TextSurface(
fun appendRowTo(appendable: Appendable, row: Int) {
// Reused heap allocation for building ANSI attributes inside the loop.
val attributes = mutableListOf<Int>()
val attributes = mutableIntListOf()
val rowPixels = rows[row]
var lastPixel = blankPixel
@ -84,12 +86,14 @@ internal class TextSurface(
maybeToggleStyle(Strikethrough, 9, 29)
}
if (attributes.isNotEmpty()) {
attributes.joinTo(
appendable,
separator = ansiSeparator,
prefix = CSI,
postfix = ansiClosingCharacter,
)
appendable.append(CSI)
attributes.forEachIndexed { index, element ->
if (index > 0) {
appendable.append(ansiSeparator)
}
appendable.append(element.toString())
}
appendable.append(ansiClosingCharacter)
attributes.clear() // This list is reused!
}
}
@ -107,7 +111,7 @@ internal class TextSurface(
}
}
private fun MutableList<Int>.addColor(
private fun MutableIntList.addColor(
color: Color,
ansiLevel: AnsiLevel,
select: Int,

View File

@ -1,5 +1,6 @@
package com.jakewharton.mosaic.layout
import androidx.collection.MutableObjectList
import com.jakewharton.mosaic.TextCanvas
import com.jakewharton.mosaic.TextSurface
import com.jakewharton.mosaic.layout.Placeable.PlacementScope
@ -95,7 +96,7 @@ internal class MosaicNode(
val onStaticDraw: (() -> Unit)?,
) : Measurable {
val isStatic get() = onStaticDraw != null
val children = mutableListOf<MosaicNode>()
val children = ArrayList<MosaicNode>()
private val bottomLayer: MosaicNodeLayer = BottomLayer(this)
var topLayer: MosaicNodeLayer = bottomLayer
@ -150,8 +151,9 @@ internal class MosaicNode(
* Append any static [TextSurfaces][TextSurface] to [statics].
* A call to [measureAndPlace] must precede calls to this function.
*/
fun paintStatics(statics: MutableList<TextSurface>, ansiLevel: AnsiLevel) {
for (child in children) {
fun paintStatics(statics: MutableObjectList<TextSurface>, ansiLevel: AnsiLevel) {
for (index in children.indices) {
val child = children[index]
if (isStatic) {
statics += child.paint(ansiLevel)
}

View File

@ -1,5 +1,6 @@
package com.jakewharton.mosaic
import androidx.collection.mutableScatterSetOf
import androidx.compose.runtime.AbstractApplier
import androidx.compose.runtime.BroadcastFrameClock
import androidx.compose.runtime.Composable
@ -176,8 +177,8 @@ internal class MosaicComposition(
private val applyObserverHandle: ObserverHandle
private val readingStatesOnLayout = mutableSetOf<Any>()
private val readingStatesOnDraw = mutableSetOf<Any>()
private val readingStatesOnLayout = mutableScatterSetOf<Any>()
private val readingStatesOnDraw = mutableScatterSetOf<Any>()
private val layoutBlockStateReadObserver: (Any) -> Unit = { readingStatesOnLayout.add(it) }
private val drawBlockStateReadObserver: (Any) -> Unit = { readingStatesOnDraw.add(it) }

View File

@ -1,5 +1,6 @@
package com.jakewharton.mosaic
import androidx.collection.mutableObjectListOf
import com.jakewharton.mosaic.layout.MosaicNode
import com.jakewharton.mosaic.ui.AnsiLevel
import kotlin.time.ExperimentalTime
@ -37,20 +38,18 @@ internal class DebugRendering(
appendLine(node)
appendLine()
val statics = mutableObjectListOf<TextSurface>()
try {
val statics = ArrayList<TextSurface>()
.also { node.paintStatics(it, ansiLevel) }
.map { it.render() }
node.paintStatics(statics, ansiLevel)
if (statics.isNotEmpty()) {
appendLine("STATIC:")
for (static in statics) {
appendLine(static)
statics.forEach { static ->
appendLine(static.render())
}
appendLine()
}
} catch (t: Throwable) {
failed = true
appendLine("STATIC:")
appendLine(t.stackTraceToString())
}
@ -73,7 +72,7 @@ internal class AnsiRendering(
private val ansiLevel: AnsiLevel = AnsiLevel.TRUECOLOR,
) : Rendering {
private val stringBuilder = StringBuilder(100)
private val staticSurfaces = ArrayList<TextSurface>()
private val staticSurfaces = mutableObjectListOf<TextSurface>()
private var lastHeight = 0
override fun render(node: MosaicNode): CharSequence {
@ -98,11 +97,15 @@ internal class AnsiRendering(
}
}
node.paintStatics(staticSurfaces, ansiLevel)
for (staticSurface in staticSurfaces) {
appendSurface(staticSurface)
staticSurfaces.let { staticSurfaces ->
node.paintStatics(staticSurfaces, ansiLevel)
if (staticSurfaces.isNotEmpty()) {
staticSurfaces.forEach { staticSurface ->
appendSurface(staticSurface)
}
staticSurfaces.clear()
}
}
staticSurfaces.clear()
val surface = node.paint(ansiLevel)
appendSurface(surface)

View File

@ -116,9 +116,9 @@ public class AnnotatedString internal constructor(
}
}
private val text: StringBuilder = StringBuilder(capacity)
private val spanStyles: MutableList<MutableRange<SpanStyle>> = mutableListOf()
private val styleStack: MutableList<MutableRange<out Any>> = mutableListOf()
private val text = StringBuilder(capacity)
private val spanStyles = ArrayList<MutableRange<SpanStyle>>()
private val styleStack = ArrayList<MutableRange<out Any>>()
/**
* Create an [Builder] instance using the given [String].