Abdelilah El Aissaoui
06/08/2023, 1:17 PMRobert Jaros
06/08/2023, 1:42 PMAbdelilah El Aissaoui
06/08/2023, 2:02 PMimport androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.renderComposable
var idCounter = 1;
data class Row(val id: Int, val label: String)
fun main() {
var data by mutableStateOf(arrayOf<Row>())
var selected by mutableStateOf<Row?>(null)
renderComposable(rootElementId = "root") {
Div({ classes("container") }) {
Div({ classes("jumbotron") }) {
Div({ classes("row") }) {
Div({ classes("col-md-6") }) {
H1 { Text("Compose HTML") }
}
Div({ classes("col-md-6") }) {
Div({ classes("row") }) {
Button(
{
id("run")
onClick {
println("Click create 1000 rows")
data = buildData(1000)
}
}
) { Text("Create 1,000 rows") }
Button(
{
id("runlots")
onClick {
println("Click create 10_000 rows")
data = buildData(10_000)
}
}
) { Text("Create 10,000 rows") }
Button(
{
id("add")
onClick {
println("Click append 1000 rows")
data += buildData(1000)
}
}
) { Text("Append 1,000 rows") }
Button(
{
id("run")
onClick {
println("Click update every 10th row")
val newData = data.copyOf()
for (i in data.indices step 10) {
val oldData = newData[i]
newData[i] = oldData.copy(label = "${oldData.label} !!!")
}
data = newData
}
}
) { Text("Update every 10th row") }
Button(
{
id("run")
onClick {
println("Click clear")
data = emptyArray()
}
}
) { Text("Clear") }
Button(
{
id("swaprows")
onClick {
println("Click swap rows")
if(data.size > 998) {
val newData = data.copyOf()
newData[1] = data[998]
newData[998] = data[1]
data = newData
}
}
}
) { Text("Swap Rows") }
}
}
}
}
Table({ classes("table", "table-hover", "table-striped", "test-data") }) {
for (item in data) {
Tr({ if (selected?.id == item.id) classes("danger") }) {
Td({ classes("col-md-1") }) { Text(item.id.toString()) }
Td({ classes("col-md-4") }) {
A(attrs = {
onClick {
println("Clicked item $item")
selected = item
}
}) { Text(item.label) }
}
Td({ classes("col-md-1") }) {
A(attrs = { onClick { } }) {
Span({
classes(
"glyphicon",
"glyphicon-remove"
)
})
}
}
Td({ classes("col-md-6") })
}
}
}
Span({ classes("preloadicon", "glyphicon", "glyphicon-remove") })
}
}
}
fun buildData(count: Int): Array<Row> {
return Array<Row>(count, init = {
Row(
idCounter++,
"${adjectives.random()} ${colours.random()} ${nouns.random()}"
)
})
}
val adjectives = arrayOf(
"pretty",
"large",
"big",
"small",
"tall",
"short",
"long",
"handsome",
"plain",
"quaint",
"clean",
"elegant",
"easy",
"angry",
"crazy",
"helpful",
"mushy",
"odd",
"unsightly",
"adorable",
"important",
"inexpensive",
"cheap",
"expensive",
"fancy"
)
val colours = arrayOf("red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange")
val nouns = arrayOf(
"table",
"chair",
"house",
"bbq",
"desk",
"car",
"pony",
"cookie",
"sandwich",
"burger",
"pizza",
"mouse",
"keyboard"
)
Abdelilah El Aissaoui
06/08/2023, 2:03 PMmutableStateListOf
rather than mutableStateOf
+ Array
but it didn't make any difference (at least not obvious)Robert Jaros
06/08/2023, 2:06 PMAbdelilah El Aissaoui
06/08/2023, 2:07 PMAbdelilah El Aissaoui
06/08/2023, 3:02 PMArjan van Wieringen
06/08/2023, 5:41 PMhfhbd
06/08/2023, 8:55 PMrocketraman
06/08/2023, 10:25 PMArjan van Wieringen
06/09/2023, 6:24 AMAbdelilah El Aissaoui
06/09/2023, 8:29 AMThe problem is that we don’t know if the largest time is spent in the compose runtime or maybe in some of your state data structures. Js data structures are hiiiiighly optimized and the V8 runtime even optimized them further. So when using Kotlin collections they don’t leverage these benefits (yet). Although I believe Array maps to the Js array.Even clicking clear to remove all the rows seems to take much longer than it should (it only creates an empty array to replace the previous one), so it's quite likely to be a compose runtime issue
Tuna
06/10/2023, 1:05 PMbuildData
's runtime is almost 0ms. for (item in data)
also finishes long before the 1st item on the list is visible.