Home | History | Annotate | Download | only in tilebenchmark
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.test.tilebenchmark;
     18 
     19 import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
     20 
     21 import java.io.File;
     22 import java.util.HashMap;
     23 import java.util.Map;
     24 
     25 import android.content.res.Resources;
     26 import android.os.Bundle;
     27 import android.os.Environment;
     28 import android.test.ActivityInstrumentationTestCase2;
     29 import android.util.Log;
     30 import android.webkit.WebSettings;
     31 import android.widget.Spinner;
     32 
     33 public class PerformanceTest extends
     34         ActivityInstrumentationTestCase2<ProfileActivity> {
     35 
     36     public static class AnimStat {
     37         double aggVal = 0;
     38         double aggSqrVal = 0;
     39         double count = 0;
     40     }
     41 
     42     private class StatAggregator extends PlaybackGraphs {
     43         private HashMap<String, Double> mDataMap = new HashMap<String, Double>();
     44         private HashMap<String, AnimStat> mAnimDataMap = new HashMap<String, AnimStat>();
     45         private int mCount = 0;
     46 
     47 
     48         public void aggregate() {
     49             boolean inAnimTests = mAnimTests != null;
     50             Resources resources = mWeb.getResources();
     51             String animFramerateString = resources.getString(R.string.animation_framerate);
     52             for (Map.Entry<String, Double> e : mSingleStats.entrySet()) {
     53                 String name = e.getKey();
     54                 if (inAnimTests) {
     55                     if (name.equals(animFramerateString)) {
     56                         // in animation testing phase, record animation framerate and aggregate
     57                         // stats, differentiating on values of mAnimTestNr and mDoubleBuffering
     58                         String fullName = ANIM_TEST_NAMES[mAnimTestNr] + " " + name;
     59                         fullName += mDoubleBuffering ? " tiled" : " webkit";
     60 
     61                         if (!mAnimDataMap.containsKey(fullName)) {
     62                             mAnimDataMap.put(fullName, new AnimStat());
     63                         }
     64                         AnimStat statVals = mAnimDataMap.get(fullName);
     65                         statVals.aggVal += e.getValue();
     66                         statVals.aggSqrVal += e.getValue() * e.getValue();
     67                         statVals.count += 1;
     68                     }
     69                 } else {
     70                     double aggVal = mDataMap.containsKey(name)
     71                             ? mDataMap.get(name) : 0;
     72                     mDataMap.put(name, aggVal + e.getValue());
     73                 }
     74             }
     75 
     76             if (inAnimTests) {
     77                 return;
     78             }
     79 
     80             mCount++;
     81             for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
     82                 for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
     83                     String metricLabel = resources.getString(
     84                             Metrics[metricIndex].getLabelId());
     85                     String statLabel = resources.getString(
     86                             Stats[statIndex].getLabelId());
     87 
     88                     String label = metricLabel + " " + statLabel;
     89                     double aggVal = mDataMap.containsKey(label) ? mDataMap
     90                             .get(label) : 0;
     91 
     92                     aggVal += mStats[metricIndex][statIndex];
     93                     mDataMap.put(label, aggVal);
     94                 }
     95             }
     96 
     97         }
     98 
     99         // build the final bundle of results
    100         public Bundle getBundle() {
    101             Bundle b = new Bundle();
    102             int count = (0 == mCount) ? Integer.MAX_VALUE : mCount;
    103             for (Map.Entry<String, Double> e : mDataMap.entrySet()) {
    104                 b.putDouble(e.getKey(), e.getValue() / count);
    105             }
    106 
    107             for (Map.Entry<String, AnimStat> e : mAnimDataMap.entrySet()) {
    108                 String statName = e.getKey();
    109                 AnimStat statVals = e.getValue();
    110 
    111                 double avg = statVals.aggVal/statVals.count;
    112                 double stdDev = Math.sqrt((statVals.aggSqrVal / statVals.count) - avg * avg);
    113 
    114                 b.putDouble(statName, avg);
    115                 b.putDouble(statName + " STD DEV", stdDev);
    116             }
    117 
    118             return b;
    119         }
    120     }
    121 
    122     ProfileActivity mActivity;
    123     ProfiledWebView mWeb;
    124     Spinner mMovementSpinner;
    125     StatAggregator mStats;
    126 
    127     private static final String LOGTAG = "PerformanceTest";
    128     private static final String TEST_LOCATION = "webkit/page_cycler";
    129     private static final String URL_PREFIX = "file://";
    130     private static final String URL_POSTFIX = "/index.html?skip=true";
    131     private static final int MAX_ITERATIONS = 4;
    132     private static final String SCROLL_TEST_DIRS[] = {
    133         "alexa25_2011"
    134     };
    135     private static final String ANIM_TEST_DIRS[] = {
    136         "dhtml"
    137     };
    138 
    139     public PerformanceTest() {
    140         super(ProfileActivity.class);
    141     }
    142 
    143     @Override
    144     protected void setUp() throws Exception {
    145         super.setUp();
    146         mActivity = getActivity();
    147         mWeb = (ProfiledWebView) mActivity.findViewById(R.id.web);
    148         mMovementSpinner = (Spinner) mActivity.findViewById(R.id.movement);
    149         mStats = new StatAggregator();
    150 
    151         // use mStats as a condition variable between the UI thread and
    152         // this(the testing) thread
    153         mActivity.setCallback(new ProfileCallback() {
    154             @Override
    155             public void profileCallback(RunData data) {
    156                 mStats.setData(data);
    157                 synchronized (mStats) {
    158                     mStats.notify();
    159                 }
    160             }
    161         });
    162 
    163     }
    164 
    165     private boolean loadUrl(final String url) {
    166         try {
    167             Log.d(LOGTAG, "test starting for url " + url);
    168             mActivity.runOnUiThread(new Runnable() {
    169                 @Override
    170                 public void run() {
    171                     mWeb.loadUrl(url);
    172                 }
    173             });
    174             synchronized (mStats) {
    175                 mStats.wait();
    176             }
    177 
    178             mStats.aggregate();
    179         } catch (InterruptedException e) {
    180             e.printStackTrace();
    181             return false;
    182         }
    183         return true;
    184     }
    185 
    186     private boolean validTest(String nextTest) {
    187         // if testing animations, test must be in mAnimTests
    188         if (mAnimTests == null)
    189             return true;
    190 
    191         for (String test : mAnimTests) {
    192             if (test.equals(nextTest)) {
    193                 return true;
    194             }
    195         }
    196         return false;
    197     }
    198 
    199     private boolean runIteration(String[] testDirs) {
    200         File sdFile = Environment.getExternalStorageDirectory();
    201         for (String testDirName : testDirs) {
    202             File testDir = new File(sdFile, TEST_LOCATION + "/" + testDirName);
    203             Log.d(LOGTAG, "Testing dir: '" + testDir.getAbsolutePath()
    204                     + "', exists=" + testDir.exists());
    205 
    206             for (File siteDir : testDir.listFiles()) {
    207                 if (!siteDir.isDirectory() || !validTest(siteDir.getName())) {
    208                     continue;
    209                 }
    210 
    211                 if (!loadUrl(URL_PREFIX + siteDir.getAbsolutePath()
    212                         + URL_POSTFIX)) {
    213                     return false;
    214                 }
    215             }
    216         }
    217         return true;
    218     }
    219 
    220     private boolean  runTestDirs(String[] testDirs) {
    221         for (int i = 0; i < MAX_ITERATIONS; i++)
    222             if (!runIteration(testDirs)) {
    223                 return false;
    224             }
    225         return true;
    226     }
    227 
    228     private void pushDoubleBuffering() {
    229         getInstrumentation().runOnMainSync(new Runnable() {
    230             public void run() {
    231                 mWeb.setDoubleBuffering(mDoubleBuffering);
    232             }
    233         });
    234     }
    235 
    236     private void setScrollingTestingMode(final boolean scrolled) {
    237         getInstrumentation().runOnMainSync(new Runnable() {
    238             public void run() {
    239                 mMovementSpinner.setSelection(scrolled ? 0 : 2);
    240             }
    241         });
    242     }
    243 
    244 
    245     private String[] mAnimTests = null;
    246     private int mAnimTestNr = -1;
    247     private boolean mDoubleBuffering = true;
    248     private static final String[] ANIM_TEST_NAMES = {
    249         "slow", "fast"
    250     };
    251     private static final String[][] ANIM_TESTS = {
    252         {"scrolling", "replaceimages", "layers5", "layers1"},
    253         {"slidingballs", "meter", "slidein", "fadespacing", "colorfade",
    254                 "mozilla", "movingtext", "diagball", "zoom", "imageslide"},
    255     };
    256 
    257     private boolean checkMedia() {
    258         String state = Environment.getExternalStorageState();
    259 
    260         if (!Environment.MEDIA_MOUNTED.equals(state)
    261                 && !Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
    262             Log.d(LOGTAG, "ARG Can't access sd card!");
    263             // Can't read the SD card, fail and die!
    264             getInstrumentation().sendStatus(1, null);
    265             return false;
    266         }
    267         return true;
    268     }
    269 
    270     public void testMetrics() {
    271         setScrollingTestingMode(true);
    272         if (checkMedia() && runTestDirs(SCROLL_TEST_DIRS)) {
    273             getInstrumentation().sendStatus(0, mStats.getBundle());
    274         } else {
    275             getInstrumentation().sendStatus(1, null);
    276         }
    277     }
    278 
    279     public void testMetricsMinimalMemory() {
    280         mActivity.runOnUiThread(new Runnable() {
    281             @Override
    282             public void run() {
    283                 mWeb.setUseMinimalMemory(true);
    284             }
    285         });
    286 
    287         setScrollingTestingMode(true);
    288         if (checkMedia() && runTestDirs(SCROLL_TEST_DIRS)) {
    289             getInstrumentation().sendStatus(0, mStats.getBundle());
    290         } else {
    291             getInstrumentation().sendStatus(1, null);
    292         }
    293     }
    294 
    295     private boolean runAnimationTests() {
    296         for (int doubleBuffer = 0; doubleBuffer <= 1; doubleBuffer++) {
    297             mDoubleBuffering = doubleBuffer == 1;
    298             pushDoubleBuffering();
    299             for (mAnimTestNr = 0; mAnimTestNr < ANIM_TESTS.length; mAnimTestNr++) {
    300                 mAnimTests = ANIM_TESTS[mAnimTestNr];
    301                 if (!runTestDirs(ANIM_TEST_DIRS)) {
    302                     return false;
    303                 }
    304             }
    305         }
    306         return true;
    307     }
    308 
    309     public void testAnimations() {
    310         // instead of autoscrolling, load each page until either an timer fires,
    311         // or the animation signals complete via javascript
    312         setScrollingTestingMode(false);
    313 
    314         if (checkMedia() && runAnimationTests()) {
    315             getInstrumentation().sendStatus(0, mStats.getBundle());
    316         } else {
    317             getInstrumentation().sendStatus(1, null);
    318         }
    319     }
    320 }
    321