From d7e0b960827949cea615ebcf0dbf6b140c4aa4a9 Mon Sep 17 00:00:00 2001 From: jafu888 Date: Mon, 22 Aug 2022 15:26:42 -0700 Subject: [PATCH 1/3] perf check --- .../widget/ConstraintLayout.java | 13 +- .../widget/ConstraintLayoutPerformance.java | 246 +++++++++++++++++- .../constraintlayout/core/LinearSystem.java | 2 +- .../constraintlayout/core/Metrics.java | 15 +- .../core/widgets/analyzer/BasicMeasure.java | 10 +- .../app/src/main/AndroidManifest.xml | 1 + .../app/CheckPerformanceMetric.java | 61 +++++ .../constraint/app/VerificationActivity.java | 7 +- .../app/src/main/res/drawable/star8.xml | 2 +- .../app/src/main/res/layout/perf_010.xml | 163 ++++++++++++ .../app/src/main/res/layout/perf_020.xml | 81 ++++++ .../app/src/main/res/layout/perf_030.xml | 121 +++++++++ 12 files changed, 695 insertions(+), 27 deletions(-) create mode 100644 projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/CheckPerformanceMetric.java create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_010.xml create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_020.xml create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_030.xml diff --git a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java index 96f348c68..8f28d0668 100644 --- a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java +++ b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java @@ -567,7 +567,6 @@ public class ConstraintLayout extends ViewGroup { private static final boolean USE_CONSTRAINTS_HELPER = true; private static final boolean DEBUG = LinearSystem.FULL_DEBUG; private static final boolean DEBUG_DRAW_CONSTRAINTS = false; - private static final boolean MEASURE = false; private static final boolean OPTIMIZE_HEIGHT_CHANGE = false; SparseArray mChildrenByIds = new SparseArray<>(); @@ -741,10 +740,10 @@ public final void measure(ConstraintWidget widget, return; } - long startMeasure; + long startMeasure = 0; long endMeasure; - if (MEASURE) { + if (mMetrics != null) { startMeasure = System.nanoTime(); } @@ -1008,11 +1007,9 @@ && isSimilarSpec(widget.getLastVerticalMeasureSpec(), measure.measuredHeight = height; measure.measuredHasBaseline = hasBaseline; measure.measuredBaseline = baseline; - if (MEASURE) { + if (mMetrics != null) { endMeasure = System.nanoTime(); - if (mMetrics != null) { - mMetrics.measuresWidgetsDuration += (endMeasure - startMeasure); - } + mMetrics.measuresWidgetsDuration += (endMeasure - startMeasure); } } @@ -1736,6 +1733,7 @@ protected void resolveSystem(ConstraintWidgetContainer layout, heightSize -= paddingHeight; setSelfDimensionBehaviour(layout, widthMode, widthSize, heightMode, heightSize); + layout.measure(optimizationLevel, widthMode, widthSize, heightMode, heightSize, mLastMeasureWidth, mLastMeasureHeight, paddingX, paddingY); } @@ -1869,6 +1867,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mLayoutWidget.updateHierarchy(); } } + mLayoutWidget.fillMetrics(mMetrics); resolveSystem(mLayoutWidget, mOptimizationLevel, widthMeasureSpec, heightMeasureSpec); resolveMeasuredDimension(widthMeasureSpec, heightMeasureSpec, diff --git a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutPerformance.java b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutPerformance.java index 32a50ac04..c2c6b5151 100644 --- a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutPerformance.java +++ b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutPerformance.java @@ -1,2 +1,246 @@ -package androidx.constraintlayout.widget;public class ConstraintLayoutPerformance { +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.constraintlayout.widget; + +import android.annotation.SuppressLint; +import android.util.Log; + +import androidx.constraintlayout.core.Metrics; + +import java.util.ArrayList; + +public class ConstraintLayoutPerformance { + private final Metrics mMetrics = new Metrics(); + ConstraintLayout mConstraintLayout; + + /** + * Measure performance information about ConstraintLayout + * + * @param constraintLayout + */ + public ConstraintLayoutPerformance(ConstraintLayout constraintLayout) { + attach(constraintLayout); + } + public void attach(ConstraintLayout constraintLayout){ + constraintLayout.fillMetrics(mMetrics); + mConstraintLayout = constraintLayout; + } + + public void detach() { + if (mConstraintLayout != null) { + mConstraintLayout.fillMetrics(null); + } + } + + public void reset() { + mMetrics.reset(); + } + + @SuppressLint("LogConditional") + public void logSummary(String tag) { + Log.v(tag, "CL Perf: -------------- "); + + Log.v(tag, "CL Perf: measuresWidgetsDuration = " + getMeasuresWidgetsDuration() * 1E-6f + "ms"); + Log.v(tag, "CL Perf: measuresLayoutDuration = " + getMeasuresLayoutDuration() * 1E-6f + "ms"); + Log.v(tag, "CL Perf: measuredWidgets = " + getMeasuredWidgets()); + Log.v(tag, "CL Perf: layouts = " + getLayouts()); + Log.v(tag, "CL Perf: LastTableSize = " + getLastTableSize()); + Log.v(tag, "CL Perf: Constraints = " + getConstraints()); + Log.v(tag, "CL Perf: NonresolvedWidgets = " + getNonresolvedWidgets()); + Log.v(tag, "CL Perf: MaxVariables = " + getMaxVariables()); + Log.v(tag, "CL Perf: LinearSolved = " + getLinearSolved()); + Log.v(tag, "CL Perf: Errors = " + getErrors()); + Log.v(tag, "CL Perf: MinimizeGoal = " + getMinimizeGoal()); + Log.v(tag, "CL Perf: MaxRows = " + getMaxRows()); + Log.v(tag, "CL Perf: Optimize = " + getOptimize()); + Log.v(tag, "CL Perf: AdditionalMeasures = " + getAdditionalMeasures()); + Log.v(tag, "CL Perf: Minimize = " + getMinimize()); + + + Log.v(tag, "CL Perf: getResolvedWidgets = " + getResolvedWidgets()); + Log.v(tag, "CL Perf: getGraphSolved = " + getGraphSolved()); + Log.v(tag, "CL Perf: Variables = " + getVariables()); + Log.v(tag, "CL Perf: MeasuredMatchWidgets = " + getMeasuredMatchWidgets()); + Log.v(tag, "CL Perf: Measures = " + getMeasures()); + Log.v(tag, "CL Perf: Measures = " + getMeasures()); + Log.v(tag, "CL Perf: Simpleconstraints = " + getSimpleconstraints()); + + + Log.v(tag, "CL Perf: MeasuresWrap = " + getMeasuresWrap()); + Log.v(tag, "CL Perf: MeasuresWrapInfeasible = " + getMeasuresWrapInfeasible()); + Log.v(tag, "CL Perf: DetermineGroups = " + getDetermineGroups()); + Log.v(tag, "CL Perf: InfeasibleDetermineGroups = " + getInfeasibleDetermineGroups()); + Log.v(tag, "CL Perf: Grouping = " + getGrouping()); + + } + + public long getMeasuresWidgetsDuration() { + return mMetrics.measuresWidgetsDuration; + } + + public long getMeasuresLayoutDuration() { + return mMetrics.measuresLayoutDuration; + } + + public long getMeasuredWidgets() { + return mMetrics.measuredWidgets; + } + + public long getMeasuredMatchWidgets() { + return mMetrics.measuredMatchWidgets; + } + + public long getMeasures() { + return mMetrics.measures; + } + + public long getAdditionalMeasures() { + return mMetrics.additionalMeasures; + } + + public long getResolutions() { + return mMetrics.resolutions; + } + + public long getTableSizeIncrease() { + return mMetrics.tableSizeIncrease; + } + + public long getMinimize() { + return mMetrics.minimize; + } + + public long getConstraints() { + return mMetrics.constraints; + } + + public long getSimpleconstraints() { + return mMetrics.simpleconstraints; + } + + public long getOptimize() { + return mMetrics.optimize; + } + + public long getIterations() { + return mMetrics.iterations; + } + + public long getPivots() { + return mMetrics.pivots; + } + + public long getBfs() { + return mMetrics.bfs; + } + + public long getVariables() { + return mMetrics.variables; + } + + public long getErrors() { + return mMetrics.errors; + } + + public long getSlackvariables() { + return mMetrics.slackvariables; + } + + public long getExtravariables() { + return mMetrics.extravariables; + } + + public long getMaxTableSize() { + return mMetrics.maxTableSize; + } + + public long getFullySolved() { + return mMetrics.fullySolved; + } + + public long getGraphOptimizer() { + return mMetrics.graphOptimizer; + } + + public long getGraphSolved() { + return mMetrics.graphSolved; + } + + public long getLinearSolved() { + return mMetrics.linearSolved; + } + + public long getResolvedWidgets() { + return mMetrics.resolvedWidgets; + } + + public long getMinimizeGoal() { + return mMetrics.minimizeGoal; + } + + public long getMaxVariables() { + return mMetrics.maxVariables; + } + + public long getMaxRows() { + return mMetrics.maxRows; + } + + + + public long getNonresolvedWidgets() { + return mMetrics.nonresolvedWidgets; + } + + public ArrayList ProblematicLayouts() { + return mMetrics.problematicLayouts; + } + + public long getLastTableSize() { + return mMetrics.lastTableSize; + } + + public long getWidgets() { + return mMetrics.widgets; + } + + public long getMeasuresWrap() { + return mMetrics.measuresWrap; + } + + public long getMeasuresWrapInfeasible() { + return mMetrics.measuresWrapInfeasible; + } + + public long getInfeasibleDetermineGroups() { + return mMetrics.infeasibleDetermineGroups; + } + + public long getDetermineGroups() { + return mMetrics.determineGroups; + } + + public long getLayouts() { + return mMetrics.layouts; + } + + public long getGrouping() { + return mMetrics.grouping; + } + + } diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/LinearSystem.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/LinearSystem.java index 3b29b0ab9..71695a40a 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/LinearSystem.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/LinearSystem.java @@ -31,7 +31,7 @@ public class LinearSystem { public static final boolean FULL_DEBUG = false; public static final boolean DEBUG = false; private static final boolean DO_NOT_USE = false; - public static final boolean MEASURE = false; + // public static final boolean MEASURE = false; private static final boolean DEBUG_CONSTRAINTS = FULL_DEBUG; diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/Metrics.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/Metrics.java index 0fb822b4e..24982967e 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/Metrics.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/Metrics.java @@ -49,11 +49,11 @@ public class Metrics { public long minimizeGoal; public long maxVariables; public long maxRows; - public long centerConnectionResolved; - public long matchConnectionResolved; - public long chainConnectionResolved; - public long barrierConnectionResolved; - public long oldresolvedWidgets; +// public long centerConnectionResolved; +// public long matchConnectionResolved; +// public long chainConnectionResolved; +// public long barrierConnectionResolved; +// public long oldresolvedWidgets; public long nonresolvedWidgets; public ArrayList problematicLayouts = new ArrayList<>(); public long lastTableSize; @@ -139,12 +139,7 @@ public void reset() { graphOptimizer = 0; graphSolved = 0; resolvedWidgets = 0; - oldresolvedWidgets = 0; nonresolvedWidgets = 0; - centerConnectionResolved = 0; - matchConnectionResolved = 0; - chainConnectionResolved = 0; - barrierConnectionResolved = 0; problematicLayouts.clear(); } } diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/analyzer/BasicMeasure.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/analyzer/BasicMeasure.java index 09631a618..59c055aed 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/analyzer/BasicMeasure.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/analyzer/BasicMeasure.java @@ -150,8 +150,8 @@ private void solveLinearSystem(ConstraintWidgetContainer layout, int pass, int w, int h) { - long startLayout; - if (LinearSystem.MEASURE) { + long startLayout = 0; + if (layout.mMetrics != null) { startLayout = System.nanoTime(); } @@ -168,7 +168,7 @@ private void solveLinearSystem(ConstraintWidgetContainer layout, } mConstraintWidgetContainer.setPass(pass); mConstraintWidgetContainer.layout(); - if (LinearSystem.MEASURE && layout.mMetrics != null) { + if (layout.mMetrics != null) { long endLayout = System.nanoTime(); layout.mMetrics.measuresLayoutDuration += (endLayout - startLayout); } @@ -283,7 +283,7 @@ public long solverMeasure(ConstraintWidgetContainer layout, if (childCount > 0) { measureChildren(layout); } - if (LinearSystem.MEASURE) { + if (layout.mMetrics != null) { layoutTime = System.nanoTime(); } @@ -445,7 +445,7 @@ public long solverMeasure(ConstraintWidgetContainer layout, } layout.setOptimizationLevel(optimizations); } - if (LinearSystem.MEASURE) { + if (layout.mMetrics != null) { layoutTime = (System.nanoTime() - layoutTime); } return layoutTime; diff --git a/projects/MotionLayoutVerification/app/src/main/AndroidManifest.xml b/projects/MotionLayoutVerification/app/src/main/AndroidManifest.xml index c27f10719..00e764d5e 100644 --- a/projects/MotionLayoutVerification/app/src/main/AndroidManifest.xml +++ b/projects/MotionLayoutVerification/app/src/main/AndroidManifest.xml @@ -46,6 +46,7 @@ + diff --git a/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/CheckPerformanceMetric.java b/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/CheckPerformanceMetric.java new file mode 100644 index 000000000..e889f88bc --- /dev/null +++ b/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/CheckPerformanceMetric.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.support.constraint.app; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.View; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.constraintlayout.motion.widget.Debug; +import androidx.constraintlayout.motion.widget.MotionLayout; +import androidx.constraintlayout.motion.widget.TransitionAdapter; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.ConstraintLayoutPerformance; + +/** + * Test transitionToState bug + */ +public class CheckPerformanceMetric extends AppCompatActivity { + private static final String TAG = "CheckPerformanceMetric"; + String layout_name; + ConstraintLayout mConstraintLayout; + ConstraintLayoutPerformance performance; + @Override + protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle extra = getIntent().getExtras(); + String prelayout = extra.getString(Utils.KEY); + layout_name = prelayout; + Context ctx = getApplicationContext(); + int id = ctx.getResources().getIdentifier(prelayout, "layout", ctx.getPackageName()); + setContentView(id); + mConstraintLayout = Utils.findConstraintLayout(this); + performance = new ConstraintLayoutPerformance(mConstraintLayout); + mConstraintLayout.addOnLayoutChangeListener(this::foo); + mConstraintLayout.postDelayed(this::log, 1000); + } + public void foo(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + log(); + } + void log(){ + performance.logSummary("CheckPerformanceMetric"); + } +} diff --git a/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/VerificationActivity.java b/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/VerificationActivity.java index 9ccf3a465..c3fc10dd8 100644 --- a/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/VerificationActivity.java +++ b/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/VerificationActivity.java @@ -100,6 +100,9 @@ public class VerificationActivity extends AppCompatActivity implements View.OnCl activity_map.put("basic_cl_001", CheckDumpJson.class); activity_map.put("basic_cl_002", CheckDumpJson.class); activity_map.put("verification_091", CheckCSTypes.class); + activity_map.put("perf_010", CheckPerformanceMetric.class); + activity_map.put("perf_020", CheckPerformanceMetric.class); + activity_map.put("perf_030", CheckPerformanceMetric.class); // activity_map.put("check_cl01", CheckCLPlugin.class); // activity_map.put("verification_037", RotationToolbar.class); // activity_map.put("verification_038", RotationRotateToToolbar.class); @@ -111,8 +114,8 @@ public class VerificationActivity extends AppCompatActivity implements View.OnCl private static boolean REVERSE = false; - private static final String RUN_FIRST = "verification_091";// (true) ? "verification_801" : "bug_005"; - private final String LAYOUTS_MATCHES = "[bcv].*_.*"; + private static final String RUN_FIRST = "perf_030";// (true) ? "verification_801" : "bug_005"; + private final String LAYOUTS_MATCHES = "[bcpv].*_.*"; private static String SHOW_FIRST = ""; MotionLayout mMotionLayout; diff --git a/projects/MotionLayoutVerification/app/src/main/res/drawable/star8.xml b/projects/MotionLayoutVerification/app/src/main/res/drawable/star8.xml index 00012f6e0..59f84f128 100644 --- a/projects/MotionLayoutVerification/app/src/main/res/drawable/star8.xml +++ b/projects/MotionLayoutVerification/app/src/main/res/drawable/star8.xml @@ -7,5 +7,5 @@ - octagram + diff --git a/projects/MotionLayoutVerification/app/src/main/res/layout/perf_010.xml b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_010.xml new file mode 100644 index 000000000..252be6d60 --- /dev/null +++ b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_010.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/MotionLayoutVerification/app/src/main/res/layout/perf_020.xml b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_020.xml new file mode 100644 index 000000000..b40b42565 --- /dev/null +++ b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_020.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/MotionLayoutVerification/app/src/main/res/layout/perf_030.xml b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_030.xml new file mode 100644 index 000000000..a9836d992 --- /dev/null +++ b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_030.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From 08d7c7c76fd27b14758a51e100bdcb37a2bd53a2 Mon Sep 17 00:00:00 2001 From: John Hoford Date: Fri, 26 Aug 2022 09:09:16 -0700 Subject: [PATCH 2/3] ConstraintLayoutPerformance --- .../widget/ConstraintLayout.java | 21 +- .../widget/ConstraintLayoutPerformance.java | 246 ---------------- .../widget/ConstraintLayoutStatistics.java | 264 ++++++++++++++++++ .../constraintlayout/core/LinearSystem.java | 6 + .../constraintlayout/core/Metrics.java | 106 ++++--- .../core/widgets/ConstraintWidget.java | 5 + .../core/widgets/analyzer/BasicMeasure.java | 1 + .../app/CheckPerformanceMetric.java | 45 ++- .../constraint/app/VerificationActivity.java | 15 +- .../app/src/main/res/layout/perf_001.xml | 22 ++ .../app/src/main/res/layout/perf_002.xml | 21 ++ .../app/src/main/res/layout/perf_003.xml | 22 ++ .../app/src/main/res/layout/perf_004.xml | 33 +++ .../app/src/main/res/layout/perf_005.xml | 37 +++ .../app/src/main/res/layout/perf_030.xml | 16 +- .../app/src/main/res/layout/perf_040.xml | 122 ++++++++ 16 files changed, 669 insertions(+), 313 deletions(-) delete mode 100644 constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutPerformance.java create mode 100644 constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutStatistics.java create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_001.xml create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_002.xml create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_003.xml create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_004.xml create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_005.xml create mode 100644 projects/MotionLayoutVerification/app/src/main/res/layout/perf_040.xml diff --git a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java index 8f28d0668..e74ae497f 100644 --- a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java +++ b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java @@ -744,6 +744,7 @@ public final void measure(ConstraintWidget widget, long endMeasure; if (mMetrics != null) { + mMetrics.mNumberOfMeasures++; startMeasure = System.nanoTime(); } @@ -1786,8 +1787,10 @@ protected void resolveMeasuredDimension(int widthMeasureSpec, @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { long time = 0; - if (DEBUG) { - time = System.currentTimeMillis(); + if (mMetrics != null) { + time = System.nanoTime(); + mMetrics.mChildCount = getChildCount(); + mMetrics.mMeasureCalls ++; } mDirtyHierarchy |= dynamicUpdateConstraints(widthMeasureSpec, heightMeasureSpec); @@ -1825,6 +1828,9 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mLayoutWidget.getWidth(), mLayoutWidget.getHeight(), mLayoutWidget.isWidthMeasuredTooSmall(), mLayoutWidget.isHeightMeasuredTooSmall()); + if (mMetrics != null) { + mMetrics.mMeasureDuration += System.nanoTime() - time; + } return; } if (OPTIMIZE_HEIGHT_CHANGE @@ -1845,6 +1851,9 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mLayoutWidget.getWidth(), mLayoutWidget.getHeight(), mLayoutWidget.isWidthMeasuredTooSmall(), mLayoutWidget.isHeightMeasuredTooSmall()); + if (mMetrics != null) { + mMetrics.mMeasureDuration += System.nanoTime() - time; + } return; } } @@ -1874,8 +1883,11 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mLayoutWidget.getWidth(), mLayoutWidget.getHeight(), mLayoutWidget.isWidthMeasuredTooSmall(), mLayoutWidget.isHeightMeasuredTooSmall()); + if (mMetrics != null) { + mMetrics.mMeasureDuration += System.nanoTime() - time; + } if (DEBUG) { - time = System.currentTimeMillis() - time; + time = System.nanoTime() - time; System.out.println(mLayoutWidget.getDebugName() + " (" + getChildCount() + ") DONE onMeasure width: " + MeasureSpec.toString(widthMeasureSpec) + " height: " + MeasureSpec.toString(heightMeasureSpec) + " => " @@ -2007,6 +2019,9 @@ public void setState(int id, int screenWidth, int screenHeight) { */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (mMetrics != null) { + mMetrics.mNumberOfLayouts++; + } if (DEBUG) { System.out.println(mLayoutWidget.getDebugName() + " onLayout changed: " + changed + " left: " + left + " top: " + top diff --git a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutPerformance.java b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutPerformance.java deleted file mode 100644 index c2c6b5151..000000000 --- a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutPerformance.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package androidx.constraintlayout.widget; - -import android.annotation.SuppressLint; -import android.util.Log; - -import androidx.constraintlayout.core.Metrics; - -import java.util.ArrayList; - -public class ConstraintLayoutPerformance { - private final Metrics mMetrics = new Metrics(); - ConstraintLayout mConstraintLayout; - - /** - * Measure performance information about ConstraintLayout - * - * @param constraintLayout - */ - public ConstraintLayoutPerformance(ConstraintLayout constraintLayout) { - attach(constraintLayout); - } - public void attach(ConstraintLayout constraintLayout){ - constraintLayout.fillMetrics(mMetrics); - mConstraintLayout = constraintLayout; - } - - public void detach() { - if (mConstraintLayout != null) { - mConstraintLayout.fillMetrics(null); - } - } - - public void reset() { - mMetrics.reset(); - } - - @SuppressLint("LogConditional") - public void logSummary(String tag) { - Log.v(tag, "CL Perf: -------------- "); - - Log.v(tag, "CL Perf: measuresWidgetsDuration = " + getMeasuresWidgetsDuration() * 1E-6f + "ms"); - Log.v(tag, "CL Perf: measuresLayoutDuration = " + getMeasuresLayoutDuration() * 1E-6f + "ms"); - Log.v(tag, "CL Perf: measuredWidgets = " + getMeasuredWidgets()); - Log.v(tag, "CL Perf: layouts = " + getLayouts()); - Log.v(tag, "CL Perf: LastTableSize = " + getLastTableSize()); - Log.v(tag, "CL Perf: Constraints = " + getConstraints()); - Log.v(tag, "CL Perf: NonresolvedWidgets = " + getNonresolvedWidgets()); - Log.v(tag, "CL Perf: MaxVariables = " + getMaxVariables()); - Log.v(tag, "CL Perf: LinearSolved = " + getLinearSolved()); - Log.v(tag, "CL Perf: Errors = " + getErrors()); - Log.v(tag, "CL Perf: MinimizeGoal = " + getMinimizeGoal()); - Log.v(tag, "CL Perf: MaxRows = " + getMaxRows()); - Log.v(tag, "CL Perf: Optimize = " + getOptimize()); - Log.v(tag, "CL Perf: AdditionalMeasures = " + getAdditionalMeasures()); - Log.v(tag, "CL Perf: Minimize = " + getMinimize()); - - - Log.v(tag, "CL Perf: getResolvedWidgets = " + getResolvedWidgets()); - Log.v(tag, "CL Perf: getGraphSolved = " + getGraphSolved()); - Log.v(tag, "CL Perf: Variables = " + getVariables()); - Log.v(tag, "CL Perf: MeasuredMatchWidgets = " + getMeasuredMatchWidgets()); - Log.v(tag, "CL Perf: Measures = " + getMeasures()); - Log.v(tag, "CL Perf: Measures = " + getMeasures()); - Log.v(tag, "CL Perf: Simpleconstraints = " + getSimpleconstraints()); - - - Log.v(tag, "CL Perf: MeasuresWrap = " + getMeasuresWrap()); - Log.v(tag, "CL Perf: MeasuresWrapInfeasible = " + getMeasuresWrapInfeasible()); - Log.v(tag, "CL Perf: DetermineGroups = " + getDetermineGroups()); - Log.v(tag, "CL Perf: InfeasibleDetermineGroups = " + getInfeasibleDetermineGroups()); - Log.v(tag, "CL Perf: Grouping = " + getGrouping()); - - } - - public long getMeasuresWidgetsDuration() { - return mMetrics.measuresWidgetsDuration; - } - - public long getMeasuresLayoutDuration() { - return mMetrics.measuresLayoutDuration; - } - - public long getMeasuredWidgets() { - return mMetrics.measuredWidgets; - } - - public long getMeasuredMatchWidgets() { - return mMetrics.measuredMatchWidgets; - } - - public long getMeasures() { - return mMetrics.measures; - } - - public long getAdditionalMeasures() { - return mMetrics.additionalMeasures; - } - - public long getResolutions() { - return mMetrics.resolutions; - } - - public long getTableSizeIncrease() { - return mMetrics.tableSizeIncrease; - } - - public long getMinimize() { - return mMetrics.minimize; - } - - public long getConstraints() { - return mMetrics.constraints; - } - - public long getSimpleconstraints() { - return mMetrics.simpleconstraints; - } - - public long getOptimize() { - return mMetrics.optimize; - } - - public long getIterations() { - return mMetrics.iterations; - } - - public long getPivots() { - return mMetrics.pivots; - } - - public long getBfs() { - return mMetrics.bfs; - } - - public long getVariables() { - return mMetrics.variables; - } - - public long getErrors() { - return mMetrics.errors; - } - - public long getSlackvariables() { - return mMetrics.slackvariables; - } - - public long getExtravariables() { - return mMetrics.extravariables; - } - - public long getMaxTableSize() { - return mMetrics.maxTableSize; - } - - public long getFullySolved() { - return mMetrics.fullySolved; - } - - public long getGraphOptimizer() { - return mMetrics.graphOptimizer; - } - - public long getGraphSolved() { - return mMetrics.graphSolved; - } - - public long getLinearSolved() { - return mMetrics.linearSolved; - } - - public long getResolvedWidgets() { - return mMetrics.resolvedWidgets; - } - - public long getMinimizeGoal() { - return mMetrics.minimizeGoal; - } - - public long getMaxVariables() { - return mMetrics.maxVariables; - } - - public long getMaxRows() { - return mMetrics.maxRows; - } - - - - public long getNonresolvedWidgets() { - return mMetrics.nonresolvedWidgets; - } - - public ArrayList ProblematicLayouts() { - return mMetrics.problematicLayouts; - } - - public long getLastTableSize() { - return mMetrics.lastTableSize; - } - - public long getWidgets() { - return mMetrics.widgets; - } - - public long getMeasuresWrap() { - return mMetrics.measuresWrap; - } - - public long getMeasuresWrapInfeasible() { - return mMetrics.measuresWrapInfeasible; - } - - public long getInfeasibleDetermineGroups() { - return mMetrics.infeasibleDetermineGroups; - } - - public long getDetermineGroups() { - return mMetrics.determineGroups; - } - - public long getLayouts() { - return mMetrics.layouts; - } - - public long getGrouping() { - return mMetrics.grouping; - } - - -} diff --git a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutStatistics.java b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutStatistics.java new file mode 100644 index 000000000..0a3d8a8bc --- /dev/null +++ b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayoutStatistics.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.constraintlayout.widget; + +import android.annotation.SuppressLint; +import android.util.Log; + +import androidx.constraintlayout.core.Metrics; + +import java.text.DecimalFormat; +import java.util.ArrayList; + +/** + * This provide metrics of the complexity of the layout that is being solved. + * The intent is for developers using the too to track the evolution of their UI + * Typically the developer will monitor the computations on every callback of + * mConstraintLayout.addOnLayoutChangeListener(this::callback); + * + */ +public class ConstraintLayoutStatistics { + public final static int NUMBER_OF_LAYOUTS = 1; + public final static int NUMBER_OF_ON_MEASURES= 2; + public final static int NUMBER_OF_CHILD_VIEWS= 3; + public final static int NUMBER_OF_CHILD_MEASURES= 4; + public final static int DURATION_OF_CHILD_MEASURES= 5; + public final static int DURATION_OF_MEASURES = 6; + public final static int DURATION_OF_LAYOUT = 7; + public final static int NUMBER_OF_VARIABLES = 8; + public final static int NUMBER_OF_EQUATIONS = 9; + public final static int NUMBER_OF_SIMPLE_EQUATIONS = 10; + + private final Metrics mMetrics = new Metrics(); + ConstraintLayout mConstraintLayout; + private static int MAX_WORD = 25; + private static final String WORD_PAD = new String(new char[MAX_WORD]).replace('\0', ' '); + + /** + * Measure performance information about ConstraintLayout + * + * @param constraintLayout + */ + public ConstraintLayoutStatistics(ConstraintLayout constraintLayout) { + attach(constraintLayout); + } + + /** + * Copy a layout Stats useful for comparing two stats + * @param copy + */ + public ConstraintLayoutStatistics(ConstraintLayoutStatistics copy) { + mMetrics.copy(copy.mMetrics); + } + + + /** + * Attach to a ConstraintLayout to gather statistics on its layout performance + * @param constraintLayout + */ + public void attach(ConstraintLayout constraintLayout) { + constraintLayout.fillMetrics(mMetrics); + mConstraintLayout = constraintLayout; + } + + /** + * Detach from a ConstraintLayout + */ + public void detach() { + if (mConstraintLayout != null) { + mConstraintLayout.fillMetrics(null); + } + } + + /** + * Clear the current metrics + */ + public void reset() { + mMetrics.reset(); + } + + /** + * Create a copy of the statistics + * @return a copy + */ + public ConstraintLayoutStatistics clone() { + return new ConstraintLayoutStatistics(this); + } + + private String fmt(DecimalFormat df, float val, int sp) { + String s = new String(new char[sp]).replace('\0', ' '); + s = (s + df.format(val)); + return s.substring(s.length() - sp); + } + + /** + * Log a summary of the statistics + * @param tag + */ + public void logSummary(String tag) { + log(tag); + } + + @SuppressLint({"LogConditional"}) + private void log(String tag) { + String value; + StackTraceElement s = new Throwable().getStackTrace()[2]; + + Log.v(tag, "CL Perf: -------- Performance .(" + s.getFileName() + ":" + s.getLineNumber() + ") ------ "); + + DecimalFormat df = new DecimalFormat("###.000"); + + Log.v(tag, log(df, DURATION_OF_CHILD_MEASURES)); + Log.v(tag, log(df, DURATION_OF_LAYOUT)); + Log.v(tag, log(df, DURATION_OF_MEASURES)); + Log.v(tag, log(NUMBER_OF_LAYOUTS)); + Log.v(tag, log( NUMBER_OF_ON_MEASURES)); + Log.v(tag, log(NUMBER_OF_CHILD_VIEWS)); + Log.v(tag, log(NUMBER_OF_CHILD_MEASURES)); + Log.v(tag, log(NUMBER_OF_VARIABLES)); + Log.v(tag, log(NUMBER_OF_EQUATIONS)); + Log.v(tag, log( NUMBER_OF_SIMPLE_EQUATIONS)); + } + + private String log(DecimalFormat df, int param) { + String value = fmt(df, getValue(param) * 1E-6f, 7); + + String title = geName(param); + title = WORD_PAD + title; + title = title.substring(title.length() - MAX_WORD); + title += " = "; + return "CL Perf: " + title + value; + } + private String log(int param) { + String value = Long.toString(this.getValue(param)); + String title = geName(param); + title = WORD_PAD + title; + title = title.substring(title.length() - MAX_WORD); + title += " = "; + return "CL Perf: " + title + value; + } + + private String compare(DecimalFormat df, ConstraintLayoutStatistics relative, int param) { + String value = fmt(df, getValue(param) * 1E-6f, 7); + value += " -> " + fmt(df, relative.getValue(param) * 1E-6f, 7) + "ms"; + String title = geName(param); + title = WORD_PAD + title; + title = title.substring(title.length() - MAX_WORD); + title += " = "; + return "CL Perf: " + title + value; + } + + private String compare(ConstraintLayoutStatistics relative, int param) { + String value = this.getValue(param) + " -> " + relative.getValue(param); + String title = geName(param); + + title = WORD_PAD + title; + title = title.substring(title.length() - MAX_WORD); + title += " = "; + return "CL Perf: " + title + value; + } + + /** + * log a summary of the stats compared to another statics + * @param tag used in Log.v(tag, ...) + * @param prev the previous stats to compare to + */ + @SuppressLint("LogConditional") + public void logSummary(String tag, ConstraintLayoutStatistics prev) { + if (prev == null) { + log(tag); + return; + } + DecimalFormat df = new DecimalFormat("###.000"); + StackTraceElement s = new Throwable().getStackTrace()[1]; + + Log.v(tag, "CL Perf: -= Performance .(" + s.getFileName() + ":" + s.getLineNumber() + ") =- "); + Log.v(tag, compare(df, prev, DURATION_OF_CHILD_MEASURES)); + Log.v(tag, compare(df, prev, DURATION_OF_LAYOUT)); + Log.v(tag, compare(df, prev, DURATION_OF_MEASURES)); + Log.v(tag, compare(prev, NUMBER_OF_LAYOUTS)); + Log.v(tag, compare(prev, NUMBER_OF_ON_MEASURES)); + Log.v(tag, compare(prev, NUMBER_OF_CHILD_VIEWS)); + Log.v(tag, compare(prev, NUMBER_OF_CHILD_MEASURES)); + Log.v(tag, compare(prev, NUMBER_OF_VARIABLES)); + Log.v(tag, compare(prev, NUMBER_OF_EQUATIONS)); + Log.v(tag, compare(prev, NUMBER_OF_SIMPLE_EQUATIONS)); + } + + /** + * get the value of a statistic + * @param type + * @return + */ + public long getValue(int type) { + switch (type) { + case NUMBER_OF_LAYOUTS: + return mMetrics.mNumberOfLayouts; + case NUMBER_OF_ON_MEASURES: + return mMetrics.mMeasureCalls; + case NUMBER_OF_CHILD_VIEWS: + return mMetrics.mChildCount; + case NUMBER_OF_CHILD_MEASURES: + return mMetrics.mNumberOfMeasures; + case DURATION_OF_CHILD_MEASURES: + return mMetrics.measuresWidgetsDuration ; + case DURATION_OF_MEASURES: + return mMetrics.mMeasureDuration; + case DURATION_OF_LAYOUT: + return mMetrics.measuresLayoutDuration; + case NUMBER_OF_VARIABLES: + return mMetrics.mVariables; + case NUMBER_OF_EQUATIONS: + return mMetrics.mEquations; + case NUMBER_OF_SIMPLE_EQUATIONS: + return mMetrics.mSimpleEquations; + } + return 0; + } + + /** get a simple name for a statistic + * + * @param type type of statistic + * @return a camel case + */ + String geName(int type) { + switch (type) { + case NUMBER_OF_LAYOUTS: + return "NumberOfLayouts"; + case NUMBER_OF_ON_MEASURES: + return "MeasureCalls"; + case NUMBER_OF_CHILD_VIEWS: + return "ChildCount"; + case NUMBER_OF_CHILD_MEASURES: + return "ChildrenMeasures"; + case DURATION_OF_CHILD_MEASURES: + return "MeasuresWidgetsDuration "; + case DURATION_OF_MEASURES: + return "MeasureDuration"; + case DURATION_OF_LAYOUT: + return "MeasuresLayoutDuration"; + case NUMBER_OF_VARIABLES: + return "SolverVariables"; + case NUMBER_OF_EQUATIONS: + return "SolverEquations"; + case NUMBER_OF_SIMPLE_EQUATIONS: + return "SimpleEquations"; + } + return ""; + } + +} diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/LinearSystem.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/LinearSystem.java index 71695a40a..760f22841 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/LinearSystem.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/LinearSystem.java @@ -1395,6 +1395,9 @@ public void addSynonym(SolverVariable a, SolverVariable b, int margin) { * @param strength strength used */ public ArrayRow addEquality(SolverVariable a, SolverVariable b, int margin, int strength) { + if (sMetrics != null) { + sMetrics.mSimpleEquations++; + } if (USE_BASIC_SYNONYMS && strength == SolverVariable.STRENGTH_FIXED && b.isFinalValue && a.mDefinitionId == -1) { if (DEBUG_CONSTRAINTS) { @@ -1442,6 +1445,9 @@ public ArrayRow addEquality(SolverVariable a, SolverVariable b, int margin, int * @param value the value we set */ public void addEquality(SolverVariable a, int value) { + if (sMetrics != null) { + sMetrics.mSimpleEquations++; + } if (USE_BASIC_SYNONYMS && a.mDefinitionId == -1) { if (DEBUG_CONSTRAINTS) { System.out.println("=> " + a + " = " + value + " (Synonym)"); diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/Metrics.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/Metrics.java index 24982967e..9590a8d7d 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/Metrics.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/Metrics.java @@ -21,8 +21,8 @@ * Utility class to track metrics during the system resolution */ public class Metrics { - public long measuresWidgetsDuration; - public long measuresLayoutDuration; + public long measuresWidgetsDuration; // time spent in child measures in nanoseconds + public long measuresLayoutDuration; // time spent in child measures in nanoseconds public long measuredWidgets; public long measuredMatchWidgets; public long measures; @@ -49,11 +49,6 @@ public class Metrics { public long minimizeGoal; public long maxVariables; public long maxRows; -// public long centerConnectionResolved; -// public long matchConnectionResolved; -// public long chainConnectionResolved; -// public long barrierConnectionResolved; -// public long oldresolvedWidgets; public long nonresolvedWidgets; public ArrayList problematicLayouts = new ArrayList<>(); public long lastTableSize; @@ -64,6 +59,15 @@ public class Metrics { public long determineGroups; public long layouts; public long grouping; + public int mNumberOfLayouts; // the number of times ConstraintLayout onLayout gets called + public int mNumberOfMeasures; // the number of times child measures gets called + public long mMeasureDuration; // time spent in measure in nanoseconds + public long mChildCount; // number of child Views of ConstraintLayout + public long mMeasureCalls; // number of time CL onMeasure is called + public long mSolverPasses; + public long mEquations; + public long mVariables; + public long mSimpleEquations; // @TODO: add description @Override @@ -77,39 +81,7 @@ public String toString() { + "graphOptimizer: " + graphOptimizer + "\n" + "widgets: " + widgets + "\n" + "graphSolved: " + graphSolved + "\n" - + "linearSolved: " + linearSolved + "\n" -/* - + "measures: " + measures + "\n" - + "additionalMeasures: " + additionalMeasures + "\n" - + "resolutions passes: " + resolutions + "\n" - + "table increases: " + tableSizeIncrease + "\n" - + "maxTableSize: " + maxTableSize + "\n" - + "maxVariables: " + maxVariables + "\n" - + "maxRows: " + maxRows + "\n\n" - + "minimize: " + minimize + "\n" - + "minimizeGoal: " + minimizeGoal + "\n" - + "constraints: " + constraints + "\n" - + "simpleconstraints: " + simpleconstraints + "\n" - + "optimize: " + optimize + "\n" - + "iterations: " + iterations + "\n" - + "pivots: " + pivots + "\n" - + "bfs: " + bfs + "\n" - + "variables: " + variables + "\n" - + "errors: " + errors + "\n" - + "slackvariables: " + slackvariables + "\n" - + "extravariables: " + extravariables + "\n" - + "fullySolved: " + fullySolved + "\n" - + "graphOptimizer: " + graphOptimizer + "\n" - + "resolvedWidgets: " + resolvedWidgets + "\n" - + "oldresolvedWidgets: " + oldresolvedWidgets + "\n" - + "nonresolvedWidgets: " + nonresolvedWidgets + "\n" - + "centerConnectionResolved: " + centerConnectionResolved + "\n" - + "matchConnectionResolved: " + matchConnectionResolved + "\n" - + "chainConnectionResolved: " + chainConnectionResolved + "\n" - + "barrierConnectionResolved: " + barrierConnectionResolved + "\n" - + "problematicsLayouts: " + problematicLayouts + "\n" - */ - ; + + "linearSolved: " + linearSolved + "\n"; } // @TODO: add description @@ -140,6 +112,60 @@ public void reset() { graphSolved = 0; resolvedWidgets = 0; nonresolvedWidgets = 0; + linearSolved = 0; problematicLayouts.clear(); + mNumberOfMeasures = 0; + mNumberOfLayouts = 0; + measuresWidgetsDuration = 0; + measuresLayoutDuration = 0; + mChildCount = 0; + mMeasureDuration = 0; + mMeasureCalls = 0; + mSolverPasses = 0; + mVariables = 0; + mEquations = 0; + mSimpleEquations = 0; + } + + public void copy(Metrics metrics) { + mVariables = metrics.mVariables; + mEquations = metrics.mEquations; + mSimpleEquations = metrics.mSimpleEquations; + mNumberOfMeasures = metrics.mNumberOfMeasures; + mNumberOfLayouts = metrics.mNumberOfLayouts; + mMeasureDuration = metrics.mMeasureDuration; + mChildCount = metrics.mChildCount; + mMeasureCalls = metrics.mMeasureCalls; + measuresWidgetsDuration = metrics.measuresWidgetsDuration; + mSolverPasses = metrics.mSolverPasses; + + measuresLayoutDuration = metrics.measuresLayoutDuration; + measures = metrics.measures; + widgets = metrics.widgets; + additionalMeasures = metrics.additionalMeasures; + resolutions = metrics.resolutions; + tableSizeIncrease = metrics.tableSizeIncrease; + maxTableSize = metrics.maxTableSize; + lastTableSize = metrics.lastTableSize; + maxVariables = metrics.maxVariables; + maxRows = metrics.maxRows; + minimize = metrics.minimize; + minimizeGoal = metrics.minimizeGoal; + constraints = metrics.constraints; + simpleconstraints = metrics.simpleconstraints; + optimize = metrics.optimize; + iterations = metrics.iterations; + pivots = metrics.pivots; + bfs = metrics.bfs; + variables = metrics.variables; + errors = metrics.errors; + slackvariables = metrics.slackvariables; + extravariables = metrics.extravariables; + fullySolved = metrics.fullySolved; + graphOptimizer = metrics.graphOptimizer; + graphSolved = metrics.graphSolved; + resolvedWidgets = metrics.resolvedWidgets; + nonresolvedWidgets = metrics.nonresolvedWidgets; } + } diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/ConstraintWidget.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/ConstraintWidget.java index 8fd3df49b..668d642c9 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/ConstraintWidget.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/ConstraintWidget.java @@ -2865,6 +2865,11 @@ public void addToSolver(LinearSystem system, boolean optimize) { } mResolvedHorizontal = false; mResolvedVertical = false; + if (LinearSystem.sMetrics != null) { + LinearSystem.sMetrics.mEquations = system.getNumEquations(); + LinearSystem.sMetrics.mVariables = system.getNumVariables(); + } + } /** diff --git a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/analyzer/BasicMeasure.java b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/analyzer/BasicMeasure.java index 59c055aed..e81d9cbe9 100644 --- a/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/analyzer/BasicMeasure.java +++ b/constraintlayout/core/src/main/java/androidx/constraintlayout/core/widgets/analyzer/BasicMeasure.java @@ -170,6 +170,7 @@ private void solveLinearSystem(ConstraintWidgetContainer layout, mConstraintWidgetContainer.layout(); if (layout.mMetrics != null) { long endLayout = System.nanoTime(); + layout.mMetrics.mSolverPasses++; layout.mMetrics.measuresLayoutDuration += (endLayout - startLayout); } } diff --git a/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/CheckPerformanceMetric.java b/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/CheckPerformanceMetric.java index e889f88bc..4e1fbb43a 100644 --- a/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/CheckPerformanceMetric.java +++ b/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/CheckPerformanceMetric.java @@ -18,16 +18,14 @@ import android.content.Context; import android.os.Bundle; -import android.util.Log; import android.view.View; +import android.widget.TextView; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.motion.widget.Debug; -import androidx.constraintlayout.motion.widget.MotionLayout; -import androidx.constraintlayout.motion.widget.TransitionAdapter; import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.constraintlayout.widget.ConstraintLayoutPerformance; +import androidx.constraintlayout.widget.ConstraintLayoutStatistics; /** * Test transitionToState bug @@ -36,7 +34,10 @@ public class CheckPerformanceMetric extends AppCompatActivity { private static final String TAG = "CheckPerformanceMetric"; String layout_name; ConstraintLayout mConstraintLayout; - ConstraintLayoutPerformance performance; + ConstraintLayoutStatistics performance; + ConstraintLayoutStatistics prePerformance; + int loop; + @Override protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -47,15 +48,31 @@ protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle sav int id = ctx.getResources().getIdentifier(prelayout, "layout", ctx.getPackageName()); setContentView(id); mConstraintLayout = Utils.findConstraintLayout(this); - performance = new ConstraintLayoutPerformance(mConstraintLayout); + performance = new ConstraintLayoutStatistics(mConstraintLayout); mConstraintLayout.addOnLayoutChangeListener(this::foo); - mConstraintLayout.postDelayed(this::log, 1000); + mConstraintLayout.postDelayed(this::relayout, 1000); + } + + void relayout() { + TextView tv = findViewById(R.id.text); + if (tv != null) { + tv.setText("loop " + (loop++)); + } else { + mConstraintLayout.requestLayout(); + } + mConstraintLayout.postDelayed(this::relayout, 1000); + } + + public void foo(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + log(); + } + + void log() { + Debug.logStack("TAG" ,"CL Perf:", 5); + performance.logSummary("CheckPerformanceMetric", prePerformance); + performance.logSummary("CheckPerformanceMetric"); + prePerformance = performance.clone(); + performance.reset(); } - public void foo(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - log(); - } - void log(){ - performance.logSummary("CheckPerformanceMetric"); - } } diff --git a/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/VerificationActivity.java b/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/VerificationActivity.java index c3fc10dd8..2d7f1151a 100644 --- a/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/VerificationActivity.java +++ b/projects/MotionLayoutVerification/app/src/main/java/android/support/constraint/app/VerificationActivity.java @@ -81,6 +81,7 @@ public class VerificationActivity extends AppCompatActivity implements View.OnCl private static final boolean DEBUG = false; String layout_name; HashMap> activity_map = new HashMap<>(); + HashMap> activity_class = new HashMap<>(); { activity_map.put("verification_400", CheckSharedValues.class); @@ -103,6 +104,8 @@ public class VerificationActivity extends AppCompatActivity implements View.OnCl activity_map.put("perf_010", CheckPerformanceMetric.class); activity_map.put("perf_020", CheckPerformanceMetric.class); activity_map.put("perf_030", CheckPerformanceMetric.class); + activity_map.put("perf_040", CheckPerformanceMetric.class); + activity_class.put("perf_",CheckPerformanceMetric.class); // activity_map.put("check_cl01", CheckCLPlugin.class); // activity_map.put("verification_037", RotationToolbar.class); // activity_map.put("verification_038", RotationRotateToToolbar.class); @@ -691,9 +694,15 @@ public void onFocusChange(View v, boolean hasFocus) { public void launch(String id) { Intent intent; - if (activity_map.containsKey(id)) { - Log.v(TAG, Debug.getLoc() + " launch in activity " + activity_map.get(id).getSimpleName()); - intent = new Intent(this, activity_map.get(id)); + Class to_run = activity_map.get(id); + for (String s1 : activity_class.keySet()) { + if (id.startsWith(s1)) { + to_run = activity_class.get(s1); + } + } + if (to_run != null) { + Log.v(TAG, Debug.getLoc() + " launch in activity " + to_run.getSimpleName()); + intent = new Intent(this, to_run); } else { intent = new Intent(this, VerificationActivity.class); } diff --git a/projects/MotionLayoutVerification/app/src/main/res/layout/perf_001.xml b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_001.xml new file mode 100644 index 000000000..a383be929 --- /dev/null +++ b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_001.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/projects/MotionLayoutVerification/app/src/main/res/layout/perf_002.xml b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_002.xml new file mode 100644 index 000000000..d9042156f --- /dev/null +++ b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_002.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/projects/MotionLayoutVerification/app/src/main/res/layout/perf_003.xml b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_003.xml new file mode 100644 index 000000000..155086944 --- /dev/null +++ b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_003.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/projects/MotionLayoutVerification/app/src/main/res/layout/perf_004.xml b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_004.xml new file mode 100644 index 000000000..8d4720806 --- /dev/null +++ b/projects/MotionLayoutVerification/app/src/main/res/layout/perf_004.xml @@ -0,0 +1,33 @@ + + + + + +