Status Update
Comments
cl...@google.com <cl...@google.com>
ro...@gmail.com <ro...@gmail.com> #2
Branch: androidx-main
commit a330c0d3bcdd41326f37968a60e6084ad4a2e32c
Author: Chet Haase <chet@google.com>
Date: Wed Jul 05 07:26:46 2023
Convert APIs using PointF to use Float instead
PointF is a convenient mechanism for passing around x.y values
representing 2D points. But there are downsides, including:
- Converting to PointF: You may not have the data in PointF form
to begin with, so using an API which takes PointF requires converting
the data to that form (including allocating a PointF object every time)
- Mutability: Point structures can be mutated internally, causing
unpredictability in what that mutation means. Should the library
react to those changes? Ignore them? Do defensive copies (requiring
even more allocations)? Using primitive types like Float make the
behavior more obvious (by making the data inherently immutable).
- Allocations: Whenever we use object types, there are necessarily
allocations on the Java heap for them. This puts pressure on the GC
at both allocation and collection time. Given the amount of points
being passed around (especially at morph creation time, when curves
are being split and created), this causes a lot of PointF objects to
be allocated (even temporarily). Using Float avoids that problem.
Also fixed bug with unclosed paths causing discontinuity at the
start/end point.
Bug: 276466399
Bug: 290254314
Test: integration and unit tests pass
Relnote: PointF parameters changed to Float pairs
Change-Id: Id4705d27c7be31b26ade8186b99fffe2e2f8450e
M graphics/graphics-shapes/api/current.txt
M graphics/graphics-shapes/api/restricted_current.txt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicShapeTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonMeasureTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/RoundedPolygonTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/ShapesTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/TestUtils.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Cubic.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/CubicShape.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FeatureMapping.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FloatMapping.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Morph.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/PolygonMeasure.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/RoundedPolygon.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Shapes.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Utils.kt
M graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/DebugDraw.kt
M graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/ShapeEditor.kt
M graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/MaterialShapes.kt
ro...@gmail.com <ro...@gmail.com> #3
ap...@google.com <ap...@google.com> #4
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.graphics:graphics-shapes:1.0.0-alpha04
ro...@gmail.com <ro...@gmail.com> #5
ae...@google.com <ae...@google.com>
ap...@google.com <ap...@google.com> #6
Branch: androidx-master-dev
commit dc602125a9e5fc15a37ba4fa7610998a94ead29f
Author: Andrey Kulikov <andreykulikov@google.com>
Date: Fri Sep 25 21:14:09 2020
Do less work in SubcomposeLayout when subcompose called with the same lambda
If the lambda object for the slot didn't change and there were no pending recompositons we can skip the whole subcompositions invocation as it will result in unchanged tree. Starting subcomposition is a heavy weight operation so this change allows to improve the measure benchmarks for LazyColumn scrolling by 88 percents.
To achieve it I added a hasPendingChanges() method for Composition class.
Bug: 168293643
Bug: 167972292
Bug: 165028371
Relnote: The scrolling performance of LazyColumn/Row is improved by doing less work in subcomposition on every scroll. The new hasInvalidations() method was added for Composition class. hasPendingChanges() method from Recomposer was renamed to hasInvalidations()
Test: This is not changing the behavior so I can't cover it with a unit test, but it dramatically improves the benchmark. So if this optimization will stop working in the future we will get a regression.
Change-Id: Ib2f324dd6845fd83321e0d4f3fa6e502c346dbc3
M compose/runtime/runtime/api/current.txt
M compose/runtime/runtime/api/public_plus_experimental_current.txt
M compose/runtime/runtime/api/restricted_current.txt
M compose/runtime/runtime/src/androidAndroidTest/kotlin/androidx/compose/runtime/AmbientTests.kt
M compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
M compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
M compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.kt
M compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.kt
M compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/Wrapper.kt
M compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
M ui/ui-test/src/androidMain/kotlin/androidx/ui/test/android/ComposeIdlingResource.kt
M ui/ui-test/src/androidMain/kotlin/androidx/ui/test/android/CompositionAwaiter.kt
M ui/ui-test/src/desktopMain/kotlin/androidx/ui/test/DesktopComposeTestRule.kt
an...@google.com <an...@google.com> #7
One more way to optimize it is to add Modifier.drawLayer() directly on a LazyColumn item so it is cheaper to offset such items(feature request to do it automatically:
In your specific example you will need to add Modifier.drawLayer() for ConstraintLayout here
I will close the bug as fixed for now, Please feel free to comment again if after migrating to alpha05 and adding Modifier.drawLayer() for an item the scrolling performance is still unacceptable. Thanks!
ro...@gmail.com <ro...@gmail.com> #8
Hi, I just tested with Modifiler.drawLayer
added arround a wrappning Column
(tested with Row
/Column
version). This didn't make any difference, but as you mention in your previous post, the big optimization (88%, I read) is about to come in alpha05
, right? And I assume there isn't much difference in performance between using Row
/Column
and ConstraintLayout
(unlike nested LinearLayout
and ConstraintLayout
for views)? Correct me if I'm wrong.
Thanks a lot, looking forward to alpha05! ;)
ro...@gmail.com <ro...@gmail.com> #9
As for re-composition, yes, when I scroll I can see in Logcat
that I'm getting the message I added in the composable body several times (probably it's for each item that's coming into view).
And my Wallpost class is defined like this (you can also check the sample project I attached in the beginning of the discussion -
package com.example.wpcomposable
import com.example.wpcomposable.utils.DateTimeUtils
import java.util.*
import kotlin.collections.ArrayList
import kotlin.time.ExperimentalTime
data class Wallpost(
var id: String = "",
var content: String ="",
var datePosted: Date = Date(),
var username: String = "",
var comments: ArrayList<WallpostComment> = ArrayList(),
var liked: Boolean = false
) {
val headerText: String get() {
return "${this.username} on ${this.datePosted}"
}
val linksText: String get() {
return "Show previous comments (${this.comments.size} of 5) ---- Reply ----"
}
@ExperimentalTime
val timeEllapsed: String get() {
return DateTimeUtils.periodFromNowToString(this.datePosted)
}
}
an...@google.com <an...@google.com> #10
Columns and Row are currently a bit more performant than ConstraintLayout. So I would suggest to keep the version with Columns, add Modifier.drawLayer() on a first layout inside the item and wait for alpha05. Feel free to share you findings once you try it when this version will be released.
Thanks
ro...@gmail.com <ro...@gmail.com> #11
Thanks, for now it seems Modifier.drawLayer
doesn't improve things much - as you suggested I added at the top level of the composable body another wrapper Column
with this modifier. But I'm looking forward to alpha05
and will write back as soon as I've tested with it. :)
ro...@gmail.com <ro...@gmail.com> #12
I tried alpha06
, there's definitely improvement. But still scroll speed is far from that of a RecyclerView
. I can no longer consider it "freezing", but it's laggy when scrolling a little bit faster. I understand it's probably too early to measure the final version's performance, so I can comment again let's say after some last beta or RC version. ;) Thanks!
Description
That original XML view is ConstraintLayout so initially I migrated it to the equivalent ConstraintLayout composable. I also tried Row/Column approach, too. Both versions can be found in the links below. The performance issue is expressed in slow scrolling - the initial scroll seems to freeze for a few seconds before moving just to the second item (in total I have 128 items). So I think there's also a problem with scroll speed too, that is, the amount of views which are scrolled with single finger gesture.
Compared to the RecyclerView approach, even when I do fast scrolling everything is smooth and a single scroll goes through a lot more items in total (arround 20-30 items).
---
Setup information:
Jetpack compose 0.1.0-dev16
Phone: Nexus5X
Android 8.1 Oreo
Android Studio 4.2, latest Canary build
---
Following a discussion on #compose channel in Slack, I'm posting relevant code:
The item which is repeated, here are both ConstraintLayout and Row/Column versions:
ConstraintLayout -
Row/Column -
And the custom composables which are used (button and card image):
---
In the attachments you can find the images uesd: no_avatar.png is used in the RoundedImage composable, whereas user.xml is used with the standard Image composable as vector resource.