Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LayoutInflater: Opportunistically create views directly for performance
When opening and closing activities in Settings, a significant amount of CPU time is spent performing JNI calls, as reported by simpleperf: 0.39% /system/framework/arm64/boot-framework.oat art_jni_trampoline Reflection in LayoutInflater is responsible for a significant portion of the time spent in the JNI trampoline: 6.08% 0.08% /apex/com.android.art/javalib/arm64/boot.oat art_jni_trampoline | -- art_jni_trampoline | |--12.38%-- java.lang.reflect.Constructor.newInstance | |--0.09%-- [hit in function] | | | |--88.32%-- android.view.LayoutInflater.createView | | | | | |--83.39%-- com.android.internal.policy.PhoneLayoutInflater.onCreateView | | | android.view.LayoutInflater.onCreateView | | | android.view.LayoutInflater.onCreateView | | | android.view.LayoutInflater.createViewFromTag | | | | | | | |--72.73%-- android.view.LayoutInflater.rInflate | | | | | | | | | |--57.90%-- android.view.LayoutInflater.rInflate | | | | | | | | | | | |--94.90%-- android.view.LayoutInflater.inflate | | | | | | android.view.LayoutInflater.inflate | | | | | | |--35.86%-- [hit in function] | | | | | | | | | | | | | |--58.15%-- androidx.preference.PreferenceGroupAdapter.onCreateViewHolder Empirical testing of interacting with ~113 real-world apps reveals that many of the most frequently-inflated views are framework classes: 13486 android.widget.LinearLayout 6930 android.widget.View 6447 android.widget.FrameLayout 5613 android.widget.ViewStub 5608 androidx.constraintlayout.widget.ConstraintLayout 4722 android.widget.TextView 4431 com.google.android.material.textview.MaterialTextView 3570 eu.faircode.email.FixedTextView 3044 android.widget.ImageView 2665 android.widget.RelativeLayout 1694 android.widget.Space 979 androidx.preference.internal.PreferenceImageView 926 androidx.appcompat.view.menu.ActionMenuItemView 884 androidx.appcompat.widget.AppCompatImageView 855 slack.uikit.components.icon.SKIconView 770 android.widget.ProgressBar 743 com.fastaccess.ui.widgets.FontTextView 541 androidx.recyclerview.widget.RecyclerView 442 androidx.appcompat.widget.AppCompatTextView 404 org.mariotaku.twidere.view.MediaPreviewImageView 393 com.moez.QKSMS.common.widget.QkTextView 382 android.widget.Button 365 slack.widgets.core.textview.ClickableLinkTextView 365 slack.uikit.components.avatar.SKAvatarView 352 com.google.android.libraries.inputmethod.widgets.SoftKeyView 351 com.android.launcher3.BubbleTextView 315 slack.widgets.core.viewcontainer.SingleViewContainer 315 slack.widgets.core.textview.MaxWidthTextView 313 androidx.constraintlayout.widget.Barrier 302 slack.app.ui.widgets.ReactionsLayout 302 slack.app.ui.messages.widgets.MessageLayout 302 slack.app.ui.messages.widgets.MessageHeader 290 com.android.launcher3.views.DoubleShadowBubbleTextView 285 com.android.internal.widget.CachingIconView 265 android.widget.ImageButton 262 androidx.constraintlayout.widget.Guideline 249 org.thoughtcrime.securesms.components.emoji.EmojiTextView 234 com.google.android.libraries.inputmethod.widgets.AutoSizeTextView 232 com.android.internal.widget.RemeasuringLinearLayout 228 android.view.ViewStub 227 android.app.ViewStub 226 android.webkit.ViewStub 221 im.vector.app.core.ui.views.ShieldImageView 219 androidx.constraintlayout.widget.Group 214 androidx.coordinatorlayout.widget.CoordinatorLayout 204 androidx.appcompat.widget.ContentFrameLayout All framework classes seen: 13486 android.widget.LinearLayout 6930 android.widget.View 6447 android.widget.FrameLayout 5613 android.widget.ViewStub 4722 android.widget.TextView 3044 android.widget.ImageView 2665 android.widget.RelativeLayout 1694 android.widget.Space 770 android.widget.ProgressBar 382 android.widget.Button 265 android.widget.ImageButton 228 android.view.ViewStub 227 android.app.ViewStub 226 android.webkit.ViewStub 145 android.widget.Switch 117 android.widget.DateTimeView 86 android.widget.Toolbar 68 android.widget.HorizontalScrollView 67 android.widget.ScrollView 65 android.widget.NotificationHeaderView 65 android.webkit.NotificationHeaderView 65 android.view.NotificationHeaderView 65 android.app.NotificationHeaderView 63 android.webkit.View 63 android.view.View 62 android.app.View 58 android.widget.ListView 50 android.widget.QuickContactBadge 40 android.widget.SeekBar 38 android.widget.CheckBox 16 android.widget.GridLayout 15 android.widget.TableRow 15 android.widget.RadioGroup 15 android.widget.Chronometer 13 android.widget.ViewFlipper 9 android.widget.Spinner 8 android.widget.ViewSwitcher 8 android.widget.TextSwitcher 8 android.widget.SurfaceView 8 android.widget.CheckedTextView 8 android.preference.PreferenceFrameLayout 7 android.widget.TwoLineListItem 5 android.widget.TableLayout 5 android.widget.EditText 3 android.widget.TabWidget 3 android.widget.TabHost 2 android.widget.ZoomButton 2 android.widget.TextureView 2 android.widget.ExpandableListView 2 android.webkit.TextureView 2 android.view.TextureView 2 android.app.TextureView 1 android.widget.WebView 1 android.widget.ViewAnimator 1 android.widget.TextClock 1 android.widget.AutoCompleteTextView 1 android.webkit.WebView 1 android.webkit.SurfaceView 1 android.view.SurfaceView 1 android.app.SurfaceView Unfortunately, replacing reflection with MethodHandle constructors is counter-productive in terms of performance: Constructor direct: create=5 invoke=42 Constructor reflection: create=310 invoke=433 Constructor MethodHandle: create=3283 invoke=3489 Constructor MethodHandle-exact: create=3273 invoke=3453 To reduce the performance impact of slow reflection, we can leverage the fact that the most frequently-inflated classes are from the framework, and hard-code direct constructor references for them in a switch-case block. Reflection will automatically be used as a fallback for custom app views. Test: simpleperf record -a; verify that Constructor.newInstance -> LayoutInflater no longer appears at the top under art_jni_trampoline Change-Id: I8fcc0e05813ff9ecf1eddca3cc6920e747adf4fc
- Loading branch information