1af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir/* 2af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * Copyright (C) 2017 The Android Open Source Project 3af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * 4af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * use this file except in compliance with the License. You may obtain a copy of 6af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * the License at 7af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * 8af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * http://www.apache.org/licenses/LICENSE-2.0 9af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * 10af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * Unless required by applicable law or agreed to in writing, software 11af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * License for the specific language governing permissions and limitations under 14af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * the License. 15af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir */ 16af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirpackage android.text; 17af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 18af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport static android.text.Layout.Alignment.ALIGN_NORMAL; 19af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 20af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport android.graphics.Canvas; 21af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport android.perftests.utils.BenchmarkState; 22af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport android.perftests.utils.PerfStatusReporter; 23af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport android.support.test.filters.LargeTest; 24af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport android.text.NonEditableTextGenerator.TextType; 25af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport android.view.DisplayListCanvas; 26af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport android.view.RenderNode; 27af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 28af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport org.junit.Rule; 29af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport org.junit.Test; 30af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport org.junit.runner.RunWith; 31af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport org.junit.runners.Parameterized; 32af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 33af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport java.util.ArrayList; 34af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport java.util.Collection; 35af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport java.util.List; 36af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirimport java.util.Random; 37af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 38af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir/** 39af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * Performance test for multi line, single style {@link StaticLayout} creation/draw. 40af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir */ 41af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir@LargeTest 42af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir@RunWith(Parameterized.class) 43af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinirpublic class StaticLayoutCreateDrawPerfTest { 44af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 45af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private static final boolean[] BOOLEANS = new boolean[]{false, true}; 46af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 47af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private static final float SPACING_ADD = 10f; 48af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private static final float SPACING_MULT = 1.5f; 49af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 50af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir @Rule 51af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); 52af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 531f84ea9f2d9b5df63460e88216f618ae5d1a8e1bSiyamed Sinir @Parameterized.Parameters(name = "cached={3},{1}chars,{0}") 54af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir public static Collection cases() { 55af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir final List<Object[]> params = new ArrayList<>(); 56d0a5206dd8130611567acab92206eeecc222a65eSiyamed Sinir for (int length : new int[]{128}) { 57af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir for (boolean cached : BOOLEANS) { 58d0a5206dd8130611567acab92206eeecc222a65eSiyamed Sinir for (TextType textType : new TextType[]{TextType.STRING, 59d0a5206dd8130611567acab92206eeecc222a65eSiyamed Sinir TextType.SPANNABLE_BUILDER}) { 60d0a5206dd8130611567acab92206eeecc222a65eSiyamed Sinir params.add(new Object[]{textType.name(), length, textType, cached}); 61af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 62af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 63af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 64af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir return params; 65af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 66af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 67af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private final int mLineWidth; 68af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private final int mLength; 69af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private final TextType mTextType; 70af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private final boolean mCached; 71af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private final TextPaint mTextPaint; 72af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 73af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir public StaticLayoutCreateDrawPerfTest(String label, int length, TextType textType, 74d0a5206dd8130611567acab92206eeecc222a65eSiyamed Sinir boolean cached) { 75af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir mLength = length; 76af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir mTextType = textType; 77af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir mCached = cached; 78af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir mTextPaint = new TextPaint(); 79af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir mTextPaint.setTextSize(10); 80d0a5206dd8130611567acab92206eeecc222a65eSiyamed Sinir mLineWidth = Integer.MAX_VALUE; 81af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 82af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 83af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir /** 84af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * Measures the creation time for a multi line {@link StaticLayout}. 85af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir */ 86af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir @Test 87af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir public void timeCreate() throws Exception { 88af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 89af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 90af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.pauseTiming(); 91af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir Canvas.freeTextLayoutCaches(); 92af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir final CharSequence text = createRandomText(mLength); 93af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir createLayout(text); 94af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.resumeTiming(); 95af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 96af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir while (state.keepRunning()) { 97af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.pauseTiming(); 98af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir if (!mCached) Canvas.freeTextLayoutCaches(); 99af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.resumeTiming(); 100af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 101af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir createLayout(text); 102af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 103af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 104af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 105af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir /** 106af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir * Measures the draw time for a multi line {@link StaticLayout}. 107af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir */ 108af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir @Test 109af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir public void timeDraw() throws Exception { 110af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 111af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 112af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.pauseTiming(); 113af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir Canvas.freeTextLayoutCaches(); 114af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir final RenderNode node = RenderNode.create("benchmark", null); 115af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir final CharSequence text = createRandomText(mLength); 116af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir final Layout layout = createLayout(text); 117af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.resumeTiming(); 118af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 119af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir while (state.keepRunning()) { 120af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 121af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.pauseTiming(); 122af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir final DisplayListCanvas canvas = node.start(1200, 200); 123af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir int save = canvas.save(); 124af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir if (!mCached) Canvas.freeTextLayoutCaches(); 125af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.resumeTiming(); 126af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 127af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir layout.draw(canvas); 128af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 129af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.pauseTiming(); 130af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir canvas.restoreToCount(save); 131af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir node.end(canvas); 132af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir state.resumeTiming(); 133af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 134af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 135af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 136af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private Layout createLayout(CharSequence text) { 137af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir return StaticLayout.Builder.obtain(text, 0 /*start*/, text.length() /*end*/, mTextPaint, 138af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir mLineWidth) 139af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir .setAlignment(ALIGN_NORMAL) 140af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir .setIncludePad(true) 141af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir .setLineSpacing(SPACING_ADD, SPACING_MULT) 142af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir .build(); 143af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 144af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir 145af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir private CharSequence createRandomText(int length) { 146af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir return new NonEditableTextGenerator(new Random(0)) 147af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir .setSequenceLength(length) 148af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir .setTextType(mTextType) 149af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir .build(); 150af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir } 151af479b8c9743a1536d46f0985294c8bc0823a338Siyamed Sinir} 152