2 * Copyright (c) 1996 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
49 extern void histDataCallBack(sampleValue*, timeStamp, int, int, void*, bool);
50 extern void histFoldCallBack(timeStamp, void*, bool);
53 extern void traceDataCallBack(void*, int, void*);
55 metric::metric(T_dyninstRPC::metricInfo i){
57 if(allMetrics.defines(i.name)) return;
61 info.developerMode = i.developerMode;
62 info.unitstype = i.unitstype;
63 info.aggregate = i.aggregate;
64 info.handle = metrics.size();
66 allMetrics[i.name] = met;
70 const T_dyninstRPC::metricInfo *metric::getInfo(metricHandle handle) {
72 if(handle < metrics.size()){
73 metric *met = metrics[handle];
74 return(met->getInfo());
81 const char *metric::getName(metricHandle handle){
82 if(handle < metrics.size()){
83 metric *met = metrics[handle];
84 return(met->info.name.string_of());
91 const metricHandle *metric::find(const string iName){
92 if(allMetrics.defines(iName)){
93 return(&(allMetrics[iName])->info.handle);
100 metric *metric::getMetric(metricHandle handle){
101 if(handle < metrics.size()){
102 return(metrics[handle]);
109 vector<string> *metric::allMetricNames(bool all){
111 vector<string> *temp = new vector<string>;
113 tunableBooleanConstant developerMode =
114 tunableConstantRegistry::findBoolTunableConstant(
116 bool developerModeActive = developerMode.getValue();
117 for(unsigned i=0; i < metrics.size(); i++){
118 metric *met = metrics[i];
119 if (all || developerModeActive) {
120 string name = met->getName();
123 else if (!met->isDeveloperMode()) {
124 string name = met->getName();
131 vector<met_name_id> *metric::allMetricNamesIds(bool all){
133 vector<met_name_id> *temp = new vector<met_name_id>;
135 tunableBooleanConstant developerMode =
136 tunableConstantRegistry::findBoolTunableConstant(
138 bool developerModeActive = developerMode.getValue();
140 for(unsigned i=0; i < metrics.size(); i++){
141 metric *met = metrics[i];
142 if (all || developerModeActive) {
143 next.name = met->getName();
144 next.id = met->getHandle();
147 else if (!met->isDeveloperMode()) {
148 next.name = met->getName();
149 next.id = met->getHandle();
156 metricInstance::metricInstance(resourceListHandle rl,
159 aggSample((metric::getMetric(m)->getAggregate())) {
163 //metric *mp = metric::getMetric(m);
164 //sample.aggOp = mp->getAggregate();
167 persistent_data = false;
168 persistent_collection = false;
169 phase_persistent_data = false;
170 currEnablesWaiting = 0;
171 globalEnablesWaiting = 0;
173 currently_enabling = false;
174 metricInstance::curr_phase_id = ph;
176 allMetricInstances[id] = this;
178 // trace data streams
182 metricInstance::~metricInstance() {
183 for(unsigned i=0; i < components.size(); i++){
184 delete (components[i]);
186 // for(unsigned j=0; j < parts.size(); j++){
187 // delete (parts[j]);
189 for(unsigned k=0; k < old_data.size(); k++){
190 delete (old_data[k]);
192 if (data) delete(data);
193 if (global_data) delete(global_data);
194 // remove metricInstace from list of allMetricsInstances
195 allMetricInstances.undef(id);
198 int metricInstance::getArchiveValues(sampleValue *buckets,int numOfBuckets,
199 int first,phaseHandle phase_id){
201 // find histogram associated with phase_id
202 for(unsigned i = 0; i < old_data.size(); i++){
203 if((old_data[i])->phaseId == phase_id){
204 if((old_data[i])->data)
205 return((old_data[i])->data->getBuckets(buckets,
206 numOfBuckets,first));
212 int metricInstance::getSampleValues(sampleValue *buckets,int numOfBuckets,
213 int first,phaseType phase){
215 if(phase == CurrentPhase){
216 if (!data) return (-1);
217 return(data->getBuckets(buckets, numOfBuckets, first));
220 if (!global_data) return (-1);
221 return(global_data->getBuckets(buckets, numOfBuckets, first));
227 // write out all data for a single histogram to specified file
228 // this routine assumes that fptr points to a valid file open for writing!
231 metricInstance::saveAllData (ofstream& fptr, phaseType ph)
233 // first locate the histogram
236 if (ph == GlobalPhase) {
238 width = global_bucket_width;
241 width = curr_bucket_width;
244 // histogram not created yet for this MI
248 int numBins = hdata->getNumBins();
249 sampleValue *buckets = new sampleValue [numBins];
250 unsigned count = hdata->getBuckets(buckets, numBins, 0);
251 // write header info: datatype, numBuckets, bucketWidth
252 fptr << numBins << " " << width << endl;
253 // write all data values
254 for (unsigned k = 0; k < count; k++) {
255 fptr << string(buckets[k]) << endl;
258 if (ph == CurrentPhase) {
259 // save archived data, if any
260 for (unsigned i = 0; i < old_data.size(); i++) {
261 hdata = (old_data[i])->data;
263 count = hdata->getBuckets(buckets, numBins, 0);
264 // header info: numBuckets, bucketWidth
265 fptr << numBins << " " << width << endl;
267 for (unsigned k = 0; k < count; k++) {
268 fptr << buckets[k] << endl;
277 metricInstance *metricInstance::getMI(metricInstanceHandle mh){
280 bool found = allMetricInstances.find(mh, mih);
287 // TODO: remove asserts
288 void metricInstance::dataDisable(){
290 assert(!users.size());
291 assert(!global_users.size());
292 for(unsigned i=0; i < components.size(); i++){
293 aggSample.removeComponent(components[i]->sample);
294 delete (components[i]); // this disables data collection
296 components.resize(0);
297 // deleteing components deletes parts as well
299 // num_procs_per_part.resize(0);
301 // if data is persistent this must be cleared
302 // sample.firstSampleReceived = false;
303 assert(!components.size());
304 // assert(!parts.size());
307 void metricInstance::removeCurrUser(perfStreamHandle ps){
309 // remove ps from vector of users
310 unsigned size = users.size();
311 for(unsigned i=0; i < size; i++){
313 users[i] = users[size-1];
314 users.resize(size-1);
315 assert(users.size() < size);
316 // decrease ps's data buffer size
317 performanceStream::removeCurrentUser(ps);
322 void metricInstance::removeGlobalUser(perfStreamHandle ps){
324 // remove ps from vector of users
325 unsigned size = global_users.size();
326 for(unsigned i=0; i < size; i++){
327 if(global_users[i] == ps){
328 global_users[i] = global_users[size-1];
329 global_users.resize(size-1);
330 assert(global_users.size() < size);
331 // decrease ps's data buffer size
332 performanceStream::removeGlobalUser(ps);
337 // trace data streams
338 void metricInstance::removeTraceUser(perfStreamHandle ps){
340 // remove ps from vector of users
341 unsigned size = trace_users.size();
342 for(unsigned i=0; i < size; i++){
343 if(trace_users[i] == ps){
344 trace_users[i] = trace_users[size-1];
345 trace_users.resize(size-1);
346 assert(trace_users.size() < size);
347 // decrease ps's data buffer size
348 performanceStream::removeTraceUser(ps);
353 // returns true if histogram really was deleted
354 bool metricInstance::deleteCurrHistogram(){
356 // if curr histogram exists and there are no users delete
357 if(!(users.size()) && data) {
365 metricInstance *metricInstance::find(metricHandle mh, resourceListHandle rh){
368 dictionary_hash_iter<metricInstanceHandle,metricInstance *>
369 allMI(allMetricInstances);
370 metricInstanceHandle handle;
372 while(allMI.next(handle,mi)){
373 if((mi->getMetricHandle() == mh) && (mi->getFocusHandle() == rh)){
381 // clears the persistent_data flag and deletes any histograms without
382 // subscribers. The values for num_global_hists and num_curr_hists are
383 // not changed because these are for active histograms, and this routine
384 // should not delete any histograms that are active.
385 // returns true if the metric instance can be deleted
387 bool metricInstance::clearPersistentData(){
389 phase_persistent_data = false;
390 // if there are no outstanding enables for this MI and the flag was set
391 if(persistent_data && !globalEnablesWaiting && !currEnablesWaiting){
392 // if persistent collection is false then may need to delete data
393 if(!persistent_collection){
394 // if there are no current subscribers delete curr. hist and
395 // archieved histograms
396 if(users.size() == 0){
401 // delete any archived histograms
402 for(unsigned k=0; k < old_data.size(); k++){
403 delete (old_data[k]);
407 // if there are no curr. or global data subscribers and if
408 // persistent_collection is false then delete the metric instance
410 if((global_users.size() == 0) && global_data){
413 persistent_data = false;
419 persistent_data = false;
423 bool metricInstance::addComponent(component *new_comp){
425 paradynDaemon *new_daemon = new_comp->getDaemon();
426 for (unsigned i=0; i < components.size(); i++){
427 if((components[i])->getDaemon() == new_daemon) return false;
429 components += new_comp;
430 new_comp->sample = aggSample.newComponent();
434 // remove the component correspondent to daemon
435 // If there are no more componets, flush aggregate samples,
436 // and notify clients.
437 bool metricInstance::removeComponent(paradynDaemon *daemon) {
438 unsigned size = components.size();
439 for (unsigned u = 0; u < size; u++) {
440 if (components[u]->getDaemon() == daemon) {
441 aggSample.removeComponent(components[u]->sample);
442 delete (components[u]);
444 components[u] = components[size-1];
446 components.resize(size-1);
448 // the last component was removed
449 // flush aggregate samples
450 struct sampleInterval ret;
451 ret = aggSample.aggregateValues();
453 assert(ret.end >= 0.0);
454 assert(ret.start >= 0.0);
455 assert(ret.end >= ret.start);
456 enabledTime += ret.end - ret.start;
457 addInterval(ret.start, ret.end, ret.value, false);
458 ret = aggSample.aggregateValues();
468 bool metricInstance::addPart(sampleInfo *new_part){
470 u_int new_size = num_procs_per_part.size() + 1;
471 num_procs_per_part.resize(new_size);
472 assert(parts.size() == num_procs_per_part.size());
477 // stops currentPhase data collection for all metricInstances
478 void metricInstance::stopAllCurrentDataCollection(phaseHandle last_phase_id) {
480 dictionary_hash_iter<metricInstanceHandle,metricInstance *>
481 allMI(allMetricInstances);
482 metricInstanceHandle handle;
485 vector<metricInstance *> remove_list;
487 while(allMI.next(handle,mi)){
491 assert(remove_list.size() == allMetricInstances.size());
492 for(unsigned i=0; i < remove_list.size(); i++){
494 mi->currEnablesWaiting = 0;
495 // remove all users from user list
497 assert(!(mi->users.size()));
498 // clear the persistent flag that is only valid within a phase
499 mi->clearPhasePersistentData();
501 bool was_deleted = false;
502 // if persistent data archive curr histogram
503 if(mi->isDataPersistent()){
505 if(mi->data->isActive()) was_deleted = true;
506 mi->data->clearActive();
507 mi->data->clearFoldOnInactive();
508 ArchiveType *temp = new ArchiveType;
509 temp->data = mi->data;
510 temp->phaseId = last_phase_id;
511 mi->old_data += temp;
516 else { // else delete curr histogram
517 was_deleted = mi->deleteCurrHistogram();
521 // if not persistent collection
522 if (!(mi->isCollectionPersistent())){
523 // really disable data collection
524 if((mi->isEnabled()) && (!mi->globalUsersCount())) {
525 // disable MI data collection
527 if(!(mi->isDataPersistent())){
530 metricInstance::decrNumGlobalHists();
533 metricInstance::decrNumCurrHists();
535 else { // else, create new curr histogram with empty curr users list
536 metric *m = metric::getMetric(mi->met);
537 mi->newCurrDataCollection(m->getStyle(),
542 // reduce each performance stream's buffer size by the number
543 // of current MI's it will no longer be receiving data for
544 performanceStream::removeAllCurrUsers();
548 void metricInstance::addCurrentUser(perfStreamHandle p) {
550 for(unsigned i=0; i < users.size(); i++){
551 if(users[i] == p) return;
554 assert(users.size());
555 // update buffersize for perfStream
556 performanceStream::addCurrentUser(p);
559 void metricInstance::addGlobalUser(perfStreamHandle p) {
561 for(unsigned i=0; i < global_users.size(); i++){
562 if(global_users[i] == p) return;
565 assert(global_users.size());
566 // update buffersize for perfStream
567 performanceStream::addGlobalUser(p);
570 // trace data streams
571 void metricInstance::addTraceUser(perfStreamHandle p) {
573 for(unsigned i=0; i < trace_users.size(); i++){
574 if(trace_users[i] == p) return;
577 assert(trace_users.size());
578 // update buffersize for perfStream
579 performanceStream::addTraceUser(p);
583 // trace data streams
584 void metricInstance::newTraceDataCollection(dataCallBack2 dcb) {
585 assignTraceFunc(dcb);
588 void metricInstance::newGlobalDataCollection(metricStyle style,
592 // histogram has already been created
594 global_data->setActive();
595 global_data->clearFoldOnInactive();
598 // call constructor for start time 0.0
599 global_data = new Histogram(style, dcb, fcb, this, 1);
602 void metricInstance::newCurrDataCollection(metricStyle style,
606 // histogram has already been created
609 data->clearFoldOnInactive();
612 // create new histogram
613 timeStamp start_time = phaseInfo::GetLastPhaseStart();
614 if(start_time == 0.0) {
615 data = new Histogram(style, dcb, fcb, this, 0);
617 phaseInfo::setCurrentBucketWidth(data->getBucketWidth());
621 data = new Histogram(start_time, style, dcb, fcb, this, 0);
623 phaseInfo::setCurrentBucketWidth(data->getBucketWidth());