ExperimentBuilder2.java

Go to the documentation of this file.
00001 
00002 //ExperimentBuilder2.java                       //
00004 //$Id: ExperimentBuilder2.java 1854 2015-04-03 03:55:19Z laksono@gmail.com $    //
00006 //(c) Copyright 2002-2012 Rice University. All rights reserved. //
00008 
00009 package edu.rice.cs.hpc.data.experiment.xml;
00010 
00011 import edu.rice.cs.hpc.data.experiment.*;
00012 import edu.rice.cs.hpc.data.experiment.metric.*;
00013 import edu.rice.cs.hpc.data.experiment.metric.BaseMetric.AnnotationType;
00014 import edu.rice.cs.hpc.data.experiment.scope.*;
00015 import edu.rice.cs.hpc.data.experiment.xml.Token2.TokenXML;
00016 import edu.rice.cs.hpc.data.util.IUserData;
00017 
00018 import java.util.List;
00019 import java.util.ArrayList;
00020 
00029 public class ExperimentBuilder2 extends BaseExperimentBuilder
00030 {
00032     protected List<BaseMetric> metricList;
00033     protected List<MetricRaw> metricRawList;
00034 
00035 
00038     protected int numberOfPrimaryMetrics; 
00039 
00042     final protected int maxNumberOfMetrics = 10000;
00043 
00052     public ExperimentBuilder2(BaseExperiment experiment, String defaultName, IUserData<String, String> userData) {
00053         
00054         super(experiment, defaultName, userData);
00055         this.metricList = new ArrayList<BaseMetric>();
00056         
00057         numberOfPrimaryMetrics = 0;
00058     }
00059 
00060 
00061     //====================================== PARSING SEMANTICS ==================//
00062     
00063     /*************************************************************************
00064      * parsing the beginning of XML element 
00065      *************************************************************************/
00066     public void beginElement(String element, String[] attributes, String[] values) {
00067         
00068         TokenXML current = Token2.map(element);
00069 
00070         switch(current)
00071         {
00072         case T_NAME_VALUE:
00073             this.do_NV(attributes, values);
00074             break;
00075             
00076         case T_METRIC_TABLE:
00077             break;
00078             
00079         case T_METRIC_RAW_TABLE:
00080             this.begin_MetricRawTable();
00081             break;
00082         case T_METRIC_RAW:
00083             this.do_MetricRaw(attributes, values);
00084             break;
00085 
00086         case T_METRIC_FORMULA:
00087             this.do_MetricFormula(attributes, values);
00088             break;
00089             
00090         case T_M:
00091             this.do_M     (attributes, values); break;
00092 
00093         case T_METRIC:
00094             this.do_METRIC(attributes, values); break;
00095             
00096         default:
00097             super.beginElement(element, attributes, values);
00098         }
00099         saveTokenContext(current);
00100     }
00101 
00102     /*************************************************************************
00103      *  Takes notice of the ending of an element.
00104      ************************************************************************/
00105     public void endElement(String element)
00106     {
00107         TokenXML current = Token2.map(element);
00108         switch(current)
00109         {
00110         // Data elements
00111         case T_CALLPATH_PROFILE_DATA:   // @deprecated: semi old format. some data has this kind of tag
00112         case T_SEC_FLAT_PROFILE_DATA:
00113         case T_SEC_CALLPATH_PROFILE_DATA:
00114             this.end_ProfileData();
00115             // ok, this is ugly: we force the parent class to treat the end of this element
00116             super.endElement(element);
00117             break;
00118             
00119         case T_METRIC_TABLE:
00120             this.end_MetricTable();
00121             break;
00122 
00123         case T_METRIC_RAW_TABLE:
00124             this.end_MetricRawTable();
00125             break;
00126 
00127             // ignored elements
00128             // trace database
00129         case T_TRACE_DB:
00130         case T_METRIC_RAW:
00131         case T_M:
00132             break;
00133         default:
00134             super.endElement(element);
00135         break;
00136         } 
00137     }
00138 
00139 
00140 //  ------------------------------- BUILDING        ---------------------------//
00141 
00142     /*************************************************************************
00143      *  Finishes processing a profile element.
00144      ************************************************************************/
00145     private void end_ProfileData()
00146     {
00147         boolean is_raw_metric_only = true;
00148         final BaseExperimentWithMetrics exp = (BaseExperimentWithMetrics) experiment;
00149 
00150         final int nbMetrics = this.metricList.size();
00151         
00152         // ----------------------------------------------------------------------------
00153         // check if all metrics are metric raw.
00154         // it is unlikely that hpcprof will mix between metric raw and other type of metric,
00155         // but we cannot trust hpcprof to do properly
00156         // ----------------------------------------------------------------------------
00157         for (int i=0; i<nbMetrics; i++) {
00158             BaseMetric objMetric = this.metricList.get(i);
00159             is_raw_metric_only &= (objMetric instanceof Metric);
00160         }
00161         
00162         if (is_raw_metric_only)
00163         {
00164             // ---------------------------------------------------------------------------- 
00165             // need to reorder the metrics: instead of 0, 10000, 1, 10001, ....
00166             //  it should be: 0, 1, 2, 3, ....
00167             // our xml reader is based on old xml where the number of metrics is unknown
00168             // since now we know this number, we should change the algo 
00169             //  to adapt with the new one instead of hacking
00170             // ---------------------------------------------------------------------------- 
00171             for (int i=0; i<nbMetrics; i++) 
00172             {
00173                 Metric objMetric = (Metric) this.metricList.get(i);
00174                 objMetric.setIndex(i);
00175                 
00176                 // reset the short name. short name is the key used by formula
00177                 objMetric.setShortName(String.valueOf(i));
00178                 
00179                 // reset the partner: inclusive's partner is exclusive, and vice versa
00180                 final int partner = (objMetric.getMetricType() == MetricType.EXCLUSIVE) ? i-1: i+1;
00181                 objMetric.setPartner(partner);
00182             }
00183             // notify the experiment object that we have reordered metric index
00184             exp.setMetrics(metricList);
00185         }
00186     }
00187 
00188     /*************************************************************************
00189      *  Processes a METRICFORMULA element.
00190      *     <!-- MetricFormula represents derived metrics: (t)ype; (frm): formula -->
00191     <!ELEMENT MetricFormula (Info?)>
00192     <!ATTLIST MetricFormula
00193               t   (combine|finalize) "finalize"
00194               frm CDATA #REQUIRED>
00195      ************************************************************************/
00196     private void do_MetricFormula(String[] attributes, String[] values) 
00197     {   
00198         char formula_type = '\0';
00199         int nbMetrics= this.metricList.size();
00200         
00201         for (int i=0; i<attributes.length; i++) {
00202             if (attributes[i].charAt(0) == 't') {
00203                 // type of formala
00204                 formula_type = values[i].charAt(0);
00205             } else if (attributes[i].charAt(0) == 'f') {
00206                 // formula
00207                 assert (formula_type != '\0');
00208                 AggregateMetric objMetric = (AggregateMetric) this.metricList.get(nbMetrics-1);
00209                 objMetric.setFormula(formula_type, values[i]);
00210             }
00211         }
00212     }
00213     
00214     
00215     private enum MetricValueDesc {Raw, Final, Derived_Incr, Derived}
00216     
00217     /*************************************************************************
00218      *  Processes a METRIC element.
00219      *  <!ELEMENT Metric (MetricFormula?, Info?)>
00220         <!ATTLIST Metric
00221           i    CDATA #REQUIRED
00222           n    CDATA #REQUIRED
00223           v    (raw|final|derived-incr|derived) "raw"
00224           t    (inclusive|exclusive|nil) "nil"
00225           fmt  CDATA #IMPLIED
00226           show (1|0) "1">
00227      ************************************************************************/
00228     private void do_METRIC(String[] attributes, String[] values)
00229     {       
00230         int nbMetrics = this.metricList.size();
00231         String sID = null;// = values[nID];
00232         int iSelf = -1;
00233         int partner = 0;    // 2010.06.28: new feature to add partner
00234         String sDisplayName = null;
00235         String sNativeName = null;
00236         boolean toShow = true;
00237         AnnotationType percent = AnnotationType.NONE;
00238         MetricType objType = MetricType.EXCLUSIVE;
00239         boolean needPartner = isCallingContextTree();
00240         
00241         MetricValueDesc mDesc = MetricValueDesc.Raw; // by default is a raw metric
00242         String format = null;
00243         
00244         for (int i=0; i<attributes.length; i++) {
00245             if (attributes[i].charAt(0) == 'i') {
00246                 // id ?
00247                 sID = values[i];
00248                 // somehow, the ID of the metric is not number, but asterisk
00249                 if (sID.charAt(0) == '*') {
00250                     // parsing an asterisk can throw an exception, which is annoying
00251                     // so we make an artificial ID for this particular case
00252                     iSelf = nbMetrics;
00253                     if (isCallingContextTree()) 
00254                         iSelf = nbMetrics/2;
00255                 } else {
00256                     iSelf = Integer.parseInt(sID);
00257                 }
00258             } else if (attributes[i].charAt(0) == 'n') {
00259                 // name ?
00260                 sNativeName = values[i];
00261             } else if (attributes[i].charAt(0) == 'v') {
00262                 // value: raw|final|derived-incr|derived
00263                 if (values[i].equals("final")) {
00264                     mDesc = MetricValueDesc.Final;
00265                     needPartner = false;
00266                 } else if (values[i].equals("derived-incr")) {
00267                     mDesc = MetricValueDesc.Derived_Incr;
00268                     needPartner = false;
00269                 } else if (values[i].equals("derived")) {
00270                     mDesc = MetricValueDesc.Derived;
00271                 }
00272             } else if (attributes[i].charAt(0) == 't') {
00273                 // type: inclusive|exclusive|nil
00274                 if (values[i].charAt(0) == 'i')
00275                     objType = MetricType.INCLUSIVE;
00276                 else if (values[i].charAt(0) == 'e')
00277                     objType = MetricType.EXCLUSIVE;
00278             } else if (attributes[i].charAt(0) == 'f') {
00279                 // format to display
00280                 format = values[i];
00281                 
00282             } else if (attributes[i].equals("show-percent")) {
00283                 if (values[i].charAt(0) == '1') {
00284                     percent = AnnotationType.PERCENT;
00285                 } else {
00286                     percent = AnnotationType.NONE;
00287                 }
00288             } else if (attributes[i].charAt(0) == 's') {
00289                 // show or not ? 1=yes, 0=no
00290                 toShow = (values[i].charAt(0) == '1');
00291             } else if (attributes[i].charAt(0) == 'p') {
00292                 // partner
00293                 partner = Integer.valueOf( values[i] );
00294             }
00295         }
00296         
00297         // Laks 2009.01.14: if the database is call path database, then we need
00298         //  to distinguish between exclusive and inclusive
00299         if (needPartner) {
00300             sDisplayName = sNativeName + " (I)";
00301             objType = MetricType.INCLUSIVE;
00302             partner = this.maxNumberOfMetrics + iSelf;
00303         } else {
00304             // this metric is not for inclusive, the display name should be the same as the native one
00305             sDisplayName = sNativeName;
00306         }
00307         
00308         // set the metric
00309         BaseMetric metricInc;
00310         switch (mDesc) {
00311             case Final:
00312                 metricInc = new FinalMetric(
00313                         String.valueOf(iSelf),          // short name
00314                         sNativeName,            // native name
00315                         sDisplayName,   // display name
00316                         toShow, format, percent,            // displayed ? percent ?
00317                         "",                     // period (not defined at the moment)
00318                         nbMetrics, objType, partner);
00319                 break;
00320             case Derived_Incr:
00321                 metricInc = new AggregateMetric(sID, sDisplayName, toShow, format, percent, nbMetrics, partner, objType);
00322                 ((AggregateMetric) metricInc).init( (BaseExperimentWithMetrics) this.experiment );
00323                 break;
00324             case Raw:
00325             case Derived:
00326             default:
00327                 metricInc = new Metric(
00328                         String.valueOf(iSelf),          // short name
00329                         sNativeName,            // native name
00330                         sDisplayName,   // display name
00331                         toShow, format, percent,            // displayed ? percent ?
00332                         "",                     // period (not defined at the moment)
00333                         nbMetrics, objType, partner);
00334                 break;
00335         }
00336 
00337         this.metricList.add(metricInc);
00338 
00339         // ----------------------------------------------------------------------------
00340         // if the XML file only provides one type of metric (i.e. exclusive metric),
00341         // we should create the pair <inclusive, exclusive> manually
00342         //  this only happens if the metric is "raw metric"
00343         // ----------------------------------------------------------------------------
00344         if (needPartner) {
00345             // set the exclusive metric
00346             String sSelfName = String.valueOf(partner); // I am the partner of the inclusive metric
00347             // Laks 2009.02.09: bug fix for not reusing the existing inclusive display name
00348             String sSelfDisplayName = sNativeName + " (E)";
00349             Metric metricExc = new Metric(
00350                     sSelfName,          // short name
00351                     sSelfDisplayName,   // native name
00352                     sSelfDisplayName,   // display name
00353                     toShow, format, AnnotationType.PERCENT,         // displayed ? percent ?
00354                     "",                 // period (not defined at the moment)
00355                     nbMetrics+1, MetricType.EXCLUSIVE, nbMetrics);
00356             this.metricList.add(metricExc);
00357         }
00358     }
00359 
00360 
00361     /*******
00362      * handling metric db
00363      * @param attributes
00364      * @param values
00365      */
00366     private void do_MetricRaw(String[] attributes, String[] values)
00367     {
00368         int ID = 0;
00369         String title = null;
00370         String db_glob = null;
00371         int db_id = 0;
00372         int num_metrics = 0;
00373         
00374         for (int i=0; i<attributes.length; i++) {
00375             if (attributes[i].charAt(0) == 'i') {
00376                 ID = Integer.valueOf(values[i]);
00377             } else if (attributes[i].charAt(0) == 'n') {
00378                 title = values[i];
00379             } else if (attributes[i].equals("db-glob")) {
00380                 db_glob = values[i];
00381             } else if (attributes[i].equals("db-id")) {
00382                 db_id = Integer.valueOf(values[i]);
00383             } else if (attributes[i].equals("db-num-metrics")) {
00384                 num_metrics = Integer.valueOf(values[i]);
00385             }
00386         }
00387         
00388         MetricRaw metric = new MetricRaw(ID, title, db_glob, db_id, num_metrics);
00389         this.metricRawList.add(metric);
00390     }
00391     
00392 
00393 
00394     /*************************************************************************
00395      * finishes processing metric table
00396      *************************************************************************/
00397     private void end_MetricTable() {
00398         final BaseExperimentWithMetrics exp = (BaseExperimentWithMetrics) experiment;
00399         
00400         exp.setMetrics(metricList);
00401     }
00402 
00403         
00404     /*************************************************************************
00405      *  Processes an M (metric value) element.
00406      ************************************************************************/
00407 
00408     private void do_M(String[] attributes, String[] values)
00409     {       
00410         // m n="abc" v="4.56e7"
00411         
00412         final BaseExperimentWithMetrics exp = (BaseExperimentWithMetrics) experiment;
00413         
00414         // add a metric value to the current scope
00415         String internalName = getAttributeByName(NAME_ATTRIBUTE, attributes, values);
00416         String value = getAttributeByName(VALUE_ATTRIBUTE, attributes, values);
00417         
00418         Double dblValue = null;
00419         try {
00420             dblValue = Double.valueOf(value);
00421         } catch (NumberFormatException e) {
00422             // if the value of metric cannot be determined, we consider as "nan" (not a number)
00423             dblValue = Double.NaN;
00424         }
00425         double actualValue  = dblValue.doubleValue();
00426         
00427         BaseMetric metric = exp.getMetric(internalName);
00428         // get the sample period
00429         double prd = metric.getSamplePeriod();
00430 
00431         // multiple by sample period 
00432         actualValue = prd * actualValue;
00433         MetricValue metricValue = new MetricValue(actualValue);
00434         Scope objCurrentScope = this.getCurrentScope();
00435         
00436         objCurrentScope.setMetricValue(metric.getIndex(), metricValue);
00437 
00438         // update also the self metric value for calling context only
00439         if (metric.getMetricType() == MetricType.INCLUSIVE) {
00440 
00441             //----------------------------------------------------------------------------
00442             // Final metric (inherited from Metric) doesn't need partner. It is final.
00443             //----------------------------------------------------------------------------
00444             if (!(metric instanceof FinalMetric) && metric instanceof Metric) {
00445                 int partner = ( (Metric) metric).getPartner();
00446                 String selfShortName = String.valueOf(partner);
00447 
00448                 BaseMetric selfMetric = exp.getMetric(selfShortName); 
00449                 MetricValue selfMetricValue = new MetricValue(actualValue);
00450                 objCurrentScope.setMetricValue(selfMetric.getIndex(), selfMetricValue);  
00451             }
00452         }
00453     }
00454 
00455 
00456 
00462     private enum InfoState { PERIOD, UNIT, FLAG, AGGREGATE, NULL };
00463     /************************************************************************
00464      * Laks: special treatement when NV is called under INFO
00465      * @param attributes
00466      * @param values
00467      ************************************************************************/
00468     private void do_NV(String[] attributes, String[] values) {
00469         
00470         if ( (this.elemInfoState == TokenXML.T_METRIC) || (this.elemInfoState == TokenXML.T_METRIC_FORMULA)){
00471             InfoState iState = InfoState.NULL;
00472             // previous state is metric. The attribute should be about periodicity or unit
00473             for (int i=0; i<attributes.length; i++) {
00474                 
00475                 if (attributes[i].charAt(0) == 'n') {
00476                     // name of the info
00477                     if ( values[i].charAt(0) == 'p' ) // period
00478                         iState = InfoState.PERIOD;
00479                     else if ( values[i].charAt(0) == 'u' ) // unit
00480                         iState = InfoState.UNIT;
00481                     else if ( values[i].charAt(0) == 'f' ) // flag
00482                         iState = InfoState.FLAG;
00483                     else if ( values[i].charAt(0) == 'a' || values[i].charAt(0) == 'c') // aggregate
00484                         iState = InfoState.AGGREGATE;
00485                     else
00486                         throw new RuntimeException("Unrecognize name info tag: "+values[i]);
00487                     
00488                 } else if ( attributes[i].charAt(0) == 'v' ) {
00489                     
00490                     int nbMetrics= this.metricList.size();
00491                     // value of the info
00492                     switch (iState) {
00493                     case PERIOD:
00494                         String sPeriod = values[i];
00495                         if(nbMetrics > 1) {
00496                             // get the current metric (inc)
00497                             BaseMetric metric = this.metricList.get(nbMetrics-1);
00498                             metric.setSamplePeriod(sPeriod);
00499                             // get the current metric (exc)
00500                             metric = this.metricList.get(nbMetrics-2);
00501                             metric.setSamplePeriod(sPeriod);
00502                             
00503                         }
00504                         break;
00505                         
00506                     case UNIT:
00507                         if(nbMetrics > 0) {
00508                             // get the current metric (inc)
00509                             BaseMetric metric = this.metricList.get(nbMetrics-1);
00510                             metric.setUnit( values[i] );
00511                             if (!(metric instanceof AggregateMetric) && (nbMetrics>1)) {
00512                                 // get partner metric if the current metric is not aggregate metric
00513                                 metric = this.metricList.get(nbMetrics-2);
00514                                 metric.setUnit(values[i]);
00515                             }
00516                         }
00517                         break;
00518                         
00519                     case AGGREGATE:
00520                     case FLAG:
00521                         // not used ?
00522                         break;
00523                     default:
00524                         System.err.println("Warning: unrecognize info value state: "+iState);
00525                         break;
00526                     }
00527                     // reinitialize the info state
00528                     iState = InfoState.NULL;
00529                 } else 
00530                     System.err.println("Warning: incorrect XML info format: " + attributes[i]+" "+ values[i]);
00531             }
00532         }
00533         else
00534         {
00535             System.err.println("Warning: unknown NV from previous token: " + elemInfoState);
00536         }
00537     }
00538     
00539     //--------------------------------------------------------------------------------
00540     // raw metric database
00541     //--------------------------------------------------------------------------------
00542 
00543     /******
00544      * begin metric database
00545      */
00546     private void begin_MetricRawTable() 
00547     {
00548         this.metricRawList = new ArrayList<MetricRaw>();
00549     }
00550 
00551     /***
00552      * end metric database
00553      */
00554     private void end_MetricRawTable() 
00555     {
00556         if (this.metricRawList != null && this.metricRawList.size()>0) {
00557             MetricRaw[] metrics = new MetricRaw[metricRawList.size()];
00558             this.metricRawList.toArray( metrics );
00559             ((Experiment)this.experiment).setMetricRaw( metrics );
00560         }
00561     }
00562 }
00563 

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1