// File: sather_bench.sa
// Author: Subutai Ahmad
// Created: Sat Oct 27 12:03:47 1990
//-
// Benchmark class for sather
// converted to c++ Wed Oct 31 01:03:06 1990


#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>


class benchmarks {

  public:

  struct rusage rus; // r usages start
  struct rusage rue; // r usage end

  void startTiming() { getrusage(RUSAGE_SELF,&rus); }
  void finishTiming() { getrusage(RUSAGE_SELF,&rue); }
  void reportTiming() { 
    struct timeval utime;
    float utimef;
    struct timeval stime;
    float stimef;

    /* user time */
    utime.tv_sec = rue.ru_utime.tv_sec - rus.ru_utime.tv_sec ;
    if ( rue.ru_utime.tv_usec < rus.ru_utime.tv_usec ) {
      utime.tv_sec--;
      utime.tv_usec = 1000000l - rus.ru_utime.tv_usec +
	rue.ru_utime.tv_usec;
    } else
      utime.tv_usec = rue.ru_utime.tv_usec -
	rus.ru_utime.tv_usec ;
    utimef = (float)utime.tv_sec + (float)utime.tv_usec/1e6;
    /* system time */
    stime.tv_sec = rue.ru_stime.tv_sec - rus.ru_stime.tv_sec ;
    if ( rue.ru_stime.tv_usec < rus.ru_stime.tv_usec ) {
      stime.tv_sec--;
      stime.tv_usec = 1000000l - rus.ru_stime.tv_usec +
	rue.ru_stime.tv_usec;
    } else
      stime.tv_usec = rue.ru_stime.tv_usec -
	rus.ru_stime.tv_usec ;

    stimef = (float)stime.tv_sec + (float)stime.tv_usec/1e6;

    printf("User: %f System: %f CPU %f\n",
	  utimef, stimef, utimef+stimef);
  }

 public:


};


class FOO {
  public:
   int a;
   static void sf();
   virtual void vf();
   void f();
   void g(); 
   virtual void vg(); 
}; // class FOO

void FOO::sf() {}
void FOO::vf() {}
void FOO::f() {}

void FOO::g() {
  a = 23;
}

void FOO::vg() {
  a = 23;
}


class SATHER_BENCH { 

  public:

  benchmarks bm;

  SATHER_BENCH() {}

  void array_bench(int count);
  void funcall1(int count);
  void funcall2(int count);
  void dispatch_bench(int count);
  void assign1(int count);
  void assign2(int count);

  
  void main(char *args[]) {
    int b = atoi(args[1]);
    int count = atoi(args[2]);
    switch (b) {
      case 1:  bm.startTiming(); array_bench(count); bm.finishTiming(); break;
      case 2:  bm.startTiming(); funcall1(count); bm.finishTiming(); break;
      case 3:  bm.startTiming(); funcall2(count); bm.finishTiming(); break;
      case 4:  bm.startTiming(); dispatch_bench(count); bm.finishTiming(); break;
      case 5:  bm.startTiming(); assign1(count); bm.finishTiming(); break;
      case 6:  bm.startTiming(); assign2(count); bm.finishTiming(); break;
      default: fprintf(stderr,"Error, bad opt\n"); ::exit(1); break;
    }
    bm.reportTiming();
  }

};


void SATHER_BENCH::array_bench(int count) {
  int i=0;
  int *a = new int[count];
  while (i<count) {
    a[i] = i;
    i++;
  }
}

void SATHER_BENCH::funcall1(int count) {
  // times calls of the form CLASS::routine
  int i = 0;
  while (i<count) { 
    FOO::sf(); FOO::sf(); FOO::sf(); FOO::sf(); FOO::sf();
    FOO::sf(); FOO::sf(); FOO::sf(); FOO::sf(); FOO::sf();
    i++;
  }
}

void SATHER_BENCH::funcall2(int count) {
  // -- times non-dispatched function calls
  int i=0; 
  FOO f;
  while (i<count) { 
    f.f(); f.f(); f.f(); f.f(); f.f();
    f.f(); f.f(); f.f(); f.f(); f.f();
    i++;
  }
}


void SATHER_BENCH::dispatch_bench(int count) {
  // -- dispatched routine calls
  int i=0; 
  FOO *f;
  f = new FOO;
  while (i<count) {
    f->vf(); f->vf(); f->vf(); f->vf(); f->vf();
    f->vf(); f->vf(); f->vf(); f->vf(); f->vf();
    i++;
  }
}


void SATHER_BENCH::assign1(int count) {
  // assignment within non-dispatched calls
  int i=0; 
  FOO f;
  while (i<count) {
    f.g(); f.g(); f.g(); f.g(); f.g();
    f.g(); f.g(); f.g(); f.g(); f.g();
    i++;
  }
}


void SATHER_BENCH::assign2(int count) {
  // assignment with dispacthed calls
  int i=0; 
  FOO *f;
  f = new FOO;
  while (i<count) {
    f->vg(); f->vg(); f->vg(); f->vg(); f->vg();
    f->vg(); f->vg(); f->vg(); f->vg(); f->vg();
    i++;
  }
}
   
main(int argc,char *argv[])
{
  SATHER_BENCH sb;
  sb.main(argv);
}









