You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jp...@apache.org on 2010/01/22 20:25:10 UTC

svn commit: r902236 - in /incubator/trafficserver/traffic/branches/dev: libinktomi++/DynArray.h libinktomi++/Regression.cc libinktomi++/Regression.h proxy/Makefile.am proxy/RegressionSM.cc proxy/RegressionSM.h

Author: jplevyak
Date: Fri Jan 22 19:25:10 2010
New Revision: 902236

URL: http://svn.apache.org/viewvc?rev=902236&view=rev
Log:
TS-115: This adds a new rperf() call to report performance results in regressions
This adds a sequential and parallel composition system for regression statemachines.

Added:
    incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.cc
    incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.h
Modified:
    incubator/trafficserver/traffic/branches/dev/libinktomi++/DynArray.h
    incubator/trafficserver/traffic/branches/dev/libinktomi++/Regression.cc
    incubator/trafficserver/traffic/branches/dev/libinktomi++/Regression.h
    incubator/trafficserver/traffic/branches/dev/proxy/Makefile.am

Modified: incubator/trafficserver/traffic/branches/dev/libinktomi++/DynArray.h
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/branches/dev/libinktomi%2B%2B/DynArray.h?rev=902236&r1=902235&r2=902236&view=diff
==============================================================================
--- incubator/trafficserver/traffic/branches/dev/libinktomi++/DynArray.h (original)
+++ incubator/trafficserver/traffic/branches/dev/libinktomi++/DynArray.h Fri Jan 22 19:25:10 2010
@@ -30,7 +30,7 @@
 
 template<class T> class DynArray {
 public:
-  DynArray(const T * val, intptr_t initial_size = 0);
+  DynArray(const T * val = 0, intptr_t initial_size = 0);
   ~DynArray();
 
 #ifndef __GNUC__
@@ -71,6 +71,7 @@
 
     resize(i);
   }
+
 }
 
 template<class T> inline DynArray<T>::~DynArray()
@@ -177,7 +178,8 @@
     }
 
     for (; i < new_size; i++) {
-      new_data[i] = (T) * default_val;
+      if (default_val)
+        new_data[i] = (T) * default_val;
     }
 
     if (data) {

Modified: incubator/trafficserver/traffic/branches/dev/libinktomi++/Regression.cc
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/branches/dev/libinktomi%2B%2B/Regression.cc?rev=902236&r1=902235&r2=902236&view=diff
==============================================================================
--- incubator/trafficserver/traffic/branches/dev/libinktomi++/Regression.cc (original)
+++ incubator/trafficserver/traffic/branches/dev/libinktomi++/Regression.cc Fri Jan 22 19:25:10 2010
@@ -35,16 +35,12 @@
 static RegressionTest *test = NULL;
 static RegressionTest *exclusive_test = NULL;
 
-RegressionTest *
-  RegressionTest::current = 0;
-int
-  RegressionTest::ran_tests = 0;
-DFA
-  RegressionTest::dfa;
-int
-  regression_level = 0;
-int
-  RegressionTest::final_status = REGRESSION_TEST_PASSED;
+RegressionTest *RegressionTest::current = 0;
+int RegressionTest::ran_tests = 0;
+DFA RegressionTest::dfa;
+int regression_level = 0;
+int RegressionTest::final_status = REGRESSION_TEST_PASSED;
+
 char *
 regression_status_string(int status)
 {
@@ -55,7 +51,6 @@
 
 RegressionTest::RegressionTest(const char *name_arg, TestFunction * function_arg, int aopt)
 {
-  // printf("<%s>\n",name_arg);
   name = name_arg;
   function = function_arg;
   status = REGRESSION_TEST_NOT_RUN;
@@ -109,7 +104,6 @@
   return run_some();
 }
 
-
 int
 RegressionTest::run_some()
 {
@@ -123,7 +117,6 @@
               &SPACES[40 + strlen(current->name)], regression_status_string(current->status));
     }
     current = current->next;
-
   }
   for (; current; current = current->next) {
     if ((dfa.match(current->name) >= 0)) {
@@ -180,7 +173,7 @@
 }
 
 int
-rprintf(RegressionTest * t, const char *format, ...)
+rprintf(RegressionTest *t, const char *format, ...)
 {
   int l;
   char buffer[8192];
@@ -194,10 +187,21 @@
   return (l);
 }
 
+int
+rperf(RegressionTest *t, const char *tag, double val)
+{
+  int l;
+  char format2[8192];
+  l = snprintf(format2, sizeof(format2), "RPERF %s.%s %f\n", t->name, tag, val);
+  fputs(format2, stderr);
+  return (l);
+}
+
 REGRESSION_TEST(Regression) (RegressionTest * t, int atype, int *status) {
   (void) t;
   (void) atype;
   rprintf(t, "regression test\n");
+  rperf(t, "speed", 100.0);
   if (!test)
     *status = REGRESSION_TEST_FAILED;
   else

Modified: incubator/trafficserver/traffic/branches/dev/libinktomi++/Regression.h
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/branches/dev/libinktomi%2B%2B/Regression.h?rev=902236&r1=902235&r2=902236&view=diff
==============================================================================
--- incubator/trafficserver/traffic/branches/dev/libinktomi++/Regression.h (original)
+++ incubator/trafficserver/traffic/branches/dev/libinktomi++/Regression.h Fri Jan 22 19:25:10 2010
@@ -21,38 +21,32 @@
   limitations under the License.
  */
 
-/****************************************************************************
-
-  Regression.h
-
-  
- ****************************************************************************/
-
 #ifndef _Regression_h
 #define _Regression_h
+
 #include "inktomi++.h"
 #include "Regex.h"
 
-// 
-//  Each module should provide one or more regression tests
+//   Each module should provide one or more regression tests
 //
-//  An example:
+//   An example:
 //
-// REGRESSION_TEST(Addition)(RegressionTest *t, int atype, int *pstatus) {
-//    if (1 + 1 != 2) 
-//      *pstatus = REGRESSION_TEST_FAILED;
-//    if (atype > REGRESSION_TEST_NIGHTLY)  // try again
-//      if (1 + 1 != 2) 
-//        *pstatus = REGRESSION_TEST_FAILED;
-//    rprintf(t, "it worked, 1+1 really is 2!");
-//    *pstatus return REGRESSION_TEST_PASSED;
-// }
-// 
-// 
+//   REGRESSION_TEST(Addition)(RegressionTest *t, int atype, int *pstatus) {
+//     if (atype < REGRESSION_TEST_NIGHTLY) { // to expensive to do more than nightly
+//       *pstatus = REGRESSION_TEST_NOT_RUN;
+//       return;
+//     }
+//     if (1 + 1 != 2) {
+//       rprintf(t, "drat, 1+1 isn't 2??");
+//       *pstatus = REGRESSION_TEST_FAILED;
+//     } else
+//       *pstatus = REGRESSION_TEST_PASSED;
+//   }
+
 
 // status values
 #define REGRESSION_TEST_PASSED         1
-#define REGRESSION_TEST_INPROGRESS     0
+#define REGRESSION_TEST_INPROGRESS     0 // initial value
 #define REGRESSION_TEST_FAILED         -1
 #define REGRESSION_TEST_NOT_RUN        -2
 
@@ -80,7 +74,7 @@
   int printed;
   int opt;
 
-    RegressionTest(const char *name_arg, TestFunction * function_arg, int aopt);
+  RegressionTest(const char *name_arg, TestFunction * function_arg, int aopt);
 
   static int final_status;
   static int ran_tests;
@@ -102,6 +96,7 @@
 void RegressionTest_##_f
 
 int rprintf(RegressionTest * t, const char *format, ...);
+int rperf(RegressionTest *t, const char *tag, double val);
 char *regression_status_string(int status);
 
 extern int regression_level;
@@ -113,5 +108,4 @@
   Warning(_buf);                                                        \
 }                                                                       \
 
-#define _Regression_h
 #endif /* _Regression_h */

Modified: incubator/trafficserver/traffic/branches/dev/proxy/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/branches/dev/proxy/Makefile.am?rev=902236&r1=902235&r2=902236&view=diff
==============================================================================
--- incubator/trafficserver/traffic/branches/dev/proxy/Makefile.am (original)
+++ incubator/trafficserver/traffic/branches/dev/proxy/Makefile.am Fri Jan 22 19:25:10 2010
@@ -109,6 +109,8 @@
   Prefetch.cc \
   Prefetch.h \
   Raf.h \
+  RegressionSM.h \
+  RegressionSM.cc \
   RemapAPI.h \
   ReverseProxy.cc \
   ReverseProxy.h \

Added: incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.cc
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.cc?rev=902236&view=auto
==============================================================================
--- incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.cc (added)
+++ incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.cc Fri Jan 22 19:25:10 2010
@@ -0,0 +1,259 @@
+/** @file
+
+  A brief file description
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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.
+ */
+
+#include "P_EventSystem.h"
+#include "RegressionSM.h"
+
+#define REGRESSION_SM_RETRY (100*HRTIME_MSECOND)
+
+void RegressionSM::set_status(int astatus) {
+  ink_assert(astatus != REGRESSION_TEST_INPROGRESS);
+  // INPROGRESS < NOT_RUN < PASSED < FAILED
+  if (status != REGRESSION_TEST_FAILED) {
+    if (status == REGRESSION_TEST_PASSED) {
+      if (astatus != REGRESSION_TEST_NOT_RUN)
+        status = astatus;
+    } else {
+      // INPROGRESS or NOT_RUN
+      status = astatus;
+    }
+  } // else FAILED is FAILED
+}
+
+void RegressionSM::done(int astatus) {
+  if (pending_action) {
+    pending_action->cancel();
+    pending_action = 0;
+  }
+  set_status(astatus);
+  if (pstatus) *pstatus = status;
+  if (parent) parent->child_done(status);
+}
+
+void RegressionSM::run(int *apstatus) {
+  pstatus = apstatus;
+  run();
+}
+
+void RegressionSM::xrun(RegressionSM *aparent) {
+  parent = aparent;
+  parent->nwaiting++;
+  run();
+}
+
+void RegressionSM::run_in(int *apstatus, ink_hrtime t) {
+  pstatus = apstatus;
+  SET_HANDLER(&RegressionSM::regression_sm_start);
+  eventProcessor.schedule_in(this, t);
+}
+
+void RegressionSM::child_done(int astatus) {
+  { 
+    MUTEX_LOCK(l, mutex, this_ethread());
+    if (pending_action) {
+      pending_action->cancel();
+      pending_action = 0;
+    }
+    ink_assert(nwaiting > 0);
+    --nwaiting;
+    set_status(astatus);
+  }
+}
+
+int RegressionSM::regression_sm_waiting(int event, void *data) {
+  if (!nwaiting) {
+    done(REGRESSION_TEST_NOT_RUN);
+    delete this;
+  }
+  else
+    ((Event*)data)->schedule_in(REGRESSION_SM_RETRY);
+  return EVENT_CONT;
+}
+
+int RegressionSM::regression_sm_start(int event, void *data) {
+  run();
+  return EVENT_CONT;
+}
+
+RegressionSM *RegressionSM::do_sequential(RegressionSM *sm, ...) {
+  RegressionSM *new_sm = new RegressionSM(t);
+  va_list ap;
+  va_start(ap, sm);
+  new_sm->par = false;
+  new_sm->rep = false;
+  new_sm->ichild = 0;
+  new_sm->nchildren = 0;
+  new_sm->nwaiting = 0;
+  new_sm->children(new_sm->nchildren++) = sm;
+  while (1) {
+    RegressionSM *x = va_arg(ap, RegressionSM*);
+    if (!x) break;
+    new_sm->children(new_sm->nchildren++) = x;
+  }
+  new_sm->n = new_sm->nchildren;
+  va_end(ap);
+  return new_sm;
+}
+
+RegressionSM *RegressionSM::do_sequential(int an, RegressionSM *sm) {
+  RegressionSM *new_sm = new RegressionSM(t);
+  new_sm->par = false;
+  new_sm->rep = true;
+  new_sm->ichild = 0;
+  new_sm->nchildren = 1;
+  new_sm->children(0) = sm;
+  new_sm->nwaiting = 0;
+  new_sm->n = an;
+  return new_sm;
+}
+
+RegressionSM *RegressionSM::do_parallel(RegressionSM *sm, ...) {
+  RegressionSM *new_sm = new RegressionSM(t);
+  va_list ap;
+  va_start(ap, sm);
+  new_sm->par = true;
+  new_sm->rep = false;
+  new_sm->ichild = 0;
+  new_sm->nchildren = 0;
+  new_sm->nwaiting = 0;
+  new_sm->children(new_sm->nchildren++) = sm;
+  while (1) {
+    RegressionSM *x = va_arg(ap, RegressionSM*);
+    if (!x) break;
+    new_sm->children(new_sm->nchildren++) = x;
+  }
+  new_sm->n = new_sm->nchildren;
+  va_end(ap);
+  return new_sm;
+}
+
+RegressionSM *RegressionSM::do_parallel(int an, RegressionSM *sm) {
+  RegressionSM *new_sm = new RegressionSM(t);
+  new_sm->par = true;
+  new_sm->rep = true;
+  new_sm->ichild = 0;
+  new_sm->nchildren = 1;
+  new_sm->children(0) = sm;
+  new_sm->nwaiting = 0;
+  new_sm->n = an;
+  return new_sm;
+}
+
+void RegressionSM::run() {
+  {
+    MUTEX_TRY_LOCK(l, mutex, this_ethread());
+    if (!l || nwaiting)
+      pending_action = eventProcessor.schedule_in(this, REGRESSION_SM_RETRY);
+    RegressionSM *x = 0;
+    for (; ichild < n; ichild++) {
+      if (!rep)
+        x = children[ichild];
+      else {
+        if (ichild != n-1)
+          x = children[0]->clone();
+        else
+          x = children[0];
+      }
+      x->xrun(this);
+      if (!par && nwaiting)
+        goto Lretry;
+    }
+  }
+  if (!nwaiting) {
+    done(REGRESSION_TEST_NOT_RUN);
+    delete this;
+    return;
+  }
+Lretry:
+  SET_HANDLER(&RegressionSM::regression_sm_waiting);
+  pending_action = eventProcessor.schedule_in(this, REGRESSION_SM_RETRY);
+}
+
+void RegressionSM::do_run(RegressionSM *sm) {
+  par = false;
+  rep = true;
+  ichild = 0;
+  nchildren = 1;
+  children(0) = sm;
+  nwaiting = 0;
+  n = 1;
+  RegressionSM::run();
+}
+
+RegressionSM::RegressionSM(const RegressionSM &ao) {
+  RegressionSM &o = *(RegressionSM*)&ao;
+  t = o.t;
+  status = o.status;
+  pstatus = o.pstatus;
+  parent = &o;
+  nwaiting = o.nwaiting;
+  nchildren = o.nchildren;
+  for (int i = 0; i < nchildren; i++)
+    children(i) = o.children[i]->clone();
+  n = o.n;
+  ichild = o.ichild;
+  par = o.par;
+  rep = o.rep;
+  ink_assert(status == REGRESSION_TEST_INPROGRESS);
+  ink_assert(nwaiting == 0);
+  ink_assert(ichild == 0);
+  mutex = new_ProxyMutex();
+}
+
+struct ReRegressionSM1 : RegressionSM {
+  virtual void run() {
+    if (time(NULL) < 1) { // example test
+      rprintf(t,"impossible");
+      done(REGRESSION_TEST_FAILED);
+    } else
+      done(REGRESSION_TEST_PASSED);
+  }
+  ReRegressionSM1(RegressionTest *at) : RegressionSM(at) {}
+  virtual RegressionSM *clone() { return new ReRegressionSM1(*this); }
+  ReRegressionSM1(const ReRegressionSM1 &o) {
+    t = o.t;
+  }
+};
+
+struct ReRegressionSM2 : RegressionSM {
+  virtual void run() {
+    do_run(
+      do_sequential(
+        do_parallel(new ReRegressionSM1(t), new ReRegressionSM1(t), NULL),
+        do_sequential(new ReRegressionSM1(t), new ReRegressionSM1(t), NULL),
+        do_parallel(3, new ReRegressionSM1(t)),
+        do_sequential(3, new ReRegressionSM1(t)),
+        do_parallel(
+          do_sequential(2, new ReRegressionSM1(t)),
+          do_parallel(2, new ReRegressionSM1(t)),
+          NULL),
+        NULL));
+  }
+  ReRegressionSM2(RegressionTest *at) : RegressionSM(at) {}
+};
+
+REGRESSION_TEST(RegressionSM)(RegressionTest *t, int atype, int *pstatus) {
+  ReRegressionSM2 *sm = new ReRegressionSM2(t); 
+  sm->run_in(pstatus, HRTIME_SECOND);
+}
+

Added: incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.h
URL: http://svn.apache.org/viewvc/incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.h?rev=902236&view=auto
==============================================================================
--- incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.h (added)
+++ incubator/trafficserver/traffic/branches/dev/proxy/RegressionSM.h Fri Jan 22 19:25:10 2010
@@ -0,0 +1,78 @@
+/** @file
+
+  A brief file description
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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.
+ */
+
+#ifndef _RegressionSM_h
+#define _RegressionSM_h
+
+#include "I_EventSystem.h"
+
+/*
+  Regression Test Composition State Machine
+
+  See RegressionSM.cc at the end for an example
+*/
+
+struct RegressionSM : Continuation {
+
+  RegressionTest *t; // for use with rprint
+
+  virtual void run(); // replace with leaf regression
+  void done(int status = REGRESSION_TEST_NOT_RUN);
+  void run(int *pstatus);
+  void run_in(int *pstatus, ink_hrtime t);
+  void do_run(RegressionSM *sm);
+  RegressionSM *do_sequential(RegressionSM *sm, ...); // terminate list in NULL
+  RegressionSM *do_sequential(int n, RegressionSM *sm);
+  RegressionSM *do_parallel(RegressionSM *sm, ...); // terminate list in NULL
+  RegressionSM *do_parallel(int n, RegressionSM *sm);
+  virtual RegressionSM *clone() { return new RegressionSM(*this); } // for run_xxx(int n,...);
+
+  // Internal
+
+  int status;
+  int *pstatus;
+  RegressionSM *parent;
+  int nwaiting;
+  int nchildren;
+  DynArray<RegressionSM*> children;
+  int n, ichild;
+  bool par, rep;
+  Action *pending_action;
+
+  int regression_sm_start(int event, void *data);
+  int regression_sm_waiting(int event, void *data);
+  void set_status(int status);
+  void child_done(int status);
+  void xrun(RegressionSM *parent);
+
+  RegressionSM(RegressionTest *at = NULL) : 
+    t(at), status(REGRESSION_TEST_INPROGRESS),
+    pstatus(0), parent(0), nwaiting(0), nchildren(0), children(0), ichild(0), par(false), rep(false),
+    pending_action(0)
+  {
+    mutex = new_ProxyMutex();
+  }
+  RegressionSM(const RegressionSM &);
+};
+
+#endif