Home | History | Annotate | Download | only in entity
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you
      5  * may not use this file except in compliance with the License. You may
      6  * 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
     13  * implied. See the License for the specific language governing
     14  * permissions and limitations under the License.
     15  */
     16 
     17 package com.android.vts.entity;
     18 
     19 import com.android.vts.proto.VtsReportMessage.VtsProfilingRegressionMode;
     20 import com.android.vts.util.StatSummary;
     21 import com.google.appengine.api.datastore.Entity;
     22 import com.google.appengine.api.datastore.Key;
     23 import com.google.appengine.api.datastore.KeyFactory;
     24 import java.util.ArrayList;
     25 import java.util.HashMap;
     26 import java.util.List;
     27 import java.util.Map;
     28 import java.util.logging.Level;
     29 import java.util.logging.Logger;
     30 
     31 /** Entity describing a profiling point summary. */
     32 public class ProfilingPointSummaryEntity implements DashboardEntity {
     33     protected static final Logger logger =
     34             Logger.getLogger(ProfilingPointSummaryEntity.class.getName());
     35     protected static final String DELIMITER = "#";
     36 
     37     public static final String KIND = "ProfilingPointSummary";
     38     public static final String ALL = "ALL";
     39 
     40     // Property keys
     41     public static final String START_TIME = "startTime";
     42     public static final String MEAN = "mean";
     43     public static final String SUMSQ = "sumSq";
     44     public static final String MIN = "min";
     45     public static final String MAX = "max";
     46     public static final String LABELS = "labels";
     47     public static final String LABEL_MEANS = "labelMeans";
     48     public static final String LABEL_SUMSQS = "labelSumSqs";
     49     public static final String LABEL_MINS = "labelMins";
     50     public static final String LABEL_MAXES = "labelMaxes";
     51     public static final String LABEL_COUNTS = "labelCounts";
     52     public static final String COUNT = "count";
     53     public static final String BRANCH = "branch";
     54     public static final String BUILD_FLAVOR = "buildFlavor";
     55     public static final String SERIES = "series";
     56 
     57     private final Key key;
     58 
     59     public final StatSummary globalStats;
     60     public final List<String> labels;
     61     public final Map<String, StatSummary> labelStats;
     62     public final String branch;
     63     public final String buildFlavor;
     64     public final String series;
     65     public final long startTime;
     66 
     67     /**
     68      * Create a ProfilingPointSummaryEntity object.
     69      *
     70      * @param parentKey The Key object for the parent TestRunEntity in the database.
     71      * @param globalStats The StatSummary object recording global statistics about the profiling
     72      *     point.
     73      * @param labels The list of data labels.
     74      * @param labelStats The map from data label to StatSummary object for the label.
     75      * @param branch The branch.
     76      * @param buildFlavor The device build flavor.
     77      * @param series The string describing the profiling point series (e.g. binder or passthrough).
     78      * @param startTime The timestamp indicating the beginning of the summary.
     79      */
     80     public ProfilingPointSummaryEntity(
     81             Key parentKey,
     82             StatSummary globalStats,
     83             List<String> labels,
     84             Map<String, StatSummary> labelStats,
     85             String branch,
     86             String buildFlavor,
     87             String series,
     88             long startTime) {
     89         this.globalStats = globalStats;
     90         this.labels = labels;
     91         this.labelStats = labelStats;
     92         this.buildFlavor = buildFlavor == null ? ALL : buildFlavor;
     93         this.branch = branch == null ? ALL : branch;
     94         this.series = series == null ? "" : series;
     95         this.startTime = startTime;
     96         this.key = createKey(parentKey, this.branch, this.buildFlavor, this.series, this.startTime);
     97     }
     98 
     99     /**
    100      * Create a new ProfilingPointSummaryEntity object.
    101      *
    102      * @param parentKey The Key object for the parent TestRunEntity in the database.
    103      * @param branch The branch.
    104      * @param buildFlavor The buildFlavor name.
    105      * @param series The string describing the profiling point series (e.g. binder or passthrough).
    106      * @param startTime The timestamp indicating the beginning of the summary.
    107      */
    108     public ProfilingPointSummaryEntity(
    109             Key parentKey, String branch, String buildFlavor, String series, long startTime) {
    110         this(
    111                 parentKey,
    112                 new StatSummary(null, VtsProfilingRegressionMode.UNKNOWN_REGRESSION_MODE),
    113                 new ArrayList<>(),
    114                 new HashMap<>(),
    115                 branch,
    116                 buildFlavor,
    117                 series,
    118                 startTime);
    119     }
    120 
    121     /**
    122      * Create a key for a ProfilingPointSummaryEntity.
    123      *
    124      * @param parentKey The Key object for the parent TestRunEntity in the database.
    125      * @param branch The branch.
    126      * @param buildFlavor The device build flavor.
    127      * @param series The string describing the profiling point series (e.g. binder or passthrough).
    128      * @param startTime The timestamp indicating the beginning of the summary.
    129      * @return a Key object for the ProfilingPointSummaryEntity in the database.
    130      */
    131     public static Key createKey(
    132             Key parentKey, String branch, String buildFlavor, String series, long startTime) {
    133         StringBuilder sb = new StringBuilder();
    134         sb.append(branch);
    135         sb.append(DELIMITER);
    136         sb.append(buildFlavor);
    137         sb.append(DELIMITER);
    138         sb.append(series);
    139         sb.append(DELIMITER);
    140         sb.append(startTime);
    141         return KeyFactory.createKey(parentKey, KIND, sb.toString());
    142     }
    143 
    144     /**
    145      * Updates the profiling summary with the data from a new profiling report.
    146      *
    147      * @param profilingRun The profiling point run entity object containing profiling data.
    148      */
    149     public void update(ProfilingPointRunEntity profilingRun) {
    150         if (profilingRun.labels != null
    151                 && profilingRun.labels.size() == profilingRun.values.size()) {
    152             for (int i = 0; i < profilingRun.labels.size(); i++) {
    153                 String label = profilingRun.labels.get(i);
    154                 if (!this.labelStats.containsKey(label)) {
    155                     StatSummary summary = new StatSummary(label, profilingRun.regressionMode);
    156                     this.labelStats.put(label, summary);
    157                 }
    158                 StatSummary summary = this.labelStats.get(label);
    159                 summary.updateStats(profilingRun.values.get(i));
    160             }
    161             this.labels.clear();
    162             this.labels.addAll(profilingRun.labels);
    163         }
    164         for (long value : profilingRun.values) {
    165             this.globalStats.updateStats(value);
    166         }
    167     }
    168 
    169     @Override
    170     public Entity toEntity() {
    171         Entity profilingSummary;
    172         profilingSummary = new Entity(this.key);
    173         profilingSummary.setUnindexedProperty(MEAN, this.globalStats.getMean());
    174         profilingSummary.setUnindexedProperty(SUMSQ, this.globalStats.getSumSq());
    175         profilingSummary.setUnindexedProperty(MIN, this.globalStats.getMin());
    176         profilingSummary.setUnindexedProperty(MAX, this.globalStats.getMax());
    177         profilingSummary.setUnindexedProperty(COUNT, this.globalStats.getCount());
    178         profilingSummary.setIndexedProperty(START_TIME, this.startTime);
    179         profilingSummary.setIndexedProperty(BRANCH, this.branch);
    180         profilingSummary.setIndexedProperty(BUILD_FLAVOR, this.buildFlavor);
    181         profilingSummary.setIndexedProperty(SERIES, this.series);
    182         if (this.labels.size() != 0) {
    183             List<Double> labelMeans = new ArrayList<>();
    184             List<Double> labelSumsqs = new ArrayList<>();
    185             List<Double> labelMins = new ArrayList<>();
    186             List<Double> labelMaxes = new ArrayList<>();
    187             List<Long> labelCounts = new ArrayList<>();
    188             for (String label : this.labels) {
    189                 if (!this.labelStats.containsKey(label)) continue;
    190                 StatSummary labelStat = this.labelStats.get(label);
    191                 labelMeans.add(labelStat.getMean());
    192                 labelSumsqs.add(labelStat.getSumSq());
    193                 labelMins.add(labelStat.getMin());
    194                 labelMaxes.add(labelStat.getMax());
    195                 labelCounts.add(new Long(labelStat.getCount()));
    196             }
    197             profilingSummary.setUnindexedProperty(LABELS, this.labels);
    198             profilingSummary.setUnindexedProperty(LABEL_MEANS, labelMeans);
    199             profilingSummary.setUnindexedProperty(LABEL_SUMSQS, labelSumsqs);
    200             profilingSummary.setUnindexedProperty(LABEL_MINS, labelMins);
    201             profilingSummary.setUnindexedProperty(LABEL_MAXES, labelMaxes);
    202             profilingSummary.setUnindexedProperty(LABEL_COUNTS, labelCounts);
    203         }
    204 
    205         return profilingSummary;
    206     }
    207 
    208     /**
    209      * Convert an Entity object to a ProfilingPointSummaryEntity.
    210      *
    211      * @param e The entity to process.
    212      * @return ProfilingPointSummaryEntity object with the properties from e, or null if
    213      *     incompatible.
    214      */
    215     @SuppressWarnings("unchecked")
    216     public static ProfilingPointSummaryEntity fromEntity(Entity e) {
    217         if (!e.getKind().equals(KIND)
    218                 || !e.hasProperty(MEAN)
    219                 || !e.hasProperty(SUMSQ)
    220                 || !e.hasProperty(MIN)
    221                 || !e.hasProperty(MAX)
    222                 || !e.hasProperty(COUNT)
    223                 || !e.hasProperty(START_TIME)
    224                 || !e.hasProperty(BRANCH)
    225                 || !e.hasProperty(BUILD_FLAVOR)
    226                 || !e.hasProperty(SERIES)) {
    227             logger.log(
    228                     Level.WARNING, "Missing profiling point attributes in entity: " + e.toString());
    229             return null;
    230         }
    231         try {
    232             Key parentKey = e.getParent();
    233             double mean = (double) e.getProperty(MEAN);
    234             double sumsq = (double) e.getProperty(SUMSQ);
    235             double min = (double) e.getProperty(MIN);
    236             double max = (double) e.getProperty(MAX);
    237             int count = (int) (long) e.getProperty(COUNT);
    238             StatSummary globalStats =
    239                     new StatSummary(
    240                             null,
    241                             min,
    242                             max,
    243                             mean,
    244                             sumsq,
    245                             count,
    246                             VtsProfilingRegressionMode.UNKNOWN_REGRESSION_MODE);
    247             Map<String, StatSummary> labelStats = new HashMap<>();
    248             List<String> labels = new ArrayList<>();
    249             if (e.hasProperty(LABELS)) {
    250                 labels = (List<String>) e.getProperty(LABELS);
    251                 List<Double> labelMeans = (List<Double>) e.getProperty(LABEL_MEANS);
    252                 List<Double> labelSumsqs = (List<Double>) e.getProperty(LABEL_SUMSQS);
    253                 List<Double> labelMins = (List<Double>) e.getProperty(LABEL_MINS);
    254                 List<Double> labelMaxes = (List<Double>) e.getProperty(LABEL_MAXES);
    255                 List<Long> labelCounts = (List<Long>) e.getProperty(LABEL_COUNTS);
    256                 if (labels.size() != labelMeans.size()
    257                         || labels.size() != labelSumsqs.size()
    258                         || labels.size() != labelMins.size()
    259                         || labels.size() != labelMaxes.size()
    260                         || labels.size() != labelCounts.size()) {
    261                     logger.log(Level.WARNING, "Jagged label information for entity: " + e.getKey());
    262                     return null;
    263                 }
    264                 for (int i = 0; i < labels.size(); ++i) {
    265                     StatSummary labelStat =
    266                             new StatSummary(
    267                                     labels.get(i),
    268                                     labelMins.get(i),
    269                                     labelMaxes.get(i),
    270                                     labelMeans.get(i),
    271                                     labelSumsqs.get(i),
    272                                     labelCounts.get(i).intValue(),
    273                                     VtsProfilingRegressionMode.UNKNOWN_REGRESSION_MODE);
    274                     labelStats.put(labels.get(i), labelStat);
    275                 }
    276             }
    277             String branch = (String) e.getProperty(BRANCH);
    278             String buildFlavor = (String) e.getProperty(BUILD_FLAVOR);
    279             String series = (String) e.getProperty(SERIES);
    280             long startTime = (long) e.getProperty(START_TIME);
    281             return new ProfilingPointSummaryEntity(
    282                     parentKey,
    283                     globalStats,
    284                     labels,
    285                     labelStats,
    286                     branch,
    287                     buildFlavor,
    288                     series,
    289                     startTime);
    290         } catch (ClassCastException exception) {
    291             // Invalid cast
    292             logger.log(Level.WARNING, "Error parsing profiling point summary entity.", exception);
    293         }
    294         return null;
    295     }
    296 }
    297