patrykandpatrick / vico

A light and extensible chart library for Android.
https://patrykandpatrick.com/vico/wiki
Apache License 2.0
2.07k stars 125 forks source link

XML/Views - showBottomAxis="true" causes memory leak and extreme slow down in the Android Studio Layout Preview #865

Open kroegerama opened 2 weeks ago

kroegerama commented 2 weeks ago

How to reproduce

Use this snippet in your xml layout:

<com.patrykandpatrick.vico.views.cartesian.CartesianChartView
        android:id="@+id/barChart"
        android:layout_width="match_parent"
        android:layout_height="130dp"
        android:layout_marginTop="@dimen/spaceL"
        app:chartHorizontalScrollingEnabled="false"
        app:chartZoomEnabled="false"
        app:horizontalLayout="fullWidth"
        app:layers="column"
        app:previewColumnSeriesCount="1"
        app:previewMaxX="7"
        app:previewMaxY="200"
        app:previewMinX="1"
        app:previewMinY="0"
        app:showBottomAxis="true"
        app:showEndAxis="true"
        app:unscalableEndContentPadding="6dp"
        app:unscalableStartContentPadding="6dp" />

Observed behavior

As soon as I use app:showBottomAxis="true" in my xml layout, Android Studio will start to fill the maximum heap size (I have set it to 16GB currently). Also, the whole editor becomes extremely slow.

Expected behavior

No memory leak 😄

Vico version(s)

2.0.0-alpha.28

Android version(s)

Android Studio Koala | 2024.1.1 Patch 2

Additional information

No response

dmytroreutov commented 2 weeks ago

+1 Have this issue both in AS Layout Preview and as OOM crash on device Without app:showBottomAxis="true" column chart is rendered ok. Although cannot use bottom labels and valueFormatter

Lib version:

com.patrykandpatrick.vico:views:2.0.0-alpha.28

Providing stack trace:

java.lang.OutOfMemoryError: Failed to allocate a 16 byte allocation with 37568 free bytes and 36KB until OOM, target footprint 268435456, growth limit 268435456; giving up on allocation because <1% of heap free after GC.
    at java.lang.Double.valueOf(Double.java:643)
    at com.patrykandpatrick.vico.core.cartesian.axis.DefaultHorizontalAxisItemPlacer.getLabelValues(DefaultHorizontalAxisItemPlacer.kt:90)
    at com.patrykandpatrick.vico.core.cartesian.axis.HorizontalAxis.drawUnderLayers(HorizontalAxis.kt:153)
    at com.patrykandpatrick.vico.core.cartesian.axis.HorizontalAxis.drawUnderLayers(HorizontalAxis.kt:153)
    at com.patrykandpatrick.vico.core.cartesian.axis.AxisManager.drawUnderLayers(AxisManager.kt:118)
    at com.patrykandpatrick.vico.core.cartesian.axis.AxisManager.drawUnderLayers(AxisManager.kt:118)
    at com.patrykandpatrick.vico.core.cartesian.CartesianChart.draw-43zNVmo(CartesianChart.kt:246)
    at com.patrykandpatrick.vico.views.cartesian.CartesianChartView.dispatchDraw(CartesianChartView.kt:331)
    at android.view.View.updateDisplayListIfDirty(View.java:23484)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4560)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4533)
    at android.view.View.updateDisplayListIfDirty(View.java:23449)
    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:694)
    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:700)
    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:798)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:5313)
    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4975)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4093)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2718)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9937)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1406)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1415)
    at android.view.Choreographer.doCallbacks(Choreographer.java:1015)
    at android.view.Choreographer.doFrame(Choreographer.java:945)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1389)
    at android.os.Handler.handleCallback(Handler.java:959)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loopOnce(Looper.java:232)
    at android.os.Looper.loop(Looper.java:317)
    at android.app.ActivityThread.main(ActivityThread.java:8592)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)
Gowsky commented 1 week ago

Hi @kroegerama! Thank you for your report. We've identified the problem causing the OOM, and it's not a memory leak. We will fix it in the next release.