diff probes.c @ 50:8f7141a9272e

Added VMS__malloc and probes, and major re-factoring to separate mallocs
author Me
date Sat, 30 Oct 2010 20:54:36 -0700
parents
children f59cfa31a579
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/probes.c	Sat Oct 30 20:54:36 2010 -0700
     1.3 @@ -0,0 +1,342 @@
     1.4 +/*
     1.5 + * Copyright 2010  OpenSourceStewardshipFoundation
     1.6 + *
     1.7 + * Licensed under BSD
     1.8 + */
     1.9 +
    1.10 +#include <stdio.h>
    1.11 +#include <stdlib.h>
    1.12 +#include <malloc.h>
    1.13 +#include <sys/time.h>
    1.14 +
    1.15 +#include "VMS.h"
    1.16 +#include "Queue_impl/BlockingQueue.h"
    1.17 +#include "Histogram/Histogram.h"
    1.18 +
    1.19 +
    1.20 +//================================ STATS ====================================
    1.21 +
    1.22 +inline TSCount getTSCount()
    1.23 + { unsigned int low, high;
    1.24 +   TSCount  out;
    1.25 +
    1.26 +   saveTimeStampCountInto( low, high );
    1.27 +   out = high;
    1.28 +   out = (out << 32) + low;
    1.29 +   return out;
    1.30 + }
    1.31 +
    1.32 +
    1.33 +
    1.34 +//====================  Probes =================
    1.35 +#ifdef STATS__USE_TSC_PROBES
    1.36 +int32
    1.37 +VMS__create_single_interval_probe( char *nameStr )
    1.38 + { IntervalProbe *newProbe;
    1.39 +   int32 idx;
    1.40 +
    1.41 +   newProbe = malloc( sizeof(IntervalProbe) );
    1.42 +   newProbe->nameStr = nameStr;  //caller frees if not constant on stack
    1.43 +   newProbe->hist = NULL;
    1.44 +   idx = addToDynArray( newProbe, _VMSMasterEnv->dynIntervalProbesInfo );
    1.45 +   return idx;
    1.46 + }
    1.47 +
    1.48 +int32
    1.49 +VMS__create_histogram_probe( int32 numBins, float32 startValue,
    1.50 +                             float32 binWidth, char *nameStr )
    1.51 + { IntervalProbe *newProbe;
    1.52 +   int32 idx;
    1.53 +   FloatHist *hist;
    1.54 +
    1.55 +   idx = VMS__create_single_interval_probe( nameStr );
    1.56 +   newProbe =  _VMSMasterEnv->intervalProbes[ idx ];
    1.57 +
    1.58 +   hist =  makeFloatHistogram( numBins, startValue, binWidth );
    1.59 +   newProbe->hist = hist;
    1.60 +   return idx;
    1.61 + }
    1.62 +
    1.63 +void
    1.64 +VMS_impl__record_interval_start_in_probe( int32 probeID )
    1.65 + { IntervalProbe *probe;
    1.66 +
    1.67 +   probe = _VMSMasterEnv->intervalProbes[ probeID ];
    1.68 +   probe->startStamp = getTSCount();
    1.69 + }
    1.70 +
    1.71 +void
    1.72 +VMS_impl__record_interval_end_in_probe( int32 probeID )
    1.73 + { IntervalProbe *probe;
    1.74 +   TSCount endStamp;
    1.75 +
    1.76 +   endStamp = getTSCount();
    1.77 +
    1.78 +   probe = _VMSMasterEnv->intervalProbes[ probeID ];
    1.79 +   probe->endStamp = endStamp;
    1.80 +
    1.81 +   if( probe->hist != NULL )
    1.82 +    { TSCount interval = probe->endStamp - probe->startStamp;
    1.83 +         //if the interval is sane, then add to histogram
    1.84 +      if( interval < probe->hist->endOfRange * 10 )
    1.85 +         addToFloatHist( interval, probe->hist );
    1.86 +    }
    1.87 + }
    1.88 +
    1.89 +void
    1.90 +VMS_impl__print_stats_of_probe( int32 probeID )
    1.91 + { IntervalProbe *probe;
    1.92 +
    1.93 +   probe = _VMSMasterEnv->intervalProbes[ probeID ];
    1.94 +
    1.95 +   if( probe->hist == NULL )
    1.96 +    {
    1.97 +      printf("probe: %s, interval: %.6lf\n", probe->nameStr,probe->interval);
    1.98 +    }
    1.99 +
   1.100 +   else
   1.101 +    {
   1.102 +      printf( "probe: %s\n", probe->nameStr );
   1.103 +      printFloatHist( probe->hist );
   1.104 +    }
   1.105 + }
   1.106 +#else
   1.107 +#ifdef STATS__USE_DBL_PROBES
   1.108 +
   1.109 +/*
   1.110 + * In practice, probe operations are called from the app, from inside slaves
   1.111 + *  -- so have to be sure each probe is single-VP owned, and be sure that
   1.112 + *  any place common structures are modified it's done inside the master.
   1.113 + * So -- the only place common structures are modified is during creation.
   1.114 + *  after that, all mods are to individual instances.
   1.115 + *
   1.116 + * Thniking perhaps should change the semantics to be that probes are
   1.117 + *  attached to the virtual processor -- and then everything is guaranteed
   1.118 + *  to be isolated -- except then can't take any intervals that span VPs,
   1.119 + *  and would have to transfer the probes to Master env when VP dissipates..
   1.120 + *  gets messy..
   1.121 + *
   1.122 + * For now, just making so that probe creation causes a suspend, so that
   1.123 + *  the dynamic array in the master env is only modified from the master
   1.124 + * 
   1.125 + */
   1.126 +IntervalProbe *
   1.127 +create_generic_probe( char *nameStr, VirtProcr *animPr )
   1.128 + { IntervalProbe *newProbe;
   1.129 +   int32 idx;
   1.130 +   VMSSemReq reqData;
   1.131 +
   1.132 +   reqData.reqType  = createProbe;
   1.133 +   reqData.nameStr  = nameStr;
   1.134 +
   1.135 +   VMS__send_VMSSem_request( reqData, animPr );
   1.136 +
   1.137 +   return animPr->dataReturnedFromReq;
   1.138 + }
   1.139 +
   1.140 +int32
   1.141 +VMS_impl__record_time_point_into_new_probe( char *nameStr, VirtProcr *animPr )
   1.142 + { IntervalProbe *newProbe;
   1.143 +   struct timeval *startStamp;
   1.144 +   float64 startSecs;
   1.145 +
   1.146 +   newProbe           = create_generic_probe( nameStr, animPr );
   1.147 +   newProbe->endSecs  = 0;
   1.148 +
   1.149 +   gettimeofday( &(newProbe->startStamp), NULL);
   1.150 +
   1.151 +      //turn into a double
   1.152 +   startStamp = &(newProbe->startStamp);
   1.153 +   startSecs = startStamp->tv_sec + ( startStamp->tv_usec / 1000000.0 );
   1.154 +   newProbe->startSecs = startSecs;
   1.155 +
   1.156 +   return newProbe->probeID;
   1.157 + }
   1.158 +
   1.159 +int32
   1.160 +VMS_impl__create_single_interval_probe( char *nameStr, VirtProcr *animPr )
   1.161 + { IntervalProbe *newProbe;
   1.162 +
   1.163 +   newProbe = create_generic_probe( nameStr, animPr );
   1.164 +   
   1.165 +   return newProbe->probeID;
   1.166 + }
   1.167 +
   1.168 +int32
   1.169 +VMS_impl__create_histogram_probe( int32   numBins, float64    startValue,
   1.170 +               float64 binWidth, char   *nameStr, VirtProcr *animPr )
   1.171 + { IntervalProbe *newProbe;
   1.172 +   DblHist *hist;
   1.173 +
   1.174 +   newProbe = create_generic_probe( nameStr, animPr );
   1.175 +   
   1.176 +   hist =  makeDblHistogram( numBins, startValue, binWidth );
   1.177 +   newProbe->hist = hist;
   1.178 +   return newProbe->probeID;
   1.179 + }
   1.180 +
   1.181 +void
   1.182 +VMS_impl__index_probe_by_its_name( int32 probeID, VirtProcr *animPr )
   1.183 + { IntervalProbe *probe;
   1.184 +
   1.185 +   //TODO: fix this To be in Master -- race condition
   1.186 +   probe = _VMSMasterEnv->intervalProbes[ probeID ];
   1.187 +
   1.188 +   addValueIntoTable(probe->nameStr, probe, _VMSMasterEnv->probeNameHashTbl);
   1.189 + }
   1.190 +
   1.191 +IntervalProbe *
   1.192 +VMS_impl__get_probe_by_name( char *probeName, VirtProcr *animPr )
   1.193 + {
   1.194 +   //TODO: fix this To be in Master -- race condition
   1.195 +   return getValueFromTable( probeName, _VMSMasterEnv->probeNameHashTbl );
   1.196 + }
   1.197 +
   1.198 +
   1.199 +/*Everything is local to the animating procr, so no need for request, do
   1.200 + * work locally, in the anim Pr
   1.201 + */
   1.202 +void
   1.203 +VMS_impl__record_sched_choice_into_probe( int32 probeID, VirtProcr *animatingPr )
   1.204 + { IntervalProbe *probe;
   1.205 + 
   1.206 +   probe = _VMSMasterEnv->intervalProbes[ probeID ];
   1.207 +   probe->schedChoiceWasRecorded = TRUE;
   1.208 +   probe->coreNum = animatingPr->coreAnimatedBy;
   1.209 +   probe->procrID = animatingPr->procrID;
   1.210 +   probe->procrCreateSecs = 0;
   1.211 + }
   1.212 +
   1.213 +/*Everything is local to the animating procr, so no need for request, do
   1.214 + * work locally, in the anim Pr
   1.215 + */
   1.216 +void
   1.217 +VMS_impl__record_interval_start_in_probe( int32 probeID )
   1.218 + { IntervalProbe *probe;
   1.219 +
   1.220 +   probe = _VMSMasterEnv->intervalProbes[ probeID ];
   1.221 +   gettimeofday( &(probe->startStamp), NULL );
   1.222 + }
   1.223 +
   1.224 +
   1.225 +/*Everything is local to the animating procr, so no need for request, do
   1.226 + * work locally, in the anim Pr
   1.227 + */
   1.228 +void
   1.229 +VMS_impl__record_interval_end_in_probe( int32 probeID )
   1.230 + { IntervalProbe *probe;
   1.231 +   struct timeval *endStamp, *startStamp;
   1.232 +   double startSecs, endSecs;
   1.233 +
   1.234 +      //possible seg-fault if array resized by diff core right after this
   1.235 +      // one gets probe..?  Something like that?  Might be safe.. don't care
   1.236 +   probe = _VMSMasterEnv->intervalProbes[ probeID ];
   1.237 +   gettimeofday( &(probe->endStamp), NULL);
   1.238 +
   1.239 +      //now turn into an interval held in a double
   1.240 +   startStamp = &(probe->startStamp);
   1.241 +   endStamp   = &(probe->endStamp);
   1.242 +
   1.243 +   startSecs = startStamp->tv_sec + ( startStamp->tv_usec / 1000000.0 );
   1.244 +   endSecs   = endStamp->tv_sec   + ( endStamp->tv_usec / 1000000.0 );
   1.245 +
   1.246 +   probe->interval  = endSecs - startSecs;
   1.247 +   probe->startSecs = startSecs;
   1.248 +   probe->endSecs   = endSecs;
   1.249 +
   1.250 +   if( probe->hist != NULL )
   1.251 +    {
   1.252 +         //if the interval is sane, then add to histogram
   1.253 +      if( probe->interval < probe->hist->endOfRange * 10 )
   1.254 +         addToDblHist( probe->interval, probe->hist );
   1.255 +    }
   1.256 + }
   1.257 +
   1.258 +void
   1.259 +print_probe_helper( IntervalProbe *probe )
   1.260 + {
   1.261 +   printf( "\nprobe: %s, ",  probe->nameStr );
   1.262 +   
   1.263 +   if( probe->schedChoiceWasRecorded )
   1.264 +    { printf( "coreNum: %d, procrID: %d, procrCreated: %.6lf | ",
   1.265 +              probe->coreNum, probe->procrID, probe->procrCreateSecs );
   1.266 +    }
   1.267 +
   1.268 +   if( probe->endSecs == 0 ) //just a single point in time
   1.269 +    {
   1.270 +      printf( " time point: %.6lf\n",
   1.271 +              probe->startSecs - _VMSMasterEnv->createPtInSecs );
   1.272 +    }
   1.273 +   else if( probe->hist == NULL ) //just an interval
   1.274 +    {
   1.275 +      printf( " startSecs: %.6lf, interval: %.6lf\n", 
   1.276 +         probe->startSecs - _VMSMasterEnv->createPtInSecs, probe->interval);
   1.277 +    }
   1.278 +   else  //a full histogram of intervals
   1.279 +    {
   1.280 +      printDblHist( probe->hist );
   1.281 +    }
   1.282 + }
   1.283 +
   1.284 +//TODO: change so pass around pointer to probe instead of its array-index..
   1.285 +// will eliminate chance for timing of resize to cause problems with the
   1.286 +// lookup -- even though don't think it actually can cause problems..
   1.287 +// there's no need to pass index around -- have hash table for names, and
   1.288 +// only need it once, then have ptr to probe..  the thing about enum the
   1.289 +// index and use that as name is clunky in practice -- just hash.
   1.290 +void
   1.291 +VMS_impl__print_stats_of_probe( int32 probeID )
   1.292 + { IntervalProbe *probe;
   1.293 +
   1.294 +   probe = _VMSMasterEnv->intervalProbes[ probeID ];
   1.295 +
   1.296 +   print_probe_helper( probe );
   1.297 + }
   1.298 +
   1.299 +
   1.300 +
   1.301 +void
   1.302 +generic_print_probe( void *_probe )
   1.303 + { IntervalProbe *probe;
   1.304 +
   1.305 +   probe = (IntervalProbe *)_probe;
   1.306 +   print_probe_helper( probe );
   1.307 + }
   1.308 +
   1.309 +void
   1.310 +VMS_impl__print_stats_of_all_probes()
   1.311 + { IntervalProbe *probe;
   1.312 +
   1.313 +   forAllInDynArrayDo( _VMSMasterEnv->dynIntervalProbesInfo,
   1.314 +                       &generic_print_probe );
   1.315 +   fflush( stdout );
   1.316 + }
   1.317 +#endif
   1.318 +#endif
   1.319 +
   1.320 +/* Junk left over from when trying the different ways to get time stamps..
   1.321 +         struct timeval tim;
   1.322 +         gettimeofday(&tim, NULL);
   1.323 +         double t1=tim.tv_sec+(tim.tv_usec/1000000.0);
   1.324 +
   1.325 +         clock_t startClockStamp = clock();
   1.326 +
   1.327 +         TSCount startMultStamp = getTSCount();
   1.328 +*/
   1.329 +
   1.330 +/*
   1.331 +         TSCount endMultStamp = getTSCount();
   1.332 +
   1.333 +         dividerParams->numTSCsToExe = endMultStamp - startMultStamp;
   1.334 +         printf("\ntime to execute: %d\n", endMultStamp - startMultStamp);
   1.335 +
   1.336 +         //==================================================================
   1.337 +         clock_t endClockStamp = clock();
   1.338 +         printf("%.4lf seconds of processing\n",
   1.339 +                (endClockStamp - startClockStamp)/(double)CLOCKS_PER_SEC);
   1.340 +
   1.341 +         //==================================================================
   1.342 +         gettimeofday(&tim, NULL);
   1.343 +         double t2=tim.tv_sec+(tim.tv_usec/1000000.0);
   1.344 +         printf("%.6lf seconds elapsed\n", t2-t1);
   1.345 +*/