1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
30 #include <sys/param.h>
36 #include "DbeCacheMap.h"
37 #include "DefaultHandler.h"
38 #include "DefaultMap2D.h"
41 #include "SAXParser.h"
42 #include "SAXParserFactory.h"
43 #include "StringBuilder.h"
44 #include "DbeSession.h"
45 #include "DbeThread.h"
46 #include "Application.h"
47 #include "CallStack.h"
48 #include "Experiment.h"
49 #include "Exp_Layout.h"
50 #include "DataStream.h"
51 #include "Expression.h"
54 #include "LoadObject.h"
60 #include "StringMap.h"
61 #include "UserLabel.h"
63 #include "dbe_types.h"
65 #include "cc_libcollector.h"
75 struct Experiment::UIDnode
82 struct Experiment::RawFramePacket
92 parseTStamp (const char *s
)
94 hrtime_t ts
= (hrtime_t
) 0;
95 ts
= (hrtime_t
) atoi (s
) * NANOSEC
;
98 ts
+= (hrtime_t
) atoi (s
+ 1);
102 class Experiment::ExperimentFile
114 ExperimentFile (Experiment
*_exp
, const char *_fname
);
117 bool open (bool new_open
= false);
140 int bufsz
, ef_status
;
144 class Experiment::ExperimentHandler
: public DefaultHandler
148 ExperimentHandler (Experiment
*_exp
);
149 ~ExperimentHandler ();
154 void startElement (char *uri
, char *localName
, char *qName
, Attributes
*attrs
);
155 void endElement (char *uri
, char *localName
, char *qName
);
156 void characters (char *ch
, int start
, int length
);
159 ignorableWhitespace (char*, int, int) { }
161 error (SAXParseException
*e
);
186 static int toInt (Attributes
*attrs
, const char *atr
);
187 static char*toStr (Attributes
*attrs
, const char *atr
);
188 void pushElem (Element
);
193 Vector
<Element
> *stack
;
194 Module
*dynfuncModule
;
195 DataDescriptor
*dDscr
;
196 PacketDescriptor
*pDscr
;
205 // HTableSize is the size of smemHTable and instHTable
206 // omazur: both HTableSize and the hash function haven't been tuned;
207 static const int HTableSize
= 8192;
209 //-------------------------------------------------- Experiment file handler
211 Experiment::ExperimentFile::ExperimentFile (Experiment
*_exp
, const char *_fname
)
217 ef_status
= EF_NOT_OPENED
;
219 fname
= dbe_sprintf (NTXT ("%s/%s"), exp
->expt_name
, _fname
);
222 Experiment::ExperimentFile::~ExperimentFile ()
230 Experiment::ExperimentFile::open (bool new_open
)
234 fh
= fopen64 (fname
, NTXT ("r"));
237 ef_status
= EF_FAILURE
;
240 ef_status
= EF_OPENED
;
244 fseeko64 (fh
, offset
, SEEK_SET
);
250 Experiment::ExperimentFile::fgets ()
255 buffer
= (char *) xmalloc (bufsz
);
256 buffer
[bufsz
- 1] = (char) 1; // sentinel
258 char *res
= ::fgets (buffer
, bufsz
, fh
);
261 while (buffer
[bufsz
- 1] == (char) 0)
263 int newsz
= bufsz
+ 1024;
264 char *newbuf
= (char *) xmalloc (newsz
);
265 memcpy (newbuf
, buffer
, bufsz
);
268 buffer
[newsz
- 1] = (char) 1; // sentinel
269 // we don't care about fgets result here
270 ::fgets (buffer
+ bufsz
- 1, newsz
- bufsz
+ 1, fh
);
277 Experiment::ExperimentFile::close ()
281 offset
= ftello64 (fh
);
283 ef_status
= EF_CLOSED
;
289 //-------------------------------------------------- Experiment XML parser
291 Experiment::ExperimentHandler::toInt (Attributes
*attrs
, const char *atr
)
293 const char *str
= attrs
->getValue (atr
);
294 return str
? atoi (str
) : 0;
298 Experiment::ExperimentHandler::toStr (Attributes
*attrs
, const char *atr
)
300 const char *str
= attrs
->getValue (atr
);
301 return dbe_strdup (str
? str
: NTXT (""));
304 Experiment::ExperimentHandler::ExperimentHandler (Experiment
*_exp
)
307 stack
= new Vector
<Element
>;
309 dynfuncModule
= NULL
;
319 Experiment::ExperimentHandler::~ExperimentHandler ()
326 Experiment::ExperimentHandler::endDocument ()
328 { // SP_TAG_STATE should be used to describe states, but it isn't
330 DataDescriptor
*dd
= exp
->getDataDescriptor (DATA_HEAP
);
333 PropDescr
*prop
= dd
->getProp (PROP_HTYPE
);
336 char * stateNames
[HEAPTYPE_LAST
] = HEAPTYPE_STATE_STRINGS
;
337 char * stateUNames
[HEAPTYPE_LAST
] = HEAPTYPE_STATE_USTRINGS
;
338 for (int ii
= 0; ii
< HEAPTYPE_LAST
; ii
++)
339 prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
342 dd
= exp
->getDataDescriptor (DATA_IOTRACE
);
345 PropDescr
*prop
= dd
->getProp (PROP_IOTYPE
);
348 char * stateNames
[IOTRACETYPE_LAST
] = IOTRACETYPE_STATE_STRINGS
;
349 char * stateUNames
[IOTRACETYPE_LAST
] = IOTRACETYPE_STATE_USTRINGS
;
350 for (int ii
= 0; ii
< IOTRACETYPE_LAST
; ii
++)
351 prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
358 Experiment::ExperimentHandler::pushElem (Element elem
)
361 stack
->append (curElem
);
365 Experiment::ExperimentHandler::popElem ()
367 curElem
= stack
->remove (stack
->size () - 1);
371 Experiment::ExperimentHandler::startElement (char*, char*, char *qName
, Attributes
*attrs
)
373 DEBUG_CODE
if (DEBUG_SAXPARSER
) dump_startElement (qName
, attrs
);
374 if (strcmp (qName
, SP_TAG_EXPERIMENT
) == 0)
376 pushElem (EL_EXPERIMENT
);
377 const char *str
= attrs
->getValue (NTXT ("version"));
380 int major
= atoi (str
);
381 str
= strchr (str
, '.');
382 int minor
= str
? atoi (str
+ 1) : 0;
383 exp
->exp_maj_version
= major
;
384 exp
->exp_min_version
= minor
;
385 if (major
!= SUNPERF_VERNUM
|| minor
!= SUNPERF_VERNUM_MINOR
)
387 // not the current version, see if we support some earlier versions
391 sb
.sprintf (GTXT ("*** Error: experiment %s version %d.%d is not supported;\nuse the version of the tools that recorded the experiment to read it"),
392 exp
->get_expt_name (), major
, minor
);
393 // exp->errorq->append( new Emsg(CMSG_FATAL, sb) );
394 exp
->status
= FAILURE
;
396 throw new SAXException (sb
.toString ());
401 else if (strcmp (qName
, SP_TAG_COLLECTOR
) == 0)
402 pushElem (EL_COLLECTOR
);
403 else if (strcmp (qName
, SP_TAG_SETTING
) == 0)
406 pushElem (EL_SETTING
);
407 const char *str
= attrs
->getValue (SP_JCMD_LIMIT
);
411 exp
->coll_params
.limit
= atoi (str
);
413 str
= attrs
->getValue (SP_JCMD_BLKSZ
);
417 exp
->blksz
= strtol (str
, NULL
, 0);
419 str
= attrs
->getValue (SP_JCMD_STACKBASE
);
423 exp
->stack_base
= strtoull (str
, NULL
, 0);
425 str
= attrs
->getValue (SP_JCMD_HWC_DEFAULT
);
429 exp
->hwc_default
= true;
431 str
= attrs
->getValue (SP_JCMD_NOIDLE
);
435 exp
->commentq
->append (new Emsg (CMSG_COMMENT
,
436 GTXT ("*** Note: experiment does not have events from idle CPUs")));
438 str
= attrs
->getValue (SP_JCMD_FAKETIME
);
442 exp
->timelineavail
= false;
443 exp
->commentq
->append (new Emsg (CMSG_COMMENT
,
444 GTXT ("*** Note: experiment does not have timestamps; timeline unavailable")));
446 str
= attrs
->getValue (SP_JCMD_DELAYSTART
);
450 exp
->coll_params
.start_delay
= xstrdup (str
);
452 str
= attrs
->getValue (SP_JCMD_TERMINATE
);
456 exp
->coll_params
.terminate
= xstrdup (str
);
458 str
= attrs
->getValue (SP_JCMD_PAUSE_SIG
);
462 exp
->coll_params
.pause_sig
= xstrdup (str
);
464 str
= attrs
->getValue (SP_JCMD_SAMPLE_PERIOD
);
468 exp
->coll_params
.sample_periodic
= 1;
469 exp
->coll_params
.sample_timer
= atoi (str
);
471 str
= attrs
->getValue (SP_JCMD_SAMPLE_SIG
);
475 exp
->coll_params
.sample_sig
= str
;
477 str
= attrs
->getValue (SP_JCMD_SRCHPATH
);
482 sb
.sprintf (GTXT ("Search path: %s"), str
);
483 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
484 dbeSession
->add_classpath ((char*) str
);
486 str
= attrs
->getValue (SP_JCMD_LINETRACE
);
490 exp
->coll_params
.linetrace
= xstrdup (str
);
493 str
= attrs
->getValue (SP_JCMD_COLLENV
);
498 sb
.sprintf (GTXT (" Data collection environment variable: %s"), str
);
499 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
503 int nattr
= attrs
->getLength ();
506 fprintf (stderr
, "XXX Unexpected setting found; %d attributes:\n",
508 for (int k
= 0; k
< nattr
; k
++)
510 const char *qn
= attrs
->getQName (k
);
511 const char *vl
= attrs
->getValue (k
);
512 fprintf (stderr
, "XXX %s = %s\n", qn
, vl
);
516 // END OF CODE FOR "setting"
518 else if (strcmp (qName
, SP_TAG_SYSTEM
) == 0)
520 pushElem (EL_SYSTEM
);
521 const char *str
= attrs
->getValue (NTXT ("hostname"));
523 exp
->hostname
= xstrdup (str
);
524 str
= attrs
->getValue (NTXT ("os"));
527 exp
->os_version
= xstrdup (str
);
528 /* For Linux experiments expect sparse thread ID's */
529 if (strncmp (str
, NTXT ("SunOS"), 5) != 0)
530 exp
->sparse_threads
= true;
532 str
= attrs
->getValue (NTXT ("arch"));
535 if (strcmp (str
, "i86pc") == 0 || strcmp (str
, "i686") == 0
536 || strcmp (str
, "x86_64") == 0)
537 exp
->platform
= Intel
;
538 else if (strcmp (str
, "aarch64") == 0)
539 exp
->platform
= Aarch64
;
540 else if (strcmp (str
, "riscv64") == 0)
541 exp
->platform
= RISCV
;
543 exp
->platform
= Sparc
;
544 exp
->need_swap_endian
= (DbeSession::platform
== Sparc
) ?
545 (exp
->platform
!= Sparc
) : (exp
->platform
== Sparc
);
546 exp
->architecture
= xstrdup (str
);
548 str
= attrs
->getValue (NTXT ("pagesz"));
550 exp
->page_size
= atoi (str
);
551 str
= attrs
->getValue (NTXT ("npages"));
553 exp
->npages
= atoi (str
);
555 else if (strcmp (qName
, SP_TAG_POWERM
) == 0)
556 pushElem (EL_POWERM
);
557 else if (strcmp (qName
, SP_TAG_FREQUENCY
) == 0)
559 pushElem (EL_FREQUENCY
);
560 const char *str
= attrs
->getValue (NTXT ("clk"));
562 exp
->set_clock (atoi (str
));
563 // check for frequency_scaling or turbo_mode recorded from libcollector under dbx
564 str
= attrs
->getValue (NTXT ("frequency_scaling"));
565 const char *str2
= attrs
->getValue (NTXT ("turbo_mode"));
566 if (str
!= NULL
|| str2
!= NULL
)
569 else if (strcmp (qName
, SP_TAG_CPU
) == 0)
573 const char *str
= attrs
->getValue (NTXT ("clk"));
576 int clk
= atoi (str
);
577 if (exp
->maxclock
== 0)
584 if (clk
< exp
->minclock
)
586 if (clk
> exp
->maxclock
)
591 // check for frequency_scaling or turbo_mode
592 str
= attrs
->getValue (NTXT ("frequency_scaling"));
593 const char *str2
= attrs
->getValue (NTXT ("turbo_mode"));
594 if (str
!= NULL
|| str2
!= NULL
)
597 else if (strcmp (qName
, SP_TAG_PROCESS
) == 0)
599 pushElem (EL_PROCESS
);
600 const char *str
= attrs
->getValue (NTXT ("wsize"));
603 int wsz
= atoi (str
);
609 str
= attrs
->getValue (NTXT ("pid"));
611 exp
->pid
= atoi (str
);
612 str
= attrs
->getValue (NTXT ("ppid"));
614 exp
->ppid
= atoi (str
);
615 str
= attrs
->getValue (NTXT ("pgrp"));
617 exp
->pgrp
= atoi (str
);
618 str
= attrs
->getValue (NTXT ("sid"));
620 exp
->sid
= atoi (str
);
621 str
= attrs
->getValue (NTXT ("cwd"));
623 exp
->ucwd
= xstrdup (str
);
624 str
= attrs
->getValue (NTXT ("pagesz"));
626 exp
->page_size
= atoi (str
);
628 else if (strcmp (qName
, SP_TAG_EVENT
) == 0)
629 { // Start code for event
631 hrtime_t ts
= (hrtime_t
) 0;
632 const char *str
= attrs
->getValue (NTXT ("tstamp"));
634 ts
= parseTStamp (str
);
635 str
= attrs
->getValue (NTXT ("kind"));
638 if (strcmp (str
, SP_JCMD_RUN
) == 0)
641 exp
->exp_start_time
= ts
;
642 str
= attrs
->getValue (NTXT ("time"));
644 exp
->start_sec
= atoll (str
);
645 str
= attrs
->getValue (NTXT ("pid"));
647 exp
->pid
= atoi (str
);
648 str
= attrs
->getValue (NTXT ("ppid"));
650 exp
->ppid
= atoi (str
);
651 str
= attrs
->getValue (NTXT ("pgrp"));
653 exp
->pgrp
= atoi (str
);
654 str
= attrs
->getValue (NTXT ("sid"));
656 exp
->sid
= atoi (str
);
657 exp
->status
= Experiment::INCOMPLETE
;
659 else if (strcmp (str
, SP_JCMD_ARCHIVE
) == 0)
662 sb
.sprintf (GTXT ("gprofng-archive run: XXXXXXX"));
663 exp
->pprocq
->append (new Emsg (CMSG_WARN
, sb
));
665 else if (strcmp (str
, SP_JCMD_SAMPLE
) == 0)
667 exp
->update_last_event (exp
->exp_start_time
+ ts
); // ts is 0-based
668 str
= attrs
->getValue (NTXT ("id"));
669 int id
= str
? atoi (str
) : -1;
670 char *label
= dbe_strdup (attrs
->getValue (NTXT ("label")));
671 exp
->process_sample_cmd (NULL
, ts
, id
, label
);
673 else if (strcmp (str
, SP_JCMD_EXIT
) == 0)
675 // don't treat EXIT as an event w.r.t. last_event and non_paused_time
676 exp
->status
= Experiment::SUCCESS
;
678 else if (strcmp (str
, SP_JCMD_CERROR
) == 0)
681 str
= attrs
->getValue (NTXT ("id"));
686 str
= attrs
->getValue (NTXT ("ec"));
692 else if (strcmp (str
, SP_JCMD_CWARN
) == 0)
695 str
= attrs
->getValue (NTXT ("id"));
699 else if (strcmp (str
, SP_JCMD_COMMENT
) == 0)
701 mkind
= CMSG_COMMENT
;
702 str
= attrs
->getValue (NTXT ("id"));
705 str
= attrs
->getValue (NTXT ("text"));
709 sb
.sprintf (GTXT ("*** Note: %s"), str
);
710 exp
->commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
713 else if (strcmp (str
, SP_JCMD_DESC_START
) == 0)
715 char *variant
= toStr (attrs
, NTXT ("variant"));
716 char *lineage
= toStr (attrs
, NTXT ("lineage"));
717 int follow
= toInt (attrs
, NTXT ("follow"));
718 char *msg
= toStr (attrs
, NTXT ("msg"));
719 exp
->process_desc_start_cmd (NULL
, ts
, variant
, lineage
, follow
, msg
);
721 else if (strcmp (str
, SP_JCMD_DESC_STARTED
) == 0)
723 char *variant
= toStr (attrs
, NTXT ("variant"));
724 char *lineage
= toStr (attrs
, NTXT ("lineage"));
725 int follow
= toInt (attrs
, NTXT ("follow"));
726 char *msg
= toStr (attrs
, NTXT ("msg"));
727 exp
->process_desc_started_cmd (NULL
, ts
, variant
, lineage
, follow
, msg
);
729 else if (strcmp (str
, SP_JCMD_EXEC_START
) == 0)
731 // if successful, acts like experiment termination - no "exit" entry will follow
732 exp
->update_last_event (exp
->exp_start_time
+ ts
); // ts is 0-based
733 char *variant
= toStr (attrs
, NTXT ("variant"));
734 char *lineage
= toStr (attrs
, NTXT ("lineage"));
735 int follow
= toInt (attrs
, NTXT ("follow"));
736 char *msg
= toStr (attrs
, NTXT ("msg"));
737 exp
->process_desc_start_cmd (NULL
, ts
, variant
, lineage
, follow
, msg
);
738 exp
->exec_started
= true;
740 else if (strcmp (str
, SP_JCMD_EXEC_ERROR
) == 0)
742 exp
->update_last_event (exp
->exp_start_time
+ ts
); // ts is 0-based
743 char *variant
= toStr (attrs
, NTXT ("variant"));
744 char *lineage
= toStr (attrs
, NTXT ("lineage"));
745 int follow
= toInt (attrs
, NTXT ("follow"));
746 char *msg
= toStr (attrs
, NTXT ("msg"));
747 exp
->process_desc_started_cmd (NULL
, ts
, variant
, lineage
, follow
, msg
);
748 exp
->exec_started
= false;
750 else if (strcmp (str
, SP_JCMD_JTHRSTART
) == 0)
752 char *name
= dbe_strdup (attrs
->getValue (NTXT ("name")));
753 char *grpname
= dbe_strdup (attrs
->getValue (NTXT ("grpname")));
754 char *prntname
= dbe_strdup (attrs
->getValue (NTXT ("prntname")));
755 str
= attrs
->getValue (NTXT ("tid"));
756 uint64_t tid
= str
? strtoull (str
, NULL
, 0) : 0;
757 str
= attrs
->getValue (NTXT ("jthr"));
758 Vaddr jthr
= str
? strtoull (str
, NULL
, 0) : 0;
759 str
= attrs
->getValue (NTXT ("jenv"));
760 Vaddr jenv
= str
? strtoull (str
, NULL
, 0) : 0;
761 exp
->process_jthr_start_cmd (NULL
, name
, grpname
, prntname
, tid
, jthr
, jenv
, ts
);
763 else if (strcmp (str
, SP_JCMD_JTHREND
) == 0)
765 str
= attrs
->getValue (NTXT ("tid"));
766 uint64_t tid
= str
? strtoull (str
, NULL
, 0) : 0;
767 str
= attrs
->getValue (NTXT ("jthr"));
768 Vaddr jthr
= str
? strtoull (str
, NULL
, 0) : 0;
769 str
= attrs
->getValue (NTXT ("jenv"));
770 Vaddr jenv
= str
? strtoull (str
, NULL
, 0) : 0;
771 exp
->process_jthr_end_cmd (NULL
, tid
, jthr
, jenv
, ts
);
773 else if (strcmp (str
, SP_JCMD_GCEND
) == 0)
775 if (exp
->getDataDescriptor (DATA_GCEVENT
) == NULL
)
776 exp
->newDataDescriptor (DATA_GCEVENT
);
777 exp
->process_gc_end_cmd (ts
);
779 else if (strcmp (str
, SP_JCMD_GCSTART
) == 0)
781 if (exp
->getDataDescriptor (DATA_GCEVENT
) == NULL
)
782 exp
->newDataDescriptor (DATA_GCEVENT
);
783 exp
->process_gc_start_cmd (ts
);
785 else if (strcmp (str
, SP_JCMD_PAUSE
) == 0)
787 if (exp
->resume_ts
!= MAX_TIME
)
789 // data collection was active
790 hrtime_t delta
= ts
- exp
->resume_ts
;
791 exp
->non_paused_time
+= delta
;
792 exp
->resume_ts
= MAX_TIME
; // collection is paused
795 str
= attrs
->getValue (NTXT ("name"));
797 sb
.sprintf (GTXT ("Pause: %ld.%09ld"), (long) (ts
/ NANOSEC
),
798 (long) (ts
% NANOSEC
));
800 sb
.sprintf (GTXT ("Pause (%s): %ld.%09ld"), str
,
801 (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
));
802 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
804 else if (strcmp (str
, SP_JCMD_RESUME
) == 0)
806 if (exp
->resume_ts
== MAX_TIME
)
807 // data collection was paused
808 exp
->resume_ts
= ts
; // remember start time
810 sb
.sprintf (GTXT ("Resume: %ld.%09ld"), (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
));
811 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
812 if (exp
->exp_start_time
== ZERO_TIME
)
813 exp
->exp_start_time
= ts
;
815 else if (strcmp (str
, SP_JCMD_THREAD_PAUSE
) == 0)
817 str
= attrs
->getValue (NTXT ("tid"));
818 uint64_t tid
= str
? strtoull (str
, NULL
, 0) : 0;
820 sb
.sprintf (GTXT ("Thread %llu pause: %ld.%09ld"), (unsigned long long) tid
,
821 (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
));
822 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
824 else if (strcmp (str
, SP_JCMD_THREAD_RESUME
) == 0)
826 str
= attrs
->getValue (NTXT ("tid"));
827 uint64_t tid
= str
? strtoull (str
, NULL
, 0) : 0;
829 sb
.sprintf (GTXT ("Thread %llu resume: %ld.%09ld"), (unsigned long long) tid
,
830 (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
));
831 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
833 else if (strcmp (str
, NTXT ("map")) == 0)
835 ts
+= exp
->exp_start_time
;
836 str
= attrs
->getValue (NTXT ("vaddr"));
837 Vaddr vaddr
= str
? strtoull (str
, NULL
, 0) : 0;
838 str
= attrs
->getValue (NTXT ("size"));
839 int msize
= str
? atoi (str
) : 0;
840 str
= attrs
->getValue (NTXT ("foffset"));
841 int64_t offset
= str
? strtoll (str
, NULL
, 0) : 0;
842 str
= attrs
->getValue (NTXT ("modes"));
843 int64_t modes
= str
? strtoll (str
, NULL
, 0) : 0;
844 str
= attrs
->getValue (NTXT ("chksum"));
847 chksum
= Elf::normalize_checksum (strtoll (str
, NULL
, 0));
848 char *name
= (char *) attrs
->getValue (NTXT ("name"));
849 str
= attrs
->getValue (NTXT ("object"));
850 if (strcmp (str
, NTXT ("segment")) == 0)
852 if (strcmp (name
, NTXT ("LinuxKernel")) == 0)
853 exp
->process_Linux_kernel_cmd (ts
);
855 exp
->process_seg_map_cmd (NULL
, ts
, vaddr
, msize
, 0,
856 offset
, modes
, chksum
, name
);
858 else if (strcmp (str
, NTXT ("function")) == 0)
860 exp
->process_fn_load_cmd (dynfuncModule
, name
, vaddr
, msize
, ts
);
861 dynfuncModule
= NULL
;
863 else if (strcmp (str
, NTXT ("dynfunc")) == 0)
865 if (dynfuncModule
== NULL
)
867 dynfuncModule
= dbeSession
->createModule (exp
->get_dynfunc_lo (DYNFUNC_SEGMENT
), name
);
868 dynfuncModule
->flags
|= MOD_FLAG_UNKNOWN
;
869 dynfuncModule
->set_file_name (dbe_strdup (dynfuncModule
->getMainSrc ()->get_name ()));
871 (void) exp
->create_dynfunc (dynfuncModule
,
872 (char*) attrs
->getValue (NTXT ("funcname")), vaddr
, msize
);
874 else if (strcmp (str
, NTXT ("jcm")) == 0)
876 str
= attrs
->getValue (NTXT ("methodId"));
877 Vaddr mid
= str
? strtoull (str
, NULL
, 0) : 0;
878 exp
->process_jcm_load_cmd (NULL
, mid
, vaddr
, msize
, ts
);
881 else if (strcmp (str
, NTXT ("unmap")) == 0)
883 ts
+= exp
->exp_start_time
;
884 str
= attrs
->getValue (NTXT ("vaddr"));
885 Vaddr vaddr
= str
? strtoull (str
, NULL
, 0) : 0;
886 exp
->process_seg_unmap_cmd (NULL
, ts
, vaddr
);
889 // end of code for event
891 else if (strcmp (qName
, SP_TAG_PROFILE
) == 0)
893 pushElem (EL_PROFILE
);
894 const char *str
= attrs
->getValue (NTXT ("name"));
897 if (strcmp (str
, NTXT ("profile")) == 0)
899 exp
->coll_params
.profile_mode
= 1;
900 str
= attrs
->getValue (NTXT ("numstates"));
902 exp
->coll_params
.lms_magic_id
= atoi (str
);
903 str
= attrs
->getValue (NTXT ("ptimer"));
905 exp
->coll_params
.ptimer_usec
= atoi (str
); // microseconds
907 PropDescr
*mstate_prop
= NULL
;
908 char * stateNames
[/*LMS_NUM_STATES*/] = LMS_STATE_STRINGS
;
909 char * stateUNames
[/*LMS_NUM_STATES*/] = LMS_STATE_USTRINGS
;
911 dDscr
= exp
->newDataDescriptor (DATA_CLOCK
);
912 PropDescr
*prop
= new PropDescr (PROP_MSTATE
, NTXT ("MSTATE"));
913 prop
->uname
= dbe_strdup (GTXT ("Thread state"));
914 prop
->vtype
= TYPE_UINT32
;
915 // (states added below)
916 dDscr
->addProperty (prop
);
919 prop
= new PropDescr (PROP_NTICK
, NTXT ("NTICK"));
920 prop
->uname
= dbe_strdup (GTXT ("Number of Profiling Ticks"));
921 prop
->vtype
= TYPE_UINT32
;
922 dDscr
->addProperty (prop
);
925 switch (exp
->coll_params
.lms_magic_id
)
927 case LMS_MAGIC_ID_SOLARIS
:
928 exp
->register_metric (Metric::CP_TOTAL
);
929 exp
->register_metric (Metric::CP_TOTAL_CPU
);
930 exp
->register_metric (Metric::CP_LMS_USER
);
931 exp
->register_metric (Metric::CP_LMS_SYSTEM
);
932 exp
->register_metric (Metric::CP_LMS_TRAP
);
933 exp
->register_metric (Metric::CP_LMS_DFAULT
);
934 exp
->register_metric (Metric::CP_LMS_TFAULT
);
935 exp
->register_metric (Metric::CP_LMS_KFAULT
);
936 exp
->register_metric (Metric::CP_LMS_STOPPED
);
937 exp
->register_metric (Metric::CP_LMS_WAIT_CPU
);
938 exp
->register_metric (Metric::CP_LMS_SLEEP
);
939 exp
->register_metric (Metric::CP_LMS_USER_LOCK
);
940 for (int ii
= 0; ii
< LMS_NUM_SOLARIS_MSTATES
; ii
++)
941 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
943 case LMS_MAGIC_ID_ERKERNEL_KERNEL
:
944 exp
->register_metric (Metric::CP_KERNEL_CPU
);
946 int ii
= LMS_KERNEL_CPU
;
947 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
950 case LMS_MAGIC_ID_ERKERNEL_USER
:
951 exp
->register_metric (Metric::CP_TOTAL_CPU
);
952 exp
->register_metric (Metric::CP_LMS_USER
);
953 exp
->register_metric (Metric::CP_LMS_SYSTEM
);
955 int ii
= LMS_KERNEL_CPU
;
956 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
958 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
960 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
963 case LMS_MAGIC_ID_LINUX
:
964 exp
->register_metric (Metric::CP_TOTAL_CPU
);
966 int ii
= LMS_LINUX_CPU
;
967 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
975 else if (strcmp (str
, NTXT ("heaptrace")) == 0)
977 exp
->coll_params
.heap_mode
= 1;
978 exp
->leaklistavail
= true;
979 exp
->heapdataavail
= true;
980 exp
->register_metric (Metric::HEAP_ALLOC_BYTES
);
981 exp
->register_metric (Metric::HEAP_ALLOC_CNT
);
982 exp
->register_metric (Metric::HEAP_LEAK_BYTES
);
983 exp
->register_metric (Metric::HEAP_LEAK_CNT
);
984 dDscr
= exp
->newDataDescriptor (DATA_HEAP
);
986 else if (strcmp (str
, NTXT ("iotrace")) == 0)
988 exp
->coll_params
.io_mode
= 1;
989 exp
->iodataavail
= true;
990 exp
->register_metric (Metric::IO_READ_TIME
);
991 exp
->register_metric (Metric::IO_READ_BYTES
);
992 exp
->register_metric (Metric::IO_READ_CNT
);
993 exp
->register_metric (Metric::IO_WRITE_TIME
);
994 exp
->register_metric (Metric::IO_WRITE_BYTES
);
995 exp
->register_metric (Metric::IO_WRITE_CNT
);
996 exp
->register_metric (Metric::IO_OTHER_TIME
);
997 exp
->register_metric (Metric::IO_OTHER_CNT
);
998 exp
->register_metric (Metric::IO_ERROR_TIME
);
999 exp
->register_metric (Metric::IO_ERROR_CNT
);
1000 dDscr
= exp
->newDataDescriptor (DATA_IOTRACE
);
1002 else if (strcmp (str
, NTXT ("synctrace")) == 0)
1004 exp
->coll_params
.sync_mode
= 1;
1005 str
= attrs
->getValue (NTXT ("threshold"));
1007 exp
->coll_params
.sync_threshold
= atoi (str
);
1008 str
= attrs
->getValue (NTXT ("scope"));
1010 exp
->coll_params
.sync_scope
= atoi (str
);
1011 else // Should only happen with old experiments; use the old default
1012 exp
->coll_params
.sync_scope
= SYNCSCOPE_NATIVE
| SYNCSCOPE_JAVA
;
1013 exp
->register_metric (Metric::SYNC_WAIT_TIME
);
1014 exp
->register_metric (Metric::SYNC_WAIT_COUNT
);
1015 dDscr
= exp
->newDataDescriptor (DATA_SYNCH
);
1017 else if (strcmp (str
, NTXT ("omptrace")) == 0)
1019 exp
->coll_params
.omp_mode
= 1;
1020 dDscr
= exp
->newDataDescriptor (DATA_OMP
, DDFLAG_NOSHOW
);
1022 else if (strcmp (str
, NTXT ("hwcounter")) == 0)
1024 str
= attrs
->getValue (NTXT ("cpuver"));
1025 int cpuver
= str
? atoi (str
) : 0;
1026 char *counter
= dbe_strdup (attrs
->getValue (NTXT ("hwcname")));
1027 char *int_name
= dbe_strdup (attrs
->getValue (NTXT ("int_name"))); // may not be present
1028 str
= attrs
->getValue (NTXT ("interval"));
1029 int interval
= str
? atoi (str
) : 0;
1030 str
= attrs
->getValue (NTXT ("tag"));
1031 int tag
= str
? atoi (str
) : 0;
1032 str
= attrs
->getValue (NTXT ("memop"));
1033 int i_tpc
= str
? atoi (str
) : 0;
1034 char *modstr
= dbe_strdup (attrs
->getValue (NTXT ("modstr")));
1035 exp
->process_hwcounter_cmd (NULL
, cpuver
, counter
, int_name
, interval
, tag
, i_tpc
, modstr
);
1036 dDscr
= exp
->newDataDescriptor (DATA_HWC
);
1038 else if (strcmp (str
, NTXT ("hwsimctr")) == 0)
1040 int cpuver
= toInt (attrs
, NTXT ("cpuver"));
1041 char *hwcname
= dbe_strdup (attrs
->getValue (NTXT ("hwcname")));
1042 char *int_name
= dbe_strdup (attrs
->getValue (NTXT ("int_name")));
1043 char *metric
= dbe_strdup (attrs
->getValue (NTXT ("metric")));
1044 int reg
= toInt (attrs
, NTXT ("reg_num"));
1045 int interval
= toInt (attrs
, NTXT ("interval"));
1046 int timecvt
= toInt (attrs
, NTXT ("timecvt"));
1047 int i_tpc
= toInt (attrs
, NTXT ("memop"));
1048 int tag
= toInt (attrs
, NTXT ("tag"));
1049 exp
->process_hwsimctr_cmd (NULL
, cpuver
, hwcname
, int_name
, metric
, reg
,
1050 interval
, timecvt
, i_tpc
, tag
);
1051 dDscr
= exp
->newDataDescriptor (DATA_HWC
);
1053 else if (strcmp (str
, NTXT ("dversion")) == 0)
1054 exp
->dversion
= dbe_strdup (attrs
->getValue (NTXT ("version")));
1055 else if (strcmp (str
, NTXT ("jprofile")) == 0)
1057 exp
->has_java
= true;
1058 str
= attrs
->getValue (NTXT ("jversion"));
1060 exp
->jversion
= xstrdup (str
);
1062 else if (strcmp (str
, NTXT ("datarace")) == 0)
1064 exp
->coll_params
.race_mode
= 1;
1065 exp
->racelistavail
= true;
1066 str
= attrs
->getValue (NTXT ("scheme"));
1067 exp
->coll_params
.race_stack
= str
? atoi (str
) : 0;
1068 exp
->register_metric (Metric::RACCESS
);
1069 dDscr
= exp
->newDataDescriptor (DATA_RACE
);
1071 else if (strcmp (str
, NTXT ("deadlock")) == 0)
1073 exp
->coll_params
.deadlock_mode
= 1;
1074 exp
->deadlocklistavail
= true;
1075 exp
->register_metric (Metric::DEADLOCKS
);
1076 dDscr
= exp
->newDataDescriptor (DATA_DLCK
);
1079 /* XXX -- obsolete tag, but is still written to experiments */
1080 else if (strcmp (qName
, SP_TAG_DATAPTR
) == 0)
1082 pushElem (EL_DATAPTR
);
1085 else if (strcmp (qName
, SP_TAG_PROFDATA
) == 0)
1087 pushElem (EL_PROFDATA
);
1088 // SS12 HWC experiments are not well structured
1089 const char *fname
= attrs
->getValue (NTXT ("fname"));
1090 if (fname
&& strcmp (fname
, SP_HWCNTR_FILE
) == 0)
1091 dDscr
= exp
->newDataDescriptor (DATA_HWC
);
1093 else if (strcmp (qName
, SP_TAG_PROFPCKT
) == 0)
1095 pushElem (EL_PROFPCKT
);
1096 const char *str
= attrs
->getValue (NTXT ("kind")); // see Pckt_type
1097 int kind
= str
? atoi (str
) : -1;
1100 if (exp
->coll_params
.omp_mode
== 1)
1102 if (kind
== OMP_PCKT
)
1103 dDscr
= exp
->newDataDescriptor (DATA_OMP
, DDFLAG_NOSHOW
);
1104 else if (kind
== OMP2_PCKT
)
1105 dDscr
= exp
->newDataDescriptor (DATA_OMP2
, DDFLAG_NOSHOW
);
1106 else if (kind
== OMP3_PCKT
)
1107 dDscr
= exp
->newDataDescriptor (DATA_OMP3
, DDFLAG_NOSHOW
);
1108 else if (kind
== OMP4_PCKT
)
1109 dDscr
= exp
->newDataDescriptor (DATA_OMP4
, DDFLAG_NOSHOW
);
1110 else if (kind
== OMP5_PCKT
)
1111 dDscr
= exp
->newDataDescriptor (DATA_OMP5
, DDFLAG_NOSHOW
);
1113 pDscr
= exp
->newPacketDescriptor (kind
, dDscr
);
1116 else if (strcmp (qName
, SP_TAG_FIELD
) == 0)
1118 pushElem (EL_FIELD
);
1121 const char *name
= attrs
->getValue (NTXT ("name"));
1124 int propID
= dbeSession
->registerPropertyName (name
);
1125 propDscr
= new PropDescr (propID
, name
);
1126 FieldDescr
*fldDscr
= new FieldDescr (propID
, name
);
1128 const char *str
= attrs
->getValue (NTXT ("type"));
1131 if (strcmp (str
, NTXT ("INT32")) == 0)
1132 fldDscr
->vtype
= TYPE_INT32
;
1133 else if (strcmp (str
, NTXT ("UINT32")) == 0)
1134 fldDscr
->vtype
= TYPE_UINT32
;
1135 else if (strcmp (str
, NTXT ("INT64")) == 0)
1136 fldDscr
->vtype
= TYPE_INT64
;
1137 else if (strcmp (str
, NTXT ("UINT64")) == 0)
1138 fldDscr
->vtype
= TYPE_UINT64
;
1139 else if (strcmp (str
, NTXT ("STRING")) == 0)
1140 fldDscr
->vtype
= TYPE_STRING
;
1141 else if (strcmp (str
, NTXT ("DOUBLE")) == 0)
1142 fldDscr
->vtype
= TYPE_DOUBLE
;
1143 else if (strcmp (str
, NTXT ("DATE")) == 0)
1145 fldDscr
->vtype
= TYPE_DATE
;
1146 const char *fmt
= attrs
->getValue (NTXT ("format"));
1147 fldDscr
->format
= xstrdup (fmt
? fmt
: "");
1150 propDscr
->vtype
= fldDscr
->vtype
;
1152 // TYPE_DATE is converted to TYPE_UINT64 in propDscr
1153 if (fldDscr
->vtype
== TYPE_DATE
)
1154 propDscr
->vtype
= TYPE_UINT64
;
1156 // Fix some types until they are fixed in libcollector
1157 if (propID
== PROP_VIRTPC
|| propID
== PROP_PHYSPC
)
1159 if (fldDscr
->vtype
== TYPE_INT32
)
1160 propDscr
->vtype
= TYPE_UINT32
;
1161 else if (fldDscr
->vtype
== TYPE_INT64
)
1162 propDscr
->vtype
= TYPE_UINT64
;
1165 // The following props get mapped to 32-bit values in readPacket
1166 if (propID
== PROP_CPUID
|| propID
== PROP_THRID
1167 || propID
== PROP_LWPID
)
1168 propDscr
->vtype
= TYPE_UINT32
; // override experiment property
1170 str
= attrs
->getValue (NTXT ("uname"));
1172 propDscr
->uname
= xstrdup (PTXT ((char*) str
));
1173 str
= attrs
->getValue (NTXT ("noshow"));
1174 if (str
&& atoi (str
) != 0)
1175 propDscr
->flags
|= PRFLAG_NOSHOW
;
1180 sb
.sprintf (GTXT ("*** Error: data parsing failed. Log file is corrupted."));
1181 exp
->warnq
->append (new Emsg (CMSG_ERROR
, sb
));
1182 throw new SAXException (sb
.toString ());
1185 dDscr
->addProperty (propDscr
);
1186 str
= attrs
->getValue (NTXT ("offset"));
1188 fldDscr
->offset
= atoi (str
);
1189 pDscr
->addField (fldDscr
);
1192 else if (strcmp (qName
, SP_TAG_STATE
) == 0)
1194 pushElem (EL_STATE
);
1195 if (propDscr
!= NULL
)
1197 const char *str
= attrs
->getValue (NTXT ("value"));
1198 int value
= str
? atoi (str
) : -1;
1199 str
= attrs
->getValue (NTXT ("name"));
1200 const char *ustr
= attrs
->getValue (NTXT ("uname"));
1201 propDscr
->addState (value
, str
, ustr
);
1204 else if (strcmp (qName
, SP_TAG_DTRACEFATAL
) == 0)
1205 pushElem (EL_DTRACEFATAL
);
1209 sb
.sprintf (GTXT ("*** Warning: unrecognized element %s"), qName
);
1210 exp
->warnq
->append (new Emsg (CMSG_WARN
, sb
));
1216 Experiment::ExperimentHandler::characters (char *ch
, int start
, int length
)
1221 exp
->cversion
= dbe_strndup (ch
+ start
, length
);
1224 exp
->process_arglist_cmd (NULL
, dbe_strndup (ch
+ start
, length
));
1228 text
= dbe_strndup (ch
+ start
, length
);
1236 Experiment::ExperimentHandler::endElement (char*, char*, char*)
1238 if (curElem
== EL_EVENT
&& mkind
!= CMSG_NONE
&& mnum
>= 0)
1242 str
= dbe_sprintf ("%s -- %s", text
!= NULL
? text
: "", strerror (mec
));
1244 str
= dbe_sprintf ("%s", text
!= NULL
? text
: "");
1245 Emsg
*msg
= new Emsg (mkind
, mnum
, str
);
1246 if (mkind
== CMSG_WARN
)
1248 if (mnum
!= COL_WARN_FSTYPE
1249 || dbeSession
->check_ignore_fs_warn () == false)
1250 exp
->warnq
->append (msg
);
1252 exp
->commentq
->append (msg
);
1254 else if (mkind
== CMSG_ERROR
|| mkind
== CMSG_FATAL
)
1255 exp
->errorq
->append (msg
);
1256 else if (mkind
== CMSG_COMMENT
)
1257 exp
->commentq
->append (msg
);
1264 else if (curElem
== EL_PROFILE
)
1266 else if (curElem
== EL_PROFPCKT
)
1268 else if (curElem
== EL_FIELD
)
1276 Experiment::ExperimentHandler::error (SAXParseException
*e
)
1279 sb
.sprintf (GTXT ("%s at line %d, column %d"),
1280 e
->getMessage (), e
->getLineNumber (), e
->getColumnNumber ());
1281 char *msg
= sb
.toString ();
1282 SAXException
*e1
= new SAXException (msg
);
1287 //-------------------------------------------------- Experiment
1289 Experiment::Experiment ()
1292 userExpId
= expIdx
= -1;
1295 children_exps
= new Vector
<Experiment
*>;
1296 loadObjs
= new Vector
<LoadObject
*>;
1297 loadObjMap
= new StringMap
<LoadObject
*>(128, 128);
1300 // Initialize configuration information.
1306 architecture
= NULL
;
1314 exp_maj_version
= 0;
1315 exp_min_version
= 0;
1320 stack_base
= 0xf0000000;
1326 hwc_default
= false;
1329 // clear HWC event stats
1333 memset (&coll_params
, 0, sizeof (coll_params
));
1339 exec_started
= false;
1340 timelineavail
= true;
1341 leaklistavail
= false;
1342 heapdataavail
= false;
1343 iodataavail
= false;
1344 dataspaceavail
= false;
1346 racelistavail
= false;
1347 deadlocklistavail
= false;
1349 tiny_threshold
= -1;
1355 gc_duration
= ZERO_TIME
;
1356 exp_start_time
= ZERO_TIME
; // not known. Wall-clock hrtime (not zero based)
1357 last_event
= ZERO_TIME
; // not known. Wall-clock hrtime (not zero based)
1358 non_paused_time
= 0; // 0 non-paused time (will sum as experiment is processed)
1359 resume_ts
= 0; // by default, collection is "resumed" (not paused) from time=0
1360 need_swap_endian
= false;
1361 exp_rel_start_time_set
= false;
1362 exp_rel_start_time
= ZERO_TIME
;
1364 hex_field_width
= 8;
1365 hw_cpuver
= CPUVER_UNDEFINED
;
1366 machinemodel
= NULL
;
1369 fndr_arch_name
= NULL
;
1370 dyntext_name
= NULL
;
1373 dataDscrs
= new Vector
<DataDescriptor
*>;
1374 for (int i
= 0; i
< DATA_LAST
; ++i
)
1375 dataDscrs
->append (NULL
);
1377 pcktDscrs
= new Vector
<PacketDescriptor
*>;
1378 blksz
= PROFILE_BUFFER_CHUNK
;
1379 jthreads
= new Vector
<JThread
*>;
1380 jthreads_idx
= new Vector
<JThread
*>;
1381 gcevents
= new Vector
<GCEvent
*>;
1382 gcevent_last_used
= (GCEvent
*) NULL
;
1383 heapUnmapEvents
= new Vector
<UnmapChunk
*>;
1385 cstackShowHide
= NULL
;
1386 frmpckts
= new Vector
<RawFramePacket
*>;
1387 typedef DefaultMap2D
<uint32_t, hrtime_t
, uint64_t> OmpMap0
;
1388 mapPRid
= new OmpMap0 (OmpMap0::Interval
);
1389 typedef DefaultMap2D
<uint32_t, hrtime_t
, void*> OmpMap
;
1390 mapPReg
= new OmpMap (OmpMap::Interval
);
1391 mapTask
= new OmpMap (OmpMap::Interval
);
1398 uidnodes
= new Vector
<UIDnode
*>;
1399 mrecs
= new Vector
<MapRecord
*>;
1400 samples
= new Vector
<Sample
*>;
1401 sample_last_used
= (Sample
*) NULL
;
1402 first_sample_label
= (char*) NULL
;
1405 resolveFrameInfo
= true;
1406 discardTiny
= false;
1410 Experiment::~Experiment ()
1413 free (coll_params
.linetrace
);
1414 for (int i
= 0; i
< MAX_HWCOUNT
; i
++)
1416 free (coll_params
.hw_aux_name
[i
]);
1417 free (coll_params
.hw_username
[i
]);
1421 free (architecture
);
1432 free (fndr_arch_name
);
1433 free (dyntext_name
);
1434 delete jthreads_idx
;
1436 delete cstackShowHide
;
1441 destroy_map (DbeFile
*, archiveMap
);
1445 delete children_exps
;
1449 free (first_sample_label
);
1450 free (machinemodel
);
1452 dataDscrs
->destroy ();
1454 pcktDscrs
->destroy ();
1456 jthreads
->destroy ();
1458 gcevents
->destroy ();
1460 heapUnmapEvents
->destroy ();
1461 delete heapUnmapEvents
;
1462 frmpckts
->destroy ();
1464 samples
->destroy ();
1469 for (long i
= 0; i
< nchunks
; i
++)
1475 Experiment::init_cache ()
1479 smemHTable
= new SegMem
*[HTableSize
];
1480 instHTable
= new DbeInstr
*[HTableSize
];
1481 for (int i
= 0; i
< HTableSize
; i
++)
1483 smemHTable
[i
] = NULL
;
1484 instHTable
[i
] = NULL
;
1486 uidHTable
= new UIDnode
*[HTableSize
];
1487 for (int i
= 0; i
< HTableSize
; i
++)
1488 uidHTable
[i
] = NULL
;
1490 cstack
= CallStack::getInstance (this);
1491 cstackShowHide
= CallStack::getInstance (this);
1498 seg_items
= new Vector
<SegMem
*>;
1499 maps
= new PRBTree ();
1500 jmaps
= NULL
; // used by JAVA_CLASSES only
1504 min_thread
= (uint64_t) - 1;
1507 min_lwp
= (uint64_t) - 1;
1510 min_cpu
= (uint64_t) - 1;
1514 commentq
= new Emsgqueue (NTXT ("commentq"));
1515 runlogq
= new Emsgqueue (NTXT ("runlogq"));
1516 errorq
= new Emsgqueue (NTXT ("errorq"));
1517 warnq
= new Emsgqueue (NTXT ("warnq"));
1518 notesq
= new Emsgqueue (NTXT ("notesq"));
1519 pprocq
= new Emsgqueue (NTXT ("pprocq"));
1522 metrics
= new Vector
<BaseMetric
*>;
1523 tagObjs
= new Vector
<Vector
<Histable
*>*>;
1524 tagObjs
->store (PROP_THRID
, new Vector
<Histable
*>);
1525 tagObjs
->store (PROP_LWPID
, new Vector
<Histable
*>);
1526 tagObjs
->store (PROP_CPUID
, new Vector
<Histable
*>);
1527 tagObjs
->store (PROP_EXPID
, new Vector
<Histable
*>);
1528 sparse_threads
= false;
1534 seg_items
->destroy ();
1538 delete[] smemHTable
;
1539 delete[] instHTable
;
1555 Vec_loop (BaseMetric
*, metrics
, index
, mtr
)
1557 dbeSession
->drop_metric (mtr
);
1560 tagObjs
->fetch (PROP_THRID
)->destroy ();
1561 tagObjs
->fetch (PROP_LWPID
)->destroy ();
1562 tagObjs
->fetch (PROP_CPUID
)->destroy ();
1563 tagObjs
->fetch (PROP_EXPID
)->destroy ();
1564 tagObjs
->destroy ();
1568 // These are the data files which can be read in parallel
1569 // for multiple sub-experiments.
1570 // Postpone calling resolve_frame_info()
1572 Experiment::read_experiment_data (bool read_ahead
)
1575 read_frameinfo_file ();
1578 resolveFrameInfo
= false;
1579 (void) get_profile_events ();
1580 resolveFrameInfo
= true;
1584 Experiment::Exp_status
1585 Experiment::open_epilogue ()
1588 // set up mapping for tagObj(PROP_EXPID)
1589 (void) mapTagValue (PROP_EXPID
, userExpId
);
1592 if (last_event
!= ZERO_TIME
)
1593 { // if last_event is known
1595 hrtime_t ts
= last_event
- exp_start_time
;
1596 sb
.sprintf (GTXT ("Experiment Ended: %ld.%09ld\nData Collection Duration: %ld.%09ld"),
1597 (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
),
1598 (long) (non_paused_time
/ NANOSEC
),
1599 (long) (non_paused_time
% NANOSEC
));
1600 runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
1603 // Check for incomplete experiment, and inform the user
1604 if (status
== INCOMPLETE
)
1606 if (exec_started
== true)
1607 // experiment ended with the exec, not abnormally
1611 char * cmnt
= GTXT ("*** Note: experiment was not closed");
1612 commentq
->append (new Emsg (CMSG_COMMENT
, cmnt
));
1613 // runlogq->append(new Emsg(CMSG_COMMENT, cmnt));
1616 // write a descriptive header for the experiment
1621 Experiment::Exp_status
1622 Experiment::open (char *path
)
1625 // Find experiment directory
1626 if (find_expdir (path
) != SUCCESS
)
1627 // message will have been queued and status set
1630 // Get creation time for experiment
1632 if (dbe_stat (path
, &st
) == 0)
1633 mtime
= st
.st_mtime
;
1635 // Read the warnings file
1638 // Open the log file
1640 if (status
== SUCCESS
&& last_event
// last event is initialized
1641 && (last_event
- exp_start_time
) / 1000000 < tiny_threshold
)
1643 // Process "tiny_threshold" (SP_ANALYZER_DISCARD_TINY_EXPERIMENTS)
1644 // At this point, we've only processed log.xml.
1645 // Note: if an experiment terminated abnormally, last_event will not yet
1646 // represent events from clock profiling and other metrics.
1647 // Other events will often have timestamps after the last log.xml entry.
1651 if (status
== FAILURE
)
1653 if (logFile
->get_status () == ExperimentFile::EF_FAILURE
)
1655 Emsg
*m
= new Emsg (CMSG_FATAL
, GTXT ("*** Error: log file in experiment cannot be read"));
1658 else if (fetch_errors () == NULL
)
1662 Emsg
*m
= new Emsg (CMSG_FATAL
, GTXT ("*** Error: log does not show target starting"));
1667 Emsg
*m
= new Emsg (CMSG_FATAL
, GTXT ("*** Error: log file in experiment could not be parsed"));
1678 GTXT ("*** Warning: system has variable clock frequency, which may cause variable execution times and inaccurate conversions of cycle counts into time."));
1679 warnq
->append (new Emsg (CMSG_WARN
, sb
));
1682 // Read the notes file
1684 read_labels_file ();
1687 // The log file shows experiment started
1688 read_java_classes_file ();
1692 // Dyntext file has to be processed after loadobjects file
1693 // as we need to be able to map (vaddr,ts) to dynamic functions.
1694 read_dyntext_file ();
1696 // Read the overview file and create samples.
1697 // Profiling data hasn't been read yet so we may have
1698 // events after the last recorded sample.
1699 // We'll create a fake sample to cover all those
1701 read_overview_file ();
1703 // Check if instruction frequency data is available
1706 // Check if OMP data is available
1712 /* XXX -- update() is a no-op now, but may be needed for auto-update */
1713 Experiment::Exp_status
1714 Experiment::update ()
1720 Experiment::append (LoadObject
*lo
)
1722 loadObjs
->append (lo
);
1723 char *obj_name
= lo
->get_pathname ();
1724 char *bname
= get_basename (obj_name
);
1725 loadObjMap
->put (obj_name
, lo
);
1726 loadObjMap
->put (bname
, lo
);
1727 if (lo
->flags
& SEG_FLAG_EXE
)
1728 loadObjMap
->put (COMP_EXE_NAME
, lo
);
1732 Experiment::read_notes_file ()
1737 char *fname
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_NOTES_FILE
);
1738 FILE *f
= fopen (fname
, NTXT ("r"));
1742 if (!dbeSession
->is_interactive ())
1744 m
= new Emsg (CMSG_COMMENT
, NTXT ("Notes:"));
1750 char str
[MAXPATHLEN
];
1751 char *e
= fgets (str
, ((int) sizeof (str
)) - 1, f
);
1754 if (!dbeSession
->is_interactive ())
1756 m
= new Emsg (CMSG_COMMENT
,
1757 "============================================================");
1762 size_t i
= strlen (str
);
1763 if (i
> 0 && str
[i
- 1] == '\n')
1764 // remove trailing nl
1766 m
= new Emsg (CMSG_COMMENT
, str
);
1773 Experiment::save_notes (char* text
, bool handle_file
)
1778 char *fname
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_NOTES_FILE
);
1779 fnotes
= fopen (fname
, NTXT ("w"));
1783 (void) fprintf (fnotes
, NTXT ("%s"), text
);
1787 return 1; // Cannot write file
1790 Emsg
*m
= new Emsg (CMSG_COMMENT
, text
);
1797 Experiment::delete_notes (bool handle_file
)
1801 char *fname
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_NOTES_FILE
);
1802 if (unlink (fname
) != 0)
1805 return 1; // Cannot delete file
1814 Experiment::read_warn_file ()
1816 int local_status
= SUCCESS
;
1818 ExperimentFile
*warnFile
= new ExperimentFile (this, SP_WARN_FILE
);
1819 if (warnFile
== NULL
)
1821 if (!warnFile
->open ())
1826 SAXParserFactory
*factory
= SAXParserFactory::newInstance ();
1827 SAXParser
*saxParser
= factory
->newSAXParser ();
1828 DefaultHandler
*dh
= new ExperimentHandler (this);
1831 saxParser
->parse ((File
*) warnFile
->fh
, dh
);
1833 catch (SAXException
*e
)
1835 // Fatal error in the parser
1837 sb
.sprintf (NTXT ("%s: %s"), SP_WARN_FILE
, e
->getMessage ());
1838 char *str
= sb
.toString ();
1839 Emsg
*m
= new Emsg (CMSG_FATAL
, str
);
1841 local_status
= FAILURE
;
1849 return local_status
;
1853 Experiment::read_log_file ()
1855 if (logFile
== NULL
)
1856 logFile
= new ExperimentFile (this, SP_LOG_FILE
);
1857 if (!logFile
->open ())
1863 SAXParserFactory
*factory
= SAXParserFactory::newInstance ();
1864 SAXParser
*saxParser
= factory
->newSAXParser ();
1865 DefaultHandler
*dh
= new ExperimentHandler (this);
1868 saxParser
->parse ((File
*) logFile
->fh
, dh
);
1870 catch (SAXException
*e
)
1872 // Fatal error in the parser
1875 sb
.sprintf (NTXT ("%s"), e
->getMessage ());
1877 sb
.sprintf (NTXT ("%s: %s"), SP_LOG_FILE
, e
->getMessage ());
1878 char *str
= sb
.toString ();
1879 Emsg
*m
= new Emsg (CMSG_FATAL
, str
);
1885 dbeSession
->register_metric (GTXT ("IPC"), GTXT ("Instructions Per Cycle"),
1886 NTXT ("insts/cycles"));
1887 dbeSession
->register_metric (GTXT ("CPI"), GTXT ("Cycles Per Instruction"),
1888 NTXT ("cycles/insts"));
1889 dbeSession
->register_metric (GTXT ("K_IPC"),
1890 GTXT ("Kernel Instructions Per Cycle"),
1891 NTXT ("K_insts/K_cycles"));
1892 dbeSession
->register_metric (GTXT ("K_CPI"),
1893 GTXT ("Kernel Cycles Per Instruction"),
1894 NTXT ("K_cycles/K_insts"));
1903 ////////////////////////////////////////////////////////////////////////////////
1904 // class Experiment::ExperimentLabelsHandler
1907 class Experiment::ExperimentLabelsHandler
: public DefaultHandler
1911 ExperimentLabelsHandler (Experiment
*_exp
)
1916 ~ExperimentLabelsHandler () { };
1917 void startDocument () { }
1918 void endDocument () { }
1919 void endElement (char * /*uri*/, char * /*localName*/, char * /*qName*/) { }
1920 void characters (char * /*ch*/, int /*start*/, int /*length*/) { }
1921 void ignorableWhitespace (char*, int, int) { }
1922 void error (SAXParseException
* /*e*/) { }
1924 void startElement (char *uri
, char *localName
, char *qName
, Attributes
*attrs
);
1931 return s
? s
: "NULL";
1938 Experiment::ExperimentLabelsHandler::startElement (char*, char*, char *qName
,
1941 DEBUG_CODE
if (DEBUG_SAXPARSER
) dump_startElement (qName
, attrs
);
1942 if (qName
== NULL
|| strcmp (qName
, NTXT ("id")) != 0)
1944 char *name
= NULL
, *all_times
= NULL
, *comment
= NULL
, *hostName
= NULL
;
1946 // long tm_zone = 0;
1947 hrtime_t startHrtime
= (hrtime_t
) 0;
1948 long long lbl_ts
= 0;
1951 start_tv
.tv_usec
= start_tv
.tv_sec
= 0;
1952 for (int i
= 0, sz
= attrs
? attrs
->getLength () : 0; i
< sz
; i
++)
1954 const char *qn
= attrs
->getQName (i
);
1955 const char *vl
= attrs
->getValue (i
);
1956 if (strcmp (qn
, NTXT ("name")) == 0)
1957 name
= dbe_xml2str (vl
);
1958 else if (strcmp (qn
, NTXT ("cmd")) == 0)
1959 all_times
= dbe_xml2str (vl
);
1960 else if (strcmp (qn
, NTXT ("comment")) == 0)
1961 comment
= dbe_xml2str (vl
);
1962 else if (strcmp (qn
, NTXT ("relative")) == 0)
1963 relative
= atoi (vl
);
1964 else if (strcmp (qn
, NTXT ("hostname")) == 0)
1965 hostName
= dbe_xml2str (vl
);
1966 else if (strcmp (qn
, NTXT ("time")) == 0)
1967 startSec
= atol (vl
);
1968 else if (strcmp (qn
, NTXT ("tstamp")) == 0)
1969 startHrtime
= parseTStamp (vl
);
1970 else if (strcmp (qn
, NTXT ("lbl_ts")) == 0)
1973 lbl_ts
= -parseTStamp (vl
+ 1);
1975 lbl_ts
= parseTStamp (vl
);
1978 if (name
== NULL
|| hostName
== NULL
|| (all_times
== NULL
&& comment
== NULL
))
1986 UserLabel
*lbl
= new UserLabel (name
);
1987 lbl
->comment
= comment
;
1988 lbl
->hostname
= hostName
;
1989 lbl
->start_sec
= startSec
;
1990 lbl
->start_hrtime
= startHrtime
;
1991 exp
->userLabels
->append (lbl
);
1994 lbl
->all_times
= all_times
;
1995 lbl
->start_tv
= start_tv
;
1996 lbl
->relative
= relative
;
1997 if (relative
== UserLabel::REL_TIME
)
1998 lbl
->atime
= lbl_ts
;
2000 { // relative == UserLabel::CUR_TIME
2001 long long delta
= 0;
2002 if (exp
->hostname
&& strcmp (lbl
->hostname
, exp
->hostname
) == 0)
2003 delta
= lbl_ts
+ (lbl
->start_hrtime
- exp
->exp_start_time
);
2005 for (int i
= 0; i
< exp
->userLabels
->size (); i
++)
2007 UserLabel
*firstLbl
= exp
->userLabels
->fetch (i
);
2008 if (strcmp (lbl
->hostname
, firstLbl
->hostname
) == 0)
2010 delta
= lbl_ts
+ (lbl
->start_hrtime
- firstLbl
->start_hrtime
) +
2011 ((long long) (firstLbl
->start_sec
- exp
->start_sec
)) * NANOSEC
;
2015 lbl
->atime
= delta
> 0 ? delta
: 0;
2021 sortUserLabels (const void *a
, const void *b
)
2023 UserLabel
*l1
= *((UserLabel
**) a
);
2024 UserLabel
*l2
= *((UserLabel
**) b
);
2025 int v
= dbe_strcmp (l1
->name
, l2
->name
);
2028 if (l1
->atime
< l2
->atime
)
2030 else if (l1
->atime
> l2
->atime
)
2032 if (l1
->id
< l2
->id
)
2034 else if (l1
->id
> l2
->id
)
2040 append_string (char *s
, char *str
)
2043 return dbe_strdup (str
);
2044 char *new_s
= dbe_sprintf (NTXT ("%s %s"), s
, str
);
2050 Experiment::read_labels_file ()
2052 ExperimentFile
*fp
= new ExperimentFile (this, SP_LABELS_FILE
);
2058 userLabels
= new Vector
<UserLabel
*>();
2059 SAXParserFactory
*factory
= SAXParserFactory::newInstance ();
2060 SAXParser
*saxParser
= factory
->newSAXParser ();
2061 DefaultHandler
*dh
= new ExperimentLabelsHandler (this);
2064 saxParser
->parse ((File
*) fp
->fh
, dh
);
2066 catch (SAXException
*e
)
2068 // Fatal error in the parser
2070 sb
.sprintf (NTXT ("%s: %s"), SP_LABELS_FILE
, e
->getMessage ());
2071 char *str
= sb
.toString ();
2072 Emsg
*m
= new Emsg (CMSG_FATAL
, str
);
2082 userLabels
->sort (sortUserLabels
);
2083 UserLabel::dump ("After sortUserLabels:", userLabels
);
2084 UserLabel
*ulbl
= NULL
;
2085 for (int i
= 0, sz
= userLabels
->size (); i
< sz
; i
++)
2087 UserLabel
*lbl
= userLabels
->fetch (i
);
2089 ulbl
= new UserLabel (lbl
->name
);
2090 else if (dbe_strcmp (lbl
->name
, ulbl
->name
) != 0)
2092 ulbl
->register_user_label (groupId
);
2093 if (ulbl
->expr
== NULL
)
2095 ulbl
= new UserLabel (lbl
->name
);
2099 if (strncmp (lbl
->all_times
, NTXT ("start"), 5) == 0)
2103 ulbl
->start_f
= true;
2104 ulbl
->timeStart
= lbl
->atime
;
2111 ulbl
->all_times
= append_string (ulbl
->all_times
, lbl
->all_times
);
2112 ulbl
->stop_f
= true;
2113 ulbl
->timeStop
= lbl
->atime
;
2117 if (lbl
->comment
!= NULL
)
2118 ulbl
->comment
= append_string (ulbl
->comment
, lbl
->comment
);
2122 ulbl
->register_user_label (groupId
);
2123 if (ulbl
->expr
== NULL
)
2126 Destroy (userLabels
);
2130 Experiment::read_archives ()
2134 char *allocated_str
= NULL
;
2135 char *nm
= get_arch_name ();
2136 DIR *exp_dir
= opendir (nm
);
2137 if (exp_dir
== NULL
)
2139 if (founder_exp
== NULL
)
2141 // Check if the user uses a subexperiment only
2142 nm
= dbe_sprintf (NTXT ("%s/../%s"), expt_name
, SP_ARCHIVES_DIR
);
2143 exp_dir
= opendir (nm
);
2144 if (exp_dir
== NULL
)
2158 int dlen
= sb
.length ();
2159 free (allocated_str
);
2160 archiveMap
= new StringMap
<DbeFile
*>();
2162 struct dirent
*entry
= NULL
;
2163 while ((entry
= readdir (exp_dir
)) != NULL
)
2165 char *dname
= entry
->d_name
;
2167 && (dname
[1] == '\0' || (dname
[1] == '.' && dname
[2] == '\0')))
2168 // skip links to ./ or ../
2170 sb
.setLength (dlen
);
2172 char *fnm
= sb
.toString ();
2173 DbeFile
*df
= new DbeFile (fnm
);
2174 df
->set_location (fnm
);
2175 df
->filetype
|= DbeFile::F_FILE
;
2176 df
->inArchive
= true;
2177 df
->experiment
= this;
2178 archiveMap
->put (dname
, df
);
2185 gen_file_name (const char *packet_name
, const char *src_name
)
2187 char *fnm
, *bname
= get_basename (packet_name
);
2188 if (bname
== packet_name
)
2189 fnm
= dbe_strdup (src_name
);
2191 fnm
= dbe_sprintf ("%.*s%s", (int) (bname
- packet_name
),
2192 packet_name
, src_name
);
2194 // convert "java.lang.Object/Integer.java" => "java/lang/Object/Integer.java"
2195 bname
= get_basename (fnm
);
2196 for (char *s
= fnm
; s
< bname
; s
++)
2203 get_jlass_name (const char *nm
)
2205 // Convert "Ljava/lang/Object;" => "java/lang/Object.class"
2208 size_t len
= strlen (nm
);
2209 if (nm
[len
- 1] == ';')
2210 return dbe_sprintf ("%.*s.class", (int) (len
- 2), nm
+ 1);
2212 return dbe_strdup (nm
);
2216 get_jmodule_name (const char *nm
)
2218 // convert "Ljava/lang/Object;" => "java.lang.Object"
2221 size_t len
= strlen (nm
);
2222 if (nm
[len
- 1] == ';')
2224 char *mname
= dbe_sprintf (NTXT ("%.*s"), (int) (len
- 2), nm
+ 1);
2225 for (char *s
= mname
; *s
; s
++)
2231 return dbe_strdup (nm
);
2235 Experiment::get_j_lo (const char *className
, const char *fileName
)
2237 char *class_name
= get_jlass_name (className
);
2238 Dprintf (DUMP_JCLASS_READER
,
2239 "Experiment::get_j_lo: className='%s' class_name='%s' fileName='%s'\n",
2240 STR (className
), STR (class_name
), STR (fileName
));
2241 LoadObject
*lo
= loadObjMap
->get (class_name
);
2244 lo
= createLoadObject (class_name
, fileName
);
2245 lo
->type
= LoadObject::SEG_TEXT
;
2246 lo
->mtime
= (time_t) 0;
2248 lo
->set_platform (Java
, wsize
);
2249 lo
->dbeFile
->filetype
|= DbeFile::F_FILE
| DbeFile::F_JAVACLASS
;
2251 Dprintf (DUMP_JCLASS_READER
,
2252 "Experiment::get_j_lo: creates '%s' location='%s'\n",
2253 STR (lo
->get_name ()), STR (lo
->dbeFile
->get_location (false)));
2260 Experiment::get_jclass (const char *className
, const char *fileName
)
2262 LoadObject
*lo
= get_j_lo (className
, NULL
);
2263 char *mod_name
= get_jmodule_name (className
);
2264 Module
*mod
= lo
->find_module (mod_name
);
2267 mod
= dbeSession
->createClassFile (mod_name
);
2268 mod
->loadobject
= lo
;
2269 if (strcmp (fileName
, NTXT ("<Unknown>")) != 0)
2270 mod
->set_file_name (gen_file_name (lo
->get_pathname (), fileName
));
2272 mod
->set_file_name (dbe_strdup (fileName
));
2273 lo
->append_module (mod
);
2276 else if (mod
->file_name
&& (strcmp (mod
->file_name
, "<Unknown>") == 0)
2277 && strcmp (fileName
, "<Unknown>") != 0)
2278 mod
->set_file_name (gen_file_name (lo
->get_pathname (), fileName
));
2279 Dprintf (DUMP_JCLASS_READER
,
2280 "Experiment::get_jclass: class_name='%s' mod_name='%s' fileName='%s'\n",
2281 mod
->loadobject
->get_pathname (), mod
->get_name (), mod
->file_name
);
2286 #define ARCH_STRLEN(s) ( ( strlen(s) + 4 ) & ~0x3 )
2289 Experiment::read_java_classes_file ()
2291 char *data_file_name
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_JCLASSES_FILE
);
2292 Data_window
*dwin
= new Data_window (data_file_name
);
2293 free (data_file_name
);
2294 if (dwin
->not_opened ())
2299 dwin
->need_swap_endian
= need_swap_endian
;
2300 jmaps
= new PRBTree ();
2301 jmidHTable
= new DbeCacheMap
<unsigned long long, JMethod
>;
2303 hrtime_t cur_loaded
= 0;
2304 Module
*cur_mod
= NULL
;
2305 for (int64_t offset
= 0;;)
2307 CM_Packet
*cpkt
= (CM_Packet
*) dwin
->bind (offset
, sizeof (CM_Packet
));
2310 uint16_t v16
= (uint16_t) cpkt
->tsize
;
2311 size_t cpktsize
= dwin
->decode (v16
);
2312 cpkt
= (CM_Packet
*) dwin
->bind (offset
, cpktsize
);
2313 if ((cpkt
== NULL
) || (cpktsize
== 0))
2315 char *buf
= dbe_sprintf (GTXT ("archive file malformed %s"),
2317 errorq
->append (new Emsg (CMSG_ERROR
, buf
));
2321 v16
= (uint16_t) cpkt
->type
;
2322 v16
= dwin
->decode (v16
);
2327 ARCH_jclass
*ajcl
= (ARCH_jclass
*) cpkt
;
2328 uint64_t class_id
= dwin
->decode (ajcl
->class_id
);
2329 char *className
= ((char*) ajcl
) + sizeof (*ajcl
);
2330 char *fileName
= className
+ ARCH_STRLEN (className
);
2331 Dprintf (DUMP_JCLASS_READER
,
2332 "read_java_classes_file: ARCH_JCLASS(Ox%x)"
2333 "class_id=Ox%llx className='%s' fileName='%s' \n",
2334 (int) v16
, (long long) class_id
, className
, fileName
);
2336 if (*className
== 'L')
2337 { // Old libcollector generated '[' (one array dimension).
2338 cur_mod
= get_jclass (className
, fileName
);
2339 cur_loaded
= dwin
->decode (ajcl
->tstamp
);
2340 jmaps
->insert (class_id
, cur_loaded
, cur_mod
);
2344 case ARCH_JCLASS_LOCATION
:
2346 ARCH_jclass_location
*ajcl
= (ARCH_jclass_location
*) cpkt
;
2347 uint64_t class_id
= dwin
->decode (ajcl
->class_id
);
2348 char *className
= ((char*) ajcl
) + sizeof (*ajcl
);
2349 char *fileName
= className
+ ARCH_STRLEN (className
);
2350 Dprintf (DUMP_JCLASS_READER
,
2351 "read_java_classes_file: ARCH_JCLASS_LOCATION(Ox%x)"
2352 "class_id=Ox%llx className='%s' fileName='%s' \n",
2353 (int) v16
, (long long) class_id
, className
, fileName
);
2354 get_j_lo (className
, fileName
);
2359 if (cur_mod
== NULL
)
2361 ARCH_jmethod
*ajmt
= (ARCH_jmethod
*) cpkt
;
2362 uint64_t method_id
= dwin
->decode (ajmt
->method_id
);
2363 char *s_name
= ((char*) ajmt
) + sizeof (*ajmt
);
2364 char *s_signature
= s_name
+ ARCH_STRLEN (s_name
);
2365 char *fullname
= dbe_sprintf ("%s.%s", cur_mod
->get_name (), s_name
);
2366 Dprintf (DUMP_JCLASS_READER
,
2367 "read_java_classes_file: ARCH_JMETHOD(Ox%x) "
2368 "method_id=Ox%llx name='%s' signature='%s' fullname='%s'\n",
2369 (int) v16
, (long long) method_id
, s_name
,
2370 s_signature
, fullname
);
2371 JMethod
*jmthd
= cur_mod
->find_jmethod (fullname
, s_signature
);
2374 jmthd
= dbeSession
->createJMethod ();
2375 jmthd
->size
= (unsigned) - 1; // unknown until later (maybe)
2376 jmthd
->module
= cur_mod
;
2377 jmthd
->set_signature (s_signature
);
2378 jmthd
->set_name (fullname
);
2379 cur_mod
->functions
->append (jmthd
);
2380 cur_mod
->loadobject
->functions
->append (jmthd
);
2381 Dprintf (DUMP_JCLASS_READER
,
2382 "read_java_classes_file: ARCH_JMETHOD CREATE fullname=%s\n",
2385 jmaps
->insert (method_id
, cur_loaded
, jmthd
);
2390 Dprintf (DUMP_JCLASS_READER
,
2391 "read_java_classes_file: type=Ox%x (%d) cpktsize=%d\n",
2392 (int) v16
, (int) v16
, (int) cpktsize
);
2393 break; // ignore unknown packets
2402 Experiment::read_map_file ()
2404 ExperimentFile
*mapFile
= new ExperimentFile (this, SP_MAP_FILE
);
2405 if (!mapFile
->open ())
2411 SAXParserFactory
*factory
= SAXParserFactory::newInstance ();
2412 SAXParser
*saxParser
= factory
->newSAXParser ();
2413 DefaultHandler
*dh
= new ExperimentHandler (this);
2416 saxParser
->parse ((File
*) mapFile
->fh
, dh
);
2418 catch (SAXException
*e
)
2420 // Fatal error in the parser
2422 sb
.sprintf (NTXT ("%s: %s"), SP_MAP_FILE
, e
->getMessage ());
2423 char *str
= sb
.toString ();
2424 Emsg
*m
= new Emsg (CMSG_FATAL
, str
);
2435 for (int i
= 0, sz
= mrecs
? mrecs
->size () : 0; i
< sz
; i
++)
2437 MapRecord
*mrec
= mrecs
->fetch (i
);
2438 SegMem
*smem
, *sm_lo
, *sm_hi
;
2441 case MapRecord::LOAD
:
2443 smem
->base
= mrec
->base
;
2444 smem
->size
= mrec
->size
;
2445 smem
->load_time
= mrec
->ts
;
2446 smem
->unload_time
= MAX_TIME
;
2447 smem
->obj
= mrec
->obj
;
2448 smem
->set_file_offset (mrec
->foff
);
2449 seg_items
->append (smem
); // add to the master list
2451 // Check if the new segment overlaps other active segments
2452 sm_lo
= (SegMem
*) maps
->locate (smem
->base
, smem
->load_time
);
2453 if (sm_lo
&& sm_lo
->base
+ sm_lo
->size
> smem
->base
)
2455 // check to see if it is a duplicate record: same address and size, and
2456 if ((smem
->base
== sm_lo
->base
) && (smem
->size
== sm_lo
->size
))
2458 // addresses and sizes match, check name
2459 if (strstr (smem
->obj
->get_name (), sm_lo
->obj
->get_name ()) != NULL
2460 || strstr (sm_lo
->obj
->get_name (), smem
->obj
->get_name ()) != NULL
)
2461 // this is a duplicate; just move on the the next map record
2464 GTXT ("*** Warning: Segment `%s' loaded with same address, size as `%s' [0x%llx-0x%llx]\n"),
2465 smem
->obj
->get_name (), sm_lo
->obj
->get_name (),
2466 sm_lo
->base
, sm_lo
->base
+ sm_lo
->size
);
2469 // Not a duplicate; implicitly unload the old one
2470 // Note: implicit unloading causes high <Unknown>
2471 // when such overlapping is bogus
2473 sb
.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"),
2474 smem
->obj
->get_name (), smem
->base
, smem
->base
+ smem
->size
,
2475 sm_lo
->obj
->get_name (), sm_lo
->base
, sm_lo
->base
+ sm_lo
->size
);
2476 warnq
->append (new Emsg (CMSG_WARN
, sb
));
2479 // now look for other segments with which this might overlap
2480 sm_hi
= (SegMem
*) maps
->locate_up (smem
->base
, smem
->load_time
);
2481 while (sm_hi
&& sm_hi
->base
< smem
->base
+ smem
->size
)
2484 // Note: implicit unloading causes high <Unknown> when such overlapping is bogus
2485 // maps->remove( sm_hi->base, smem->load_time );
2487 sb
.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"),
2488 smem
->obj
->get_name (), smem
->base
,
2489 smem
->base
+ smem
->size
, sm_hi
->obj
->get_name (),
2490 sm_hi
->base
, sm_hi
->base
+ sm_hi
->size
);
2491 warnq
->append (new Emsg (CMSG_WARN
, sb
));
2492 sm_hi
= (SegMem
*) maps
->locate_up (sm_hi
->base
+ sm_hi
->size
,
2496 maps
->insert (smem
->base
, smem
->load_time
, smem
);
2498 case MapRecord::UNLOAD
:
2499 smem
= (SegMem
*) maps
->locate (mrec
->base
, mrec
->ts
);
2500 if (smem
&& smem
->base
== mrec
->base
)
2502 smem
->unload_time
= mrec
->ts
;
2503 maps
->remove (mrec
->base
, mrec
->ts
);
2510 // See if there are comments or warnings for a load object;
2511 // if so, queue them to Experiment
2512 for (long i
= 0, sz
= loadObjs
? loadObjs
->size () : 0; i
< sz
; i
++)
2514 LoadObject
*lo
= loadObjs
->get (i
);
2515 for (Emsg
*m
= lo
->fetch_warnings (); m
; m
= m
->next
)
2516 warnq
->append (m
->get_warn (), m
->get_msg ());
2517 for (Emsg
*m
= lo
->fetch_comments (); m
; m
= m
->next
)
2518 commentq
->append (m
->get_warn (), m
->get_msg ());
2523 Experiment::read_frameinfo_file ()
2526 char *base_name
= get_basename (expt_name
);
2527 char *msg
= dbe_sprintf (GTXT ("Loading CallStack Data: %s"), base_name
);
2528 read_data_file ("data." SP_FRINFO_FILE
, msg
);
2530 frmpckts
->sort (frUidCmp
);
2531 uidnodes
->sort (uidNodeCmp
);
2535 Experiment::read_omp_preg ()
2537 // Parallel region descriptions
2538 DataDescriptor
*pregDdscr
= getDataDescriptor (DATA_OMP4
);
2539 if (pregDdscr
== NULL
)
2541 DataView
*pregData
= pregDdscr
->createView ();
2542 pregData
->sort (PROP_CPRID
); // omptrace PROP_CPRID
2544 // OpenMP enter parreg events
2545 DataDescriptor
*dDscr
= getDataDescriptor (DATA_OMP2
);
2546 if (dDscr
== NULL
|| dDscr
->getSize () == 0)
2552 char *idxname
= NTXT ("OMP_preg");
2553 delete dbeSession
->indxobj_define (idxname
, GTXT ("OpenMP Parallel Region"),
2554 NTXT ("CPRID"), NULL
, NULL
);
2555 int idxtype
= dbeSession
->findIndexSpaceByName (idxname
);
2563 // Pre-create parallel region with id == 0
2564 Histable
*preg0
= dbeSession
->createIndexObject (idxtype
, (int64_t) 0);
2565 preg0
->set_name (dbe_strdup (GTXT ("Implicit OpenMP Parallel Region")));
2567 // Take care of the progress bar
2568 char *msg
= dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2569 get_basename (expt_name
));
2570 theApplication
->set_progress (0, msg
);
2572 long deltaReport
= 1000;
2573 long nextReport
= 0;
2574 long errors_found
= 0;
2575 Vector
<Histable
*> pregs
;
2577 long size
= dDscr
->getSize ();
2578 for (long i
= 0; i
< size
; ++i
)
2580 if (i
== nextReport
)
2582 int percent
= (int) (i
* 100 / size
);
2584 theApplication
->set_progress (percent
, NULL
);
2585 nextReport
+= deltaReport
;
2588 uint32_t thrid
= dDscr
->getIntValue (PROP_THRID
, i
);
2589 hrtime_t tstamp
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
2590 uint64_t cprid
= dDscr
->getLongValue (PROP_CPRID
, i
); // omptrace CPRID
2591 mapPRid
->put (thrid
, tstamp
, cprid
);
2595 * We will use 2 pointers to make sure there is no loop.
2596 * First pointer "curpreg" goes to the next element,
2597 * second pointer "curpreg_loop_control" goes to the next->next element.
2598 * If these pointers have the same value - there is a loop.
2600 uint64_t curpreg_loop_control
= cprid
;
2601 Datum tval_loop_control
;
2602 if (curpreg_loop_control
!= 0)
2604 tval_loop_control
.setUINT64 (curpreg_loop_control
);
2605 long idx
= pregData
->getIdxByVals (&tval_loop_control
, DataView::REL_EQ
);
2607 curpreg_loop_control
= 0;
2609 curpreg_loop_control
= pregData
->getLongValue (PROP_PPRID
, idx
);
2611 for (uint64_t curpreg
= cprid
; curpreg
!= 0;)
2613 Histable
*val
= NULL
;
2615 tval
.setUINT64 (curpreg
);
2616 long idx
= pregData
->getIdxByVals (&tval
, DataView::REL_EQ
);
2620 * Check if there is a loop
2622 if (0 != curpreg_loop_control
)
2624 if (curpreg
== curpreg_loop_control
)
2627 if (1 == errors_found
)
2629 Emsg
*m
= new Emsg (CMSG_WARN
, GTXT ("*** Warning: circular links in OMP regions; data may not be correct."));
2635 uint64_t pragmapc
= pregData
->getLongValue (PROP_PRPC
, idx
);
2636 DbeInstr
*instr
= map_Vaddr_to_PC (pragmapc
, tstamp
);
2642 DbeLine
*dbeline
= (DbeLine
*) instr
->convertto (Histable::LINE
);
2643 if (dbeline
->lineno
> 0)
2645 if (instr
->func
->usrfunc
)
2646 dbeline
= dbeline
->sourceFile
->find_dbeline
2647 (instr
->func
->usrfunc
, dbeline
->lineno
);
2648 dbeline
->set_flag (DbeLine::OMPPRAGMA
);
2651 val
= dbeSession
->createIndexObject (idxtype
, val
);
2654 curpreg
= pregData
->getLongValue (PROP_PPRID
, idx
);
2656 * Update curpreg_loop_control
2658 if (0 != curpreg_loop_control
)
2660 tval_loop_control
.setUINT64 (curpreg_loop_control
);
2661 idx
= pregData
->getIdxByVals
2662 (&tval_loop_control
, DataView::REL_EQ
);
2664 curpreg_loop_control
= 0;
2667 curpreg_loop_control
= pregData
->getLongValue
2669 tval_loop_control
.setUINT64 (curpreg_loop_control
);
2670 idx
= pregData
->getIdxByVals
2671 (&tval_loop_control
, DataView::REL_EQ
);
2673 curpreg_loop_control
= 0;
2675 curpreg_loop_control
= pregData
->getLongValue
2680 pregs
.append (preg0
);
2681 void *prstack
= cstack
->add_stack (&pregs
);
2682 mapPReg
->put (thrid
, tstamp
, prstack
);
2684 theApplication
->set_progress (0, NTXT (""));
2689 Experiment::read_omp_task ()
2692 DataDescriptor
*taskDataDdscr
= getDataDescriptor (DATA_OMP5
);
2693 if (taskDataDdscr
== NULL
)
2696 //7035272: previously, DataView was global; now it's local...is this OK?
2697 DataView
*taskData
= taskDataDdscr
->createView ();
2698 taskData
->sort (PROP_TSKID
); // omptrace PROP_TSKID
2700 // OpenMP enter task events
2701 DataDescriptor
*dDscr
= getDataDescriptor (DATA_OMP3
);
2702 if (dDscr
== NULL
|| dDscr
->getSize () == 0)
2708 char *idxname
= NTXT ("OMP_task");
2709 // delete a possible error message. Ugly.
2710 delete dbeSession
->indxobj_define (idxname
, GTXT ("OpenMP Task"), NTXT ("TSKID"), NULL
, NULL
);
2711 int idxtype
= dbeSession
->findIndexSpaceByName (idxname
);
2719 // Pre-create task with id == 0
2720 Histable
*task0
= dbeSession
->createIndexObject (idxtype
, (int64_t) 0);
2721 task0
->set_name (dbe_strdup (GTXT ("OpenMP Task from Implicit Parallel Region")));
2723 // Take care of the progress bar
2724 char *msg
= dbe_sprintf (GTXT ("Processing OpenMP Task Data: %s"), get_basename (expt_name
));
2725 theApplication
->set_progress (0, msg
);
2727 long deltaReport
= 1000;
2728 long nextReport
= 0;
2730 Vector
<Histable
*> tasks
;
2731 long size
= dDscr
->getSize ();
2732 long errors_found
= 0;
2733 for (long i
= 0; i
< size
; ++i
)
2735 if (i
== nextReport
)
2737 int percent
= (int) (i
* 100 / size
);
2739 theApplication
->set_progress (percent
, NULL
);
2740 nextReport
+= deltaReport
;
2743 uint32_t thrid
= dDscr
->getIntValue (PROP_THRID
, i
);
2744 hrtime_t tstamp
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
2745 uint64_t tskid
= dDscr
->getLongValue (PROP_TSKID
, i
); //omptrace TSKID
2748 * We will use 2 pointers to make sure there is no loop.
2749 * First pointer "curtsk" goes to the next element,
2750 * second pointer "curtsk_loop_control" goes to the next->next element.
2751 * If these pointers have the same value - there is a loop.
2753 uint64_t curtsk_loop_control
= tskid
;
2754 Datum tval_loop_control
;
2755 if (curtsk_loop_control
!= 0)
2757 tval_loop_control
.setUINT64 (curtsk_loop_control
);
2758 long idx
= taskData
->getIdxByVals (&tval_loop_control
, DataView::REL_EQ
);
2760 curtsk_loop_control
= 0;
2762 curtsk_loop_control
= taskData
->getLongValue (PROP_PTSKID
, idx
);
2764 for (uint64_t curtsk
= tskid
; curtsk
!= 0;)
2766 Histable
*val
= NULL
;
2769 tval
.setUINT64 (curtsk
);
2770 long idx
= taskData
->getIdxByVals (&tval
, DataView::REL_EQ
);
2774 * Check if there is a loop
2776 if (0 != curtsk_loop_control
)
2778 if (curtsk
== curtsk_loop_control
)
2781 if (1 == errors_found
)
2783 Emsg
*m
= new Emsg (CMSG_WARN
, GTXT ("*** Warning: circular links in OMP tasks; data may not be correct."));
2789 uint64_t pragmapc
= taskData
->getLongValue (PROP_PRPC
, idx
);
2790 DbeInstr
*instr
= map_Vaddr_to_PC (pragmapc
, tstamp
);
2794 DbeLine
*dbeline
= (DbeLine
*) instr
->convertto (Histable::LINE
);
2795 if (dbeline
->lineno
> 0)
2797 if (instr
->func
->usrfunc
)
2798 dbeline
= dbeline
->sourceFile
->find_dbeline
2799 (instr
->func
->usrfunc
, dbeline
->lineno
);
2800 dbeline
->set_flag (DbeLine::OMPPRAGMA
);
2803 val
= dbeSession
->createIndexObject (idxtype
, val
);
2806 curtsk
= taskData
->getLongValue (PROP_PTSKID
, idx
);
2808 * Update curtsk_loop_control
2810 if (0 != curtsk_loop_control
)
2812 tval_loop_control
.setUINT64 (curtsk_loop_control
);
2813 idx
= taskData
->getIdxByVals (&tval_loop_control
, DataView::REL_EQ
);
2815 curtsk_loop_control
= 0;
2818 curtsk_loop_control
= taskData
->getLongValue (PROP_PTSKID
, idx
);
2819 tval_loop_control
.setUINT64 (curtsk_loop_control
);
2820 idx
= taskData
->getIdxByVals (&tval_loop_control
,
2823 curtsk_loop_control
= 0;
2825 curtsk_loop_control
= taskData
->getLongValue (PROP_PTSKID
,
2830 tasks
.append (task0
);
2831 void *tskstack
= cstack
->add_stack (&tasks
);
2832 mapTask
->put (thrid
, tstamp
, tskstack
);
2834 theApplication
->set_progress (0, NTXT (""));
2839 Experiment::read_omp_file ()
2841 // DATA_OMP2 table is common between OpenMP 2.5 and 3.0 profiling
2842 DataDescriptor
*dDscr
= getDataDescriptor (DATA_OMP2
);
2845 if (dDscr
->getSize () == 0)
2847 char *base_name
= get_basename (expt_name
);
2848 char *msg
= dbe_sprintf (GTXT ("Loading OpenMP Data: %s"), base_name
);
2849 read_data_file (SP_OMPTRACE_FILE
, msg
);
2852 // OpenMP fork events
2853 dDscr
= getDataDescriptor (DATA_OMP
);
2854 long sz
= dDscr
->getSize ();
2858 msg
= dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2860 theApplication
->set_progress (0, msg
);
2862 long deltaReport
= 5000;
2863 long nextReport
= 0;
2864 for (int i
= 0; i
< sz
; ++i
)
2866 if (i
== nextReport
)
2868 int percent
= (int) (i
* 100 / sz
);
2870 theApplication
->set_progress (percent
, NULL
);
2871 nextReport
+= deltaReport
;
2873 uint32_t thrid
= dDscr
->getIntValue (PROP_THRID
, i
);
2874 hrtime_t tstamp
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
2875 uint64_t cprid
= dDscr
->getLongValue (PROP_CPRID
, i
); //omptrace
2876 mapPRid
->put (thrid
, tstamp
, cprid
);
2878 theApplication
->set_progress (0, NTXT (""));
2881 openMPdata
= dDscr
->createView ();
2882 openMPdata
->sort (PROP_CPRID
); // omptrace PROP_CPRID
2884 // thread enters parreg events
2885 dDscr
= getDataDescriptor (DATA_OMP2
);
2886 sz
= dDscr
->getSize ();
2889 msg
= dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2891 theApplication
->set_progress (0, msg
);
2896 for (int i
= 0; i
< sz
; ++i
)
2898 if (i
== nextReport
)
2900 int percent
= (int) (i
* 100 / sz
);
2902 theApplication
->set_progress (percent
, NULL
);
2903 nextReport
+= deltaReport
;
2905 uint32_t thrid
= dDscr
->getIntValue (PROP_THRID
, i
);
2906 hrtime_t tstamp
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
2907 uint64_t cprid
= dDscr
->getLongValue (PROP_CPRID
, i
); //omptrace
2908 mapPRid
->put (thrid
, tstamp
, cprid
);
2910 theApplication
->set_progress (0, NTXT (""));
2917 if (ompavail
&& coll_params
.profile_mode
)
2919 dbeSession
->status_ompavail
= 1;
2920 register_metric (Metric::OMP_WORK
);
2921 register_metric (Metric::OMP_WAIT
);
2922 register_metric (Metric::OMP_OVHD
);
2923 if (coll_params
.lms_magic_id
== LMS_MAGIC_ID_SOLARIS
)
2924 register_metric (Metric::OMP_MASTER_THREAD
);
2930 Experiment::read_ifreq_file ()
2932 char *fname
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_IFREQ_FILE
);
2933 FILE *f
= fopen (fname
, NTXT ("r"));
2941 ifreqq
= new Emsgqueue (NTXT ("ifreqq"));
2946 char str
[MAXPATHLEN
];
2947 char *e
= fgets (str
, ((int) sizeof (str
)) - 1, f
);
2950 // end the list from the experiment
2951 m
= new Emsg (CMSG_COMMENT
,
2952 GTXT ("============================================================"));
2957 size_t i
= strlen (str
);
2958 if (i
> 0 && str
[i
- 1] == '\n')
2959 // remove trailing nl
2962 m
= new Emsg (CMSG_COMMENT
, str
);
2969 Experiment::getBaseFounder ()
2973 Experiment
*founder
= this;
2974 Experiment
*parent
= founder
->founder_exp
;
2978 parent
= founder
->founder_exp
;
2980 baseFounder
= founder
;
2985 Experiment::getRelativeStartTime ()
2987 if (exp_rel_start_time_set
)
2988 return exp_rel_start_time
;
2989 Experiment
*founder
= getBaseFounder ();
2990 hrtime_t child_start
= this->getStartTime ();
2991 hrtime_t founder_start
= founder
->getStartTime ();
2992 exp_rel_start_time
= child_start
- founder_start
;
2993 if (child_start
== 0 && founder_start
)
2994 exp_rel_start_time
= 0; // when descendents have incomplete log.xml
2995 exp_rel_start_time_set
= true;
2996 return exp_rel_start_time
;
3000 Experiment::get_raw_events (int data_id
)
3002 DataDescriptor
*dDscr
;
3006 dDscr
= get_profile_events ();
3009 dDscr
= get_sync_events ();
3012 dDscr
= get_hwc_events ();
3015 dDscr
= get_heap_events ();
3018 dDscr
= get_heapsz_events ();
3021 dDscr
= get_iotrace_events ();
3024 dDscr
= get_race_events ();
3027 dDscr
= get_deadlock_events ();
3030 dDscr
= get_sample_events ();
3033 dDscr
= get_gc_events ();
3043 Experiment::base_data_id (int data_id
)
3048 return DATA_HEAP
; // DATA_HEAPSZ DataView is based on DATA_HEAP's DataView
3056 Experiment::create_derived_data_view (int data_id
, DataView
*dview
)
3058 // dview contains filtered packets
3062 return create_heapsz_data_view (dview
);
3070 Experiment::get_profile_events ()
3072 DataDescriptor
*dDscr
= getDataDescriptor (DATA_CLOCK
);
3075 if (dDscr
->getSize () == 0)
3077 char *base_name
= get_basename (expt_name
);
3078 char *msg
= dbe_sprintf (GTXT ("Loading Profile Data: %s"), base_name
);
3079 read_data_file (SP_PROFILE_FILE
, msg
);
3081 add_evt_time_to_profile_events (dDscr
);
3082 resolve_frame_info (dDscr
);
3084 else if (!dDscr
->isResolveFrInfoDone ())
3085 resolve_frame_info (dDscr
);
3090 Experiment::add_evt_time_to_profile_events (DataDescriptor
*dDscr
)
3092 if (coll_params
.lms_magic_id
!= LMS_MAGIC_ID_SOLARIS
)
3095 DataView
*dview
= dDscr
->createView ();
3096 dview
->sort (PROP_THRID
, PROP_TSTAMP
);
3098 // add PROP_EVT_TIME
3099 PropDescr
* tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, "EVT_TIME");
3100 tmp_propDscr
->uname
= dbe_strdup (GTXT ("Event duration"));
3101 tmp_propDscr
->vtype
= TYPE_INT64
;
3102 dDscr
->addProperty (tmp_propDscr
);
3104 long sz
= dview
->getSize ();
3105 long long ptimer_usec
= get_params ()->ptimer_usec
;
3106 for (long i
= 0; i
< sz
; i
++)
3111 hrtime_t this_tstamp
= dview
->getLongValue (PROP_TSTAMP
, i
);
3112 long this_thrid
= dview
->getLongValue (PROP_THRID
, i
);
3113 for (jj
= i
+ 1; jj
< sz
; jj
++)
3115 hrtime_t tmp_tstamp
= dview
->getLongValue (PROP_TSTAMP
, jj
);
3116 if (tmp_tstamp
!= this_tstamp
)
3118 long tmp_thrid
= dview
->getLongValue (PROP_THRID
, jj
);
3119 if (tmp_thrid
!= this_thrid
)
3126 for (jj
= i
; jj
< next_sample
; jj
++)
3127 nticks
+= dview
->getLongValue (PROP_NTICK
, jj
);
3129 continue; // no duration
3132 hrtime_t duration
= ptimer_usec
* 1000LL * nticks
; // nanoseconds
3133 for (jj
= i
; jj
< next_sample
; jj
++)
3134 dview
->setValue (PROP_EVT_TIME
, jj
, duration
);
3141 Experiment::get_sync_events ()
3143 DataDescriptor
*dDscr
= getDataDescriptor (DATA_SYNCH
);
3146 if (dDscr
->getSize () > 0)
3151 char *base_name
= get_basename (expt_name
);
3152 char *msg
= dbe_sprintf (GTXT ("Loading Synctrace Data: %s"), base_name
);
3153 read_data_file (SP_SYNCTRACE_FILE
, msg
);
3155 resolve_frame_info (dDscr
);
3158 // check for PROP_EVT_TIME
3159 PropDescr
*tmp_propDscr
= dDscr
->getProp (PROP_EVT_TIME
);
3163 // add PROP_EVT_TIME
3164 tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, "EVT_TIME");
3165 tmp_propDscr
->uname
= dbe_strdup (GTXT ("Event duration"));
3166 tmp_propDscr
->vtype
= TYPE_INT64
;
3167 dDscr
->addProperty (tmp_propDscr
);
3169 long sz
= dDscr
->getSize ();
3170 for (long i
= 0; i
< sz
; i
++)
3172 uint64_t event_duration
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
3173 event_duration
-= dDscr
->getLongValue (PROP_SRQST
, i
);
3174 dDscr
->setValue (PROP_EVT_TIME
, i
, event_duration
);
3180 Experiment::get_hwc_events ()
3182 DataDescriptor
*dDscr
= getDataDescriptor (DATA_HWC
);
3185 if (dDscr
->getSize () == 0)
3187 char *base_name
= get_basename (expt_name
);
3188 char *msg
= dbe_sprintf (GTXT ("Loading HW Profile Data: %s"), base_name
);
3190 // clear HWC event stats
3193 read_data_file (SP_HWCNTR_FILE
, msg
);
3195 resolve_frame_info (dDscr
);
3197 // describe the HW counters in PropDescr
3198 PropDescr
*prop
= dDscr
->getProp (PROP_HWCTAG
);
3201 Collection_params
*cparam
= get_params ();
3202 if (cparam
->hw_mode
!= 0)
3203 for (int aux
= 0; aux
< MAX_HWCOUNT
; aux
++)
3204 if (cparam
->hw_aux_name
[aux
])
3206 const char* cmdname
= cparam
->hw_aux_name
[aux
];
3207 const char* uname
= cparam
->hw_username
[aux
];
3208 prop
->addState (aux
, cmdname
, uname
);
3214 double dserrrate
= 100.0 * ((double) dsnoxhwcevents
) / ((double) dsevents
);
3215 if ((dsevents
> 0) && (dserrrate
> 10.0))
3217 // warn the user that rate is high
3219 if (dbeSession
->check_ignore_no_xhwcprof ())
3221 GTXT ("Warning: experiment %s has %.1f%%%% (%lld of %lld) dataspace events that were accepted\n without verification; data may be incorrect or misleading\n recompile with -xhwcprof and rerecord to get better data\n"),
3222 base_name
, dserrrate
, (long long) dsnoxhwcevents
,
3223 (long long) dsevents
);
3226 GTXT ("Warning: experiment %s has %.1f%%%% (%lld of %lld) dataspace events that could not be verified\n recompile with -xhwcprof and rerecord to get better data\n"),
3227 base_name
, dserrrate
, (long long) dsnoxhwcevents
,
3228 (long long) dsevents
);
3229 errorq
->append (new Emsg (CMSG_WARN
, sb
));
3232 // see if we've scanned the data
3233 if (hwc_scanned
== 0)
3235 // no, scan the packets to see how many are bogus, or represent lost interrupts
3238 // loop over the packets, counting the bad ones
3239 if (hwc_bogus
!= 0 || hwc_lost_int
!= 0)
3241 // hwc counter data had bogus packets and/or packets reflecting lost interrupts
3242 double bogus_rate
= 100. * (double) hwc_bogus
/ (double) hwc_cnt
;
3243 if (bogus_rate
> 5.)
3247 GTXT ("WARNING: Too many invalid HW counter profile events (%ld/%ld = %3.2f%%) in experiment %d (`%s'); data may be unreliable"),
3248 (long) hwc_bogus
, (long) hwc_cnt
, bogus_rate
,
3249 (int) userExpId
, base_name
);
3250 Emsg
*m
= new Emsg (CMSG_WARN
, sb
);
3261 Experiment::get_iotrace_events ()
3263 DataDescriptor
*dDscr
= getDataDescriptor (DATA_IOTRACE
);
3267 if (dDscr
->getSize () > 0)
3270 char *base_name
= get_basename (expt_name
);
3271 char *msg
= dbe_sprintf (GTXT ("Loading IO Trace Data: %s"), base_name
);
3272 read_data_file (SP_IOTRACE_FILE
, msg
);
3275 if (dDscr
->getSize () == 0)
3277 resolve_frame_info (dDscr
);
3279 // check for PROP_EVT_TIME
3280 PropDescr
*tmp_propDscr
= dDscr
->getProp (PROP_EVT_TIME
);
3284 // add PROP_EVT_TIME
3285 tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, "EVT_TIME");
3286 tmp_propDscr
->uname
= dbe_strdup (GTXT ("Event duration"));
3287 tmp_propDscr
->vtype
= TYPE_INT64
;
3288 dDscr
->addProperty (tmp_propDscr
);
3291 tmp_propDscr
= new PropDescr (PROP_IOVFD
, "IOVFD");
3292 tmp_propDscr
->uname
= dbe_strdup (GTXT ("Virtual File Descriptor"));
3293 tmp_propDscr
->vtype
= TYPE_INT64
;
3294 dDscr
->addProperty (tmp_propDscr
);
3297 fDataMap
= new DefaultMap
<int64_t, FileData
*>;
3300 vFdMap
= new DefaultMap
<int, int64_t>;
3302 static int64_t virtualFd
= 0;
3306 fData
= fDataMap
->get (VIRTUAL_FD_STDIN
);
3309 fData
= new FileData (STDIN_FILENAME
);
3310 fData
->setVirtualFd (VIRTUAL_FD_STDIN
);
3311 fData
->id
= VIRTUAL_FD_STDIN
;
3312 fData
->setFileDes (STDIN_FD
);
3313 fDataMap
->put (VIRTUAL_FD_STDIN
, fData
);
3314 vFdMap
->put (STDIN_FD
, VIRTUAL_FD_STDIN
);
3317 fData
= fDataMap
->get (VIRTUAL_FD_STDOUT
);
3320 fData
= new FileData (STDOUT_FILENAME
);
3321 fData
->setVirtualFd (VIRTUAL_FD_STDOUT
);
3322 fData
->id
= VIRTUAL_FD_STDOUT
;
3323 fData
->setFileDes (STDOUT_FD
);
3324 fDataMap
->put (VIRTUAL_FD_STDOUT
, fData
);
3325 vFdMap
->put (STDOUT_FD
, VIRTUAL_FD_STDOUT
);
3328 fData
= fDataMap
->get (VIRTUAL_FD_STDERR
);
3331 fData
= new FileData (STDERR_FILENAME
);
3332 fData
->setVirtualFd (VIRTUAL_FD_STDERR
);
3333 fData
->id
= VIRTUAL_FD_STDERR
;
3334 fData
->setFileDes (STDERR_FD
);
3335 fDataMap
->put (VIRTUAL_FD_STDERR
, fData
);
3336 vFdMap
->put (STDERR_FD
, VIRTUAL_FD_STDERR
);
3339 fData
= fDataMap
->get (VIRTUAL_FD_OTHERIO
);
3342 fData
= new FileData (OTHERIO_FILENAME
);
3343 fData
->setVirtualFd (VIRTUAL_FD_OTHERIO
);
3344 fData
->id
= VIRTUAL_FD_OTHERIO
;
3345 fData
->setFileDes (OTHERIO_FD
);
3346 fDataMap
->put (VIRTUAL_FD_OTHERIO
, fData
);
3349 DataView
*dview
= dDscr
->createView ();
3350 dview
->sort (PROP_TSTAMP
);
3351 long sz
= dview
->getSize ();
3352 for (long i
= 0; i
< sz
; i
++)
3354 hrtime_t event_duration
= dview
->getLongValue (PROP_TSTAMP
, i
);
3355 hrtime_t event_start
= dview
->getLongValue (PROP_IORQST
, i
);
3356 if (event_start
> 0)
3357 event_duration
-= event_start
;
3360 dview
->setValue (PROP_EVT_TIME
, i
, event_duration
);
3363 int64_t vFd
= VIRTUAL_FD_NONE
;
3365 int32_t origFd
= -1;
3366 StringBuilder
*sb
= NULL
;
3367 FileData
*fDataOrig
= NULL
;
3368 FileSystem_type fsType
;
3370 IOTrace_type ioType
= (IOTrace_type
) dview
->getIntValue (PROP_IOTYPE
, i
);
3375 case READ_TRACE_ERROR
:
3376 case WRITE_TRACE_ERROR
:
3377 fd
= dview
->getIntValue (PROP_IOFD
, i
);
3378 vFd
= vFdMap
->get (fd
);
3379 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
3380 || (fData
= fDataMap
->get (vFd
)) == NULL
)
3382 fData
= new FileData (UNKNOWNFD_FILENAME
);
3383 fData
->setVirtualFd (virtualFd
);
3384 fData
->setFsType ("N/A");
3385 fData
->setFileDes (fd
);
3386 fDataMap
->put (virtualFd
, fData
);
3387 vFdMap
->put (fd
, virtualFd
);
3391 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3395 sb
= (StringBuilder
*) dview
->getObjValue (PROP_IOFNAME
, i
);
3396 if (sb
!= NULL
&& sb
->length () > 0)
3397 fName
= sb
->toString ();
3398 fd
= dview
->getIntValue (PROP_IOFD
, i
);
3399 origFd
= dview
->getIntValue (PROP_IOOFD
, i
);
3400 fsType
= (FileSystem_type
) dview
->getIntValue (PROP_IOFSTYPE
, i
);
3404 fData
= new FileData (fName
);
3405 fDataMap
->put (virtualFd
, fData
);
3406 vFdMap
->put (fd
, virtualFd
);
3407 fData
->setFileDes (fd
);
3408 fData
->setFsType (fsType
);
3409 fData
->setVirtualFd (virtualFd
);
3413 else if (origFd
> 0)
3415 vFd
= vFdMap
->get (origFd
);
3416 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
)
3419 "*** Error I/O tracing: (open) cannot get the virtual file descriptor, fd=%d origFd=%d\n",
3423 else if ((fDataOrig
= fDataMap
->get (vFd
)) == NULL
)
3426 "*** Error IO tracing: (open) cannot get original FileData object, fd=%d origFd=%d\n",
3432 fName
= fDataOrig
->getFileName ();
3433 fData
= new FileData (fName
);
3434 fData
->setFileDes (fd
);
3435 fData
->setFsType (fDataOrig
->getFsType ());
3436 fData
->setVirtualFd (virtualFd
);
3437 fDataMap
->put (virtualFd
, fData
);
3438 vFdMap
->put (fd
, virtualFd
);
3445 vFd
= vFdMap
->get (fd
);
3446 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
3447 || (fData
= fDataMap
->get (vFd
)) == NULL
)
3449 fData
= new FileData (UNKNOWNFD_FILENAME
);
3450 fData
->setVirtualFd (virtualFd
);
3451 fData
->setFsType ("N/A");
3452 fData
->setFileDes (fd
);
3453 fDataMap
->put (virtualFd
, fData
);
3454 vFdMap
->put (fd
, virtualFd
);
3462 NTXT ("*** Error IO tracing: (open) unknown open IO type, fd=%d origFd=%d\n"), fd
, origFd
);
3466 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3469 case OPEN_TRACE_ERROR
:
3472 sb
= (StringBuilder
*) dview
->getObjValue (PROP_IOFNAME
, i
);
3473 if (sb
!= NULL
&& sb
->length () > 0)
3474 fName
= sb
->toString ();
3475 fd
= dview
->getIntValue (PROP_IOFD
, i
);
3476 origFd
= dview
->getIntValue (PROP_IOOFD
, i
);
3477 fsType
= (FileSystem_type
) dview
->getIntValue (PROP_IOFSTYPE
, i
);
3481 fData
= new FileData (fName
);
3482 fDataMap
->put (virtualFd
, fData
);
3483 fData
->setFileDes (fd
);
3484 fData
->setFsType (fsType
);
3485 fData
->setVirtualFd (virtualFd
);
3489 else if (origFd
> 0)
3491 vFd
= vFdMap
->get (origFd
);
3492 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
)
3495 "*** Error IO tracing: (open error) cannot get the virtual file descriptor, fd=%d origFd=%d\n",
3499 else if ((fDataOrig
= fDataMap
->get (vFd
)) == NULL
)
3502 "*** Error IO tracing: (open error) cannot get original FileData object, fd=%d origFd=%d\n",
3508 fName
= fDataOrig
->getFileName ();
3509 fData
= new FileData (fName
);
3510 fData
->setFileDes (fd
);
3511 fData
->setFsType (fDataOrig
->getFsType ());
3512 fData
->setVirtualFd (virtualFd
);
3513 fDataMap
->put (virtualFd
, fData
);
3519 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3523 case CLOSE_TRACE_ERROR
:
3524 fd
= dview
->getIntValue (PROP_IOFD
, i
);
3525 vFd
= vFdMap
->get (fd
);
3526 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
)
3529 "*** Error IO tracing: (close) cannot get the virtual file descriptor, fd=%d\n",
3533 fData
= fDataMap
->get (vFd
);
3537 "*** Error IO tracing: (close) cannot get the FileData object, fd=%d\n",
3542 vFdMap
->put (fd
, VIRTUAL_FD_NONE
);
3543 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3547 case OTHERIO_TRACE_ERROR
:
3548 vFd
= VIRTUAL_FD_OTHERIO
;
3549 fData
= fDataMap
->get (vFd
);
3553 "*** Error IO tracing: (other IO) cannot get the FileData object\n");
3557 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3559 case IOTRACETYPE_LAST
:
3570 Experiment::get_heap_events ()
3572 DataDescriptor
*dDscr
= getDataDescriptor (DATA_HEAP
);
3575 if (dDscr
->getSize () > 0)
3578 char *base_name
= get_basename (expt_name
);
3579 char *msg
= dbe_sprintf (GTXT ("Loading Heap Trace Data: %s"), base_name
);
3580 read_data_file (SP_HEAPTRACE_FILE
, msg
);
3583 if (dDscr
->getSize () == 0)
3585 resolve_frame_info (dDscr
);
3587 // Match FREE to MALLOC
3588 PropDescr
*prop
= new PropDescr (PROP_HLEAKED
, NTXT ("HLEAKED"));
3589 prop
->uname
= dbe_strdup (GTXT ("Bytes Leaked"));
3590 prop
->vtype
= TYPE_UINT64
;
3591 dDscr
->addProperty (prop
);
3593 prop
= new PropDescr (PROP_HMEM_USAGE
, NTXT ("HMEM_USAGE"));
3594 prop
->uname
= dbe_strdup (GTXT ("Heap Memory Usage"));
3595 prop
->vtype
= TYPE_UINT64
;
3596 dDscr
->addProperty (prop
);
3598 prop
= new PropDescr (PROP_HFREED
, NTXT ("HFREED"));
3599 prop
->uname
= dbe_strdup (GTXT ("Bytes Freed"));
3600 prop
->vtype
= TYPE_UINT64
;
3601 dDscr
->addProperty (prop
);
3603 prop
= new PropDescr (PROP_HCUR_ALLOCS
, NTXT ("HCUR_ALLOCS"));
3604 prop
->uname
= dbe_strdup (GTXT ("Net Bytes Allocated"));
3605 prop
->vtype
= TYPE_INT64
;
3606 dDscr
->addProperty (prop
);
3608 prop
= new PropDescr (PROP_HCUR_LEAKS
, NTXT ("HCUR_LEAKS"));
3609 prop
->uname
= dbe_strdup (GTXT ("Net Bytes Leaked"));
3610 prop
->vtype
= TYPE_UINT64
;
3611 dDscr
->addProperty (prop
);
3613 prop
= new PropDescr (PROP_HCUR_NET_ALLOC
, NTXT ("HCUR_NET_ALLOC"));
3614 prop
->vtype
= TYPE_INT64
;
3615 prop
->flags
= DDFLAG_NOSHOW
;
3616 dDscr
->addProperty (prop
);
3618 prop
= new PropDescr (PROP_DDSCR_LNK
, NTXT ("DDSCR_LNK"));
3619 prop
->vtype
= TYPE_UINT64
;
3620 prop
->flags
= DDFLAG_NOSHOW
;
3621 dDscr
->addProperty (prop
);
3623 prop
= new PropDescr (PROP_VOIDP_OBJ
, NTXT ("VOIDP_OBJ"));
3624 prop
->vtype
= TYPE_OBJ
;
3625 prop
->flags
= DDFLAG_NOSHOW
;
3626 dDscr
->addProperty (prop
);
3628 prop
= new PropDescr (PROP_TSTAMP2
, NTXT ("TSTAMP2"));
3629 prop
->uname
= dbe_strdup (GTXT ("End Timestamp (nanoseconds)"));
3630 prop
->vtype
= TYPE_UINT64
;
3631 prop
->flags
= DDFLAG_NOSHOW
;
3632 dDscr
->addProperty (prop
);
3634 DataView
*dview
= dDscr
->createView ();
3635 dview
->sort (PROP_TSTAMP
);
3637 // Keep track of memory usage
3638 Size memoryUsage
= 0;
3640 HeapMap
*heapmap
= new HeapMap ();
3641 long sz
= dview
->getSize ();
3642 for (long i
= 0; i
< sz
; i
++)
3645 Heap_type mtype
= (Heap_type
) dview
->getIntValue (PROP_HTYPE
, i
);
3646 Vaddr vaddr
= dview
->getULongValue (PROP_HVADDR
, i
);
3647 Vaddr ovaddr
= dview
->getULongValue (PROP_HOVADDR
, i
);
3648 Size hsize
= dview
->getULongValue (PROP_HSIZE
, i
);
3649 hrtime_t tstamp
= dview
->getLongValue (PROP_TSTAMP
, i
);
3654 dview
->setValue (PROP_TSTAMP2
, i
, (uint64_t) MAX_TIME
);
3657 dview
->setValue (PROP_HLEAKED
, i
, hsize
);
3658 heapmap
->allocate (vaddr
, i
+ 1);
3660 // Increase heap size
3661 memoryUsage
+= hsize
;
3662 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3669 long idx
= heapmap
->deallocate (vaddr
) - 1;
3672 // Decrease heap size
3673 Size leaked
= dview
->getLongValue (PROP_HLEAKED
, idx
);
3674 memoryUsage
-= leaked
;
3675 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3677 Size alloc
= dview
->getLongValue (PROP_HSIZE
, idx
);
3678 // update allocation
3679 dview
->setValue (PROP_HLEAKED
, idx
, (uint64_t) 0);
3680 dview
->setValue (PROP_TSTAMP2
, idx
, tstamp
);
3681 dview
->setValue (PROP_DDSCR_LNK
, idx
, dview
->getIdByIdx (i
) + 1);
3682 // update this event
3683 dview
->setValue (PROP_HFREED
, i
, alloc
);
3689 dview
->setValue (PROP_TSTAMP2
, i
, (uint64_t) MAX_TIME
);
3692 long idx
= heapmap
->deallocate (ovaddr
) - 1;
3695 // Decrease heap size
3696 Size leaked
= dview
->getLongValue (PROP_HLEAKED
, idx
);
3697 memoryUsage
-= leaked
;
3698 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3700 Size alloc
= dview
->getLongValue (PROP_HSIZE
, idx
);
3701 // update allocation
3702 dview
->setValue (PROP_HLEAKED
, idx
, (uint64_t) 0);
3703 dview
->setValue (PROP_TSTAMP2
, idx
, tstamp
);
3704 dview
->setValue (PROP_DDSCR_LNK
, idx
, dview
->getIdByIdx (i
) + 1);
3705 // update this event
3706 dview
->setValue (PROP_HFREED
, i
, alloc
);
3711 dview
->setValue (PROP_HLEAKED
, i
, hsize
);
3712 heapmap
->allocate (vaddr
, i
+ 1);
3714 // Increase heap size
3715 memoryUsage
+= hsize
;
3716 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3721 // Adjust the size to be multiple of page_size
3722 //hsize = (( hsize - 1 ) / page_size + 1 ) * page_size;
3726 if (mtype
== MMAP_TRACE
)
3728 dview
->setValue (PROP_TSTAMP2
, i
, (uint64_t) MAX_TIME
);
3729 dview
->setValue (PROP_HLEAKED
, i
, hsize
);
3730 list
= heapmap
->mmap (vaddr
, hsize
, i
);
3732 // Increase heap size
3733 memoryUsage
+= hsize
;
3734 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3738 list
= heapmap
->munmap (vaddr
, hsize
);
3740 // Set allocation size to zero
3741 // Note: We're currently reusing PROP_HSIZE to mean allocation size
3742 // If we ever need to save the original HSIZE, we'll need to
3743 // create a new PROP_* to represent event allocation size
3745 // For now, tuck the original size away as HOVADDR
3746 dview
->setValue (PROP_HOVADDR
, i
, (uint64_t) hsize
);
3747 dview
->setValue (PROP_HSIZE
, i
, (uint64_t) 0);
3749 Size total_freed
= 0;
3752 long idx
= list
->val
;
3753 total_freed
+= list
->size
;
3754 Size leaked
= dview
->getLongValue (PROP_HLEAKED
, idx
);
3756 // Decrease heap size
3757 memoryUsage
-= list
->size
;
3758 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3760 Size leak_update
= leaked
- list
->size
;
3761 // update allocation
3762 dview
->setValue (PROP_HLEAKED
, idx
, leak_update
);
3763 // update allocation's list of frees
3765 UnmapChunk
*copy
= new UnmapChunk
;
3766 heapUnmapEvents
->append (copy
);
3767 copy
->val
= dview
->getIdByIdx (i
);
3768 copy
->size
= list
->size
;
3769 copy
->next
= (UnmapChunk
*) dview
->getObjValue (PROP_VOIDP_OBJ
, idx
);
3770 dview
->setObjValue (PROP_VOIDP_OBJ
, idx
, copy
);
3772 if (leak_update
<= 0)
3773 if (leak_update
== 0)
3774 dview
->setValue (PROP_TSTAMP2
, idx
, tstamp
);
3775 UnmapChunk
*t
= list
;
3779 // update this event
3781 // only need to write value if it is non-zero
3782 dview
->setValue (PROP_HFREED
, i
, total_freed
);
3785 // ignoring HEAPTYPE_LAST, which will never be recorded
3797 Experiment::get_heapsz_events ()
3799 DataDescriptor
*dDscr
= getDataDescriptor (DATA_HEAPSZ
);
3802 dDscr
= get_heap_events (); // derived from DATA_HEAP
3805 dDscr
= newDataDescriptor (DATA_HEAPSZ
, 0, dDscr
);
3810 update_heapsz_packet (std::set
<long> &pkt_id_set
, DataView
*dview
,
3811 long alloc_pkt_id
, int64_t net_alloc
, uint64_t leaks
)
3813 // pkt_id_set: set is updated to include packet
3814 // alloc_pkt_id: data descriptor id (NOT dview idx)
3815 // net_alloc: adjustment to net allocation for this packet (note: signed value)
3816 // leaks: leak bytes to attribute to alloc_pkt_id
3817 std::pair
< std::set
<long>::iterator
, bool> ret
;
3818 ret
= pkt_id_set
.insert (alloc_pkt_id
); // add to set
3819 bool new_to_set
= ret
.second
; // was not in set
3822 // Has been seen before, update values
3823 net_alloc
+= dview
->getDataDescriptorValue (PROP_HCUR_NET_ALLOC
, alloc_pkt_id
);
3826 uint64_t old
= dview
->getDataDescriptorValue (PROP_HCUR_LEAKS
, alloc_pkt_id
);
3831 dview
->setDataDescriptorValue (PROP_HCUR_NET_ALLOC
, alloc_pkt_id
, net_alloc
);
3832 dview
->setDataDescriptorValue (PROP_HCUR_LEAKS
, alloc_pkt_id
, leaks
);
3836 Experiment::create_heapsz_data_view (DataView
*heap_dview
)
3838 // heap_dview has DATA_HEAP _filtered_ packets.
3839 // This creates, populates, and returns DATA_HEAPSZ DataView
3840 DataDescriptor
*dDscr
= get_heapsz_events ();
3843 std::set
<long> pkt_id_set
;
3844 DataView
*dview
= heap_dview
;
3845 long sz
= dview
->getSize ();
3846 for (long i
= 0; i
< sz
; i
++)
3848 int64_t hsize
= (int64_t) dview
->getULongValue (PROP_HSIZE
, i
);
3849 uint64_t leaks
= dview
->getULongValue (PROP_HLEAKED
, i
);
3850 long alloc_pkt_id
= dview
->getIdByIdx (i
);
3851 update_heapsz_packet (pkt_id_set
, dview
, alloc_pkt_id
, hsize
, leaks
);
3854 UnmapChunk
*mmap_frees
= (UnmapChunk
*) dview
->getObjValue (PROP_VOIDP_OBJ
, i
); // mmap metadata
3857 // mmap: all frees associated with this packet
3860 long free_pkt_id
= mmap_frees
->val
;
3861 int64_t free_sz
= mmap_frees
->size
;
3862 update_heapsz_packet (pkt_id_set
, dview
, free_pkt_id
, -free_sz
, 0);
3863 mmap_frees
= mmap_frees
->next
;
3868 // malloc: check for associated free
3869 long free_pkt_id
= dview
->getLongValue (PROP_DDSCR_LNK
, i
) - 1;
3870 if (free_pkt_id
>= 0)
3871 update_heapsz_packet (pkt_id_set
, dview
, free_pkt_id
, -hsize
, 0);
3875 // create a new DataView based on the filtered-in and associated free events
3876 std::set
<long>::iterator it
;
3877 DataView
*heapsz_dview
= dDscr
->createExtManagedView ();
3878 for (it
= pkt_id_set
.begin (); it
!= pkt_id_set
.end (); ++it
)
3880 long ddscr_pkt_id
= *it
;
3881 heapsz_dview
->appendDataDescriptorId (ddscr_pkt_id
);
3883 compute_heapsz_data_view (heapsz_dview
);
3884 return heapsz_dview
;
3888 Experiment::compute_heapsz_data_view (DataView
*heapsz_dview
)
3890 DataView
*dview
= heapsz_dview
;
3892 // Keep track of memory usage
3893 int64_t currentAllocs
= 0;
3894 Size currentLeaks
= 0;
3895 dview
->sort (PROP_TSTAMP
);
3896 long sz
= dview
->getSize ();
3897 for (long i
= 0; i
< sz
; i
++)
3899 int64_t net_alloc
= dview
->getLongValue (PROP_HCUR_NET_ALLOC
, i
);
3900 currentAllocs
+= net_alloc
;
3901 dview
->setValue (PROP_HCUR_ALLOCS
, i
, currentAllocs
);
3903 Size leaks
= dview
->getULongValue (PROP_HCUR_LEAKS
, i
);
3904 currentLeaks
+= leaks
;
3905 dview
->setValue (PROP_HCUR_LEAKS
, i
, currentLeaks
);
3910 Experiment::DBG_memuse (Sample
* s
)
3912 DataDescriptor
*dDscr
= getDataDescriptor (DATA_HEAP
);
3913 if (dDscr
== NULL
|| dDscr
->getSize () == 0)
3916 DataView
*dview
= dDscr
->createView ();
3917 dview
->sort (PROP_TSTAMP
);
3918 hrtime_t ts1
= s
->get_start_time ();
3919 hrtime_t ts2
= s
->get_end_time ();
3921 HeapMap
*heapmap
= new HeapMap ();
3922 long sz
= dview
->getSize ();
3925 hrtime_t maxTime
= 0;
3926 for (long i
= 0; i
< sz
; i
++)
3928 hrtime_t tstamp
= dview
->getLongValue (PROP_TSTAMP
, i
);
3934 Heap_type mtype
= (Heap_type
) dview
->getIntValue (PROP_HTYPE
, i
);
3935 Vaddr vaddr
= dview
->getULongValue (PROP_HVADDR
, i
);
3936 Vaddr ovaddr
= dview
->getULongValue (PROP_HOVADDR
, i
);
3955 long idx
= heapmap
->deallocate (ovaddr
) - 1;
3957 curSize
-= dview
->getULongValue (PROP_HSIZE
, idx
);
3961 heapmap
->allocate (vaddr
, i
+ 1);
3962 curSize
+= dview
->getULongValue (PROP_HSIZE
, i
);
3963 if (curSize
> maxSize
)
3970 printf ("SAMPLE=%s (id=%d) MEMUSE=%lld TSTAMP=%lld\n", s
->get_start_label (),
3971 s
->get_number (), maxSize
, maxTime
- getStartTime ());
3977 Experiment::DBG_memuse (const char *sname
)
3979 for (int i
= 0; i
< samples
->size (); ++i
)
3981 Sample
*sample
= samples
->fetch (i
);
3982 if (streq (sname
, sample
->get_start_label ()))
3984 DBG_memuse (sample
);
3991 Experiment::get_race_events ()
3993 DataDescriptor
*dDscr
= getDataDescriptor (DATA_RACE
);
3996 if (dDscr
->getSize () == 0)
3998 char *base_name
= get_basename (expt_name
);
3999 char *msg
= dbe_sprintf (GTXT ("Loading Race Data: %s"), base_name
);
4000 read_data_file (SP_RACETRACE_FILE
, msg
);
4002 resolve_frame_info (dDscr
);
4008 Experiment::get_deadlock_events ()
4010 DataDescriptor
*dDscr
= getDataDescriptor (DATA_DLCK
);
4013 if (dDscr
->getSize () == 0)
4015 char *base_name
= get_basename (expt_name
);
4016 char *msg
= dbe_sprintf (GTXT ("Loading Deadlocks Data: %s"), base_name
);
4017 read_data_file (SP_DEADLOCK_FILE
, msg
);
4019 resolve_frame_info (dDscr
);
4025 Experiment::get_sample_events ()
4027 DataDescriptor
*dDscr
= getDataDescriptor (DATA_SAMPLE
);
4030 if (dDscr
->getSize () > 0)
4033 // read_overview_file(); //YXXX do this here at some point instead of:
4034 PropDescr
*tmp_propDscr
;
4035 tmp_propDscr
= new PropDescr (PROP_SMPLOBJ
, NTXT ("SMPLOBJ"));
4036 tmp_propDscr
->uname
= NULL
;
4037 tmp_propDscr
->vtype
= TYPE_OBJ
;
4038 dDscr
->addProperty (tmp_propDscr
);
4040 tmp_propDscr
= new PropDescr (PROP_TSTAMP
, NTXT ("TSTAMP"));
4041 tmp_propDscr
->uname
= dbe_strdup ("High resolution timestamp");
4042 tmp_propDscr
->vtype
= TYPE_UINT64
;
4043 dDscr
->addProperty (tmp_propDscr
);
4045 tmp_propDscr
= new PropDescr (PROP_SAMPLE
, NTXT ("SAMPLE"));
4046 tmp_propDscr
->uname
= dbe_strdup ("Sample number");
4047 tmp_propDscr
->vtype
= TYPE_UINT64
;
4048 dDscr
->addProperty (tmp_propDscr
);
4050 tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, NTXT ("EVT_TIME"));
4051 tmp_propDscr
->uname
= dbe_strdup ("Event duration");
4052 tmp_propDscr
->vtype
= TYPE_UINT64
;
4053 dDscr
->addProperty (tmp_propDscr
);
4055 long ssize
= samples
->size ();
4056 for (long ii
= 0; ii
< ssize
; ii
++)
4058 Sample
* sample
= samples
->fetch (ii
);
4059 long recn
= dDscr
->addRecord ();
4060 hrtime_t sduration
= sample
->get_end_time () - sample
->get_start_time ();
4061 dDscr
->setObjValue (PROP_SMPLOBJ
, recn
, sample
);
4062 dDscr
->setValue (PROP_SAMPLE
, recn
, sample
->get_number ());
4063 dDscr
->setValue (PROP_TSTAMP
, recn
, sample
->get_end_time ());
4064 dDscr
->setValue (PROP_EVT_TIME
, recn
, sduration
);
4070 Experiment::get_gc_events ()
4072 DataDescriptor
*dDscr
= getDataDescriptor (DATA_GCEVENT
);
4075 if (dDscr
->getSize () > 0)
4078 // read_overview_file(); //YXXX do this here at some point instead of:
4079 PropDescr
*tmp_propDscr
;
4080 tmp_propDscr
= new PropDescr (PROP_GCEVENTOBJ
, NTXT ("GCEVENTOBJ"));
4081 tmp_propDscr
->uname
= NULL
;
4082 tmp_propDscr
->vtype
= TYPE_OBJ
;
4083 dDscr
->addProperty (tmp_propDscr
);
4085 tmp_propDscr
= new PropDescr (PROP_TSTAMP
, NTXT ("TSTAMP"));
4086 tmp_propDscr
->uname
= dbe_strdup ("High resolution timestamp");
4087 tmp_propDscr
->vtype
= TYPE_UINT64
;
4088 dDscr
->addProperty (tmp_propDscr
);
4090 tmp_propDscr
= new PropDescr (PROP_GCEVENT
, NTXT ("GCEVENT"));
4091 tmp_propDscr
->uname
= dbe_strdup ("GCEvent number");
4092 tmp_propDscr
->vtype
= TYPE_UINT64
;
4093 dDscr
->addProperty (tmp_propDscr
);
4095 tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, NTXT ("EVT_TIME"));
4096 tmp_propDscr
->uname
= dbe_strdup ("Event duration");
4097 tmp_propDscr
->vtype
= TYPE_UINT64
;
4098 dDscr
->addProperty (tmp_propDscr
);
4100 long ssize
= gcevents
->size ();
4101 for (long ii
= 0; ii
< ssize
; ii
++)
4103 GCEvent
* gcevent
= gcevents
->fetch (ii
);
4104 long recn
= dDscr
->addRecord ();
4105 hrtime_t sduration
= gcevent
->end
- gcevent
->start
;
4106 dDscr
->setObjValue (PROP_GCEVENTOBJ
, recn
, gcevent
);
4107 dDscr
->setValue (PROP_GCEVENT
, recn
, gcevent
->id
);
4108 dDscr
->setValue (PROP_TSTAMP
, recn
, gcevent
->end
);
4109 dDscr
->setValue (PROP_EVT_TIME
, recn
, sduration
);
4115 Experiment::update_last_event (hrtime_t ts
/*wall_ts*/)
4117 if (last_event
== ZERO_TIME
)
4119 // not yet initialized
4122 if (last_event
- exp_start_time
< ts
- exp_start_time
)
4123 // compare deltas to avoid hrtime_t wrap
4128 Experiment::write_header ()
4132 // write commentary to the experiment, describing the parameters
4133 if (dbeSession
->ipc_mode
|| dbeSession
->rdt_mode
)
4135 // In GUI: print start time at the beginning
4136 time_t t
= (time_t) start_sec
;
4137 char *start_time
= ctime (&t
);
4138 if (start_time
!= NULL
)
4141 sb
.sprintf (GTXT ("Experiment started %s"), start_time
);
4142 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4145 // write message with target arglist
4146 if (uarglist
!= NULL
)
4149 sb
.sprintf (GTXT ("\nTarget command (%s): '%s'"),
4150 (wsize
== W32
? "32-bit" : "64-bit"), uarglist
);
4151 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4155 sb
.sprintf (GTXT ("Process pid %d, ppid %d, pgrp %d, sid %d"),
4156 pid
, ppid
, pgrp
, sid
);
4157 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4159 // add comment for user name, if set
4160 if (username
!= NULL
)
4163 sb
.sprintf (GTXT ("User: `%s'"), username
);
4164 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4167 // add comment for current working directory
4171 sb
.sprintf (GTXT ("Current working directory: %s"), ucwd
);
4172 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4175 // add comment for collector version string
4176 if (cversion
!= NULL
)
4182 wstring
= NTXT ("?");
4185 wstring
= GTXT ("32-bit");
4188 wstring
= GTXT ("64-bit");
4191 wstring
= NTXT ("??");
4195 sb
.sprintf (GTXT ("Collector version: `%s'; experiment version %d.%d (%s)"),
4196 cversion
, exp_maj_version
, exp_min_version
, wstring
);
4197 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4200 // add comment for driver version string (er_kernel)
4201 if (dversion
!= NULL
)
4204 sb
.sprintf (GTXT ("Kernel driver version: `%s'"), dversion
);
4205 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4208 if (jversion
!= NULL
)
4211 sb
.sprintf (GTXT ("JVM version: `%s'"), jversion
);
4212 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4215 // add comment for hostname, parameters
4216 if (hostname
== NULL
)
4217 hostname
= dbe_strdup (GTXT ("unknown"));
4218 if (os_version
== NULL
)
4219 os_version
= dbe_strdup (GTXT ("unknown"));
4220 if (architecture
== NULL
)
4221 architecture
= dbe_strdup (GTXT ("unknown"));
4223 sb
.sprintf (GTXT ("Host `%s', OS `%s', page size %d, architecture `%s'"),
4224 hostname
, os_version
, page_size
, architecture
);
4225 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4228 if (maxclock
!= minclock
)
4232 GTXT (" %d CPUs, with clocks ranging from %d to %d MHz.; max of %d MHz. assumed"),
4233 ncpus
, minclock
, maxclock
, clock
);
4236 sb
.sprintf (GTXT (" %d CPU%s, clock speed %d MHz."),
4237 ncpus
, (ncpus
== 1 ? NTXT ("") : "s"), clock
);
4238 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4240 // add comment for machine memory size
4241 if (page_size
> 0 && npages
> 0)
4243 long long memsize
= ((long long) npages
* page_size
) / (1024 * 1024);
4245 sb
.sprintf (GTXT (" Memory: %d pages @ %d = %lld MB."),
4246 npages
, page_size
, memsize
);
4247 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4250 // add comment for machine memory size
4251 if (machinemodel
!= NULL
)
4254 sb
.sprintf (GTXT (" Machine model: %s"), machinemodel
);
4255 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4258 // add comment for start time
4259 time_t t
= (time_t) start_sec
;
4260 char *p
= ctime (&t
);
4263 sb
.sprintf (GTXT ("Experiment started %s"), p
);
4265 sb
.sprintf (GTXT ("\nExperiment start not recorded"));
4266 write_coll_params ();
4267 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4268 commentq
->appendqueue (runlogq
);
4269 runlogq
->mark_clear ();
4273 Experiment::write_coll_params ()
4277 // now write the various collection parameters as comments
4279 sb
.append (GTXT ("Data collection parameters:"));
4280 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4281 if (coll_params
.profile_mode
== 1)
4284 sb
.sprintf (GTXT (" Clock-profiling, interval = %d microsecs."),
4285 (int) (coll_params
.ptimer_usec
));
4286 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4288 if (coll_params
.sync_mode
== 1)
4291 char *scope_str
= NTXT ("");
4292 switch (coll_params
.sync_scope
)
4295 scope_str
= GTXT ("Native- and Java-APIs");
4297 case SYNCSCOPE_JAVA
:
4298 scope_str
= GTXT ("JAVA-APIs");
4300 case SYNCSCOPE_NATIVE
:
4301 scope_str
= GTXT ("Native-APIs");
4303 case SYNCSCOPE_JAVA
| SYNCSCOPE_NATIVE
:
4304 scope_str
= GTXT ("Native- and Java-APIs");
4307 if (coll_params
.sync_threshold
< 0)
4308 sb
.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs. (calibrated); %s"),
4309 -coll_params
.sync_threshold
, scope_str
);
4311 sb
.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs.; %s"),
4312 coll_params
.sync_threshold
, scope_str
);
4313 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4315 if (coll_params
.heap_mode
== 1)
4318 sb
.append (GTXT (" Heap tracing"));
4319 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4321 if (coll_params
.io_mode
== 1)
4324 sb
.append (GTXT (" IO tracing"));
4325 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4327 if (coll_params
.race_mode
== 1)
4330 char *race_stack_name
;
4331 switch (coll_params
.race_stack
)
4334 race_stack_name
= GTXT ("dual-stack");
4337 race_stack_name
= GTXT ("single-stack");
4340 race_stack_name
= GTXT ("leaf");
4345 sb
.sprintf (GTXT (" Datarace detection, %s"), race_stack_name
);
4346 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4348 if (coll_params
.deadlock_mode
== 1)
4351 sb
.append (GTXT (" Deadlock detection"));
4352 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4354 if (coll_params
.hw_mode
== 1)
4357 if (hwc_default
== true)
4358 sb
.append (GTXT (" HW counter-profiling (default); counters:"));
4360 sb
.append (GTXT (" HW counter-profiling; counters:"));
4361 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4362 for (int i
= 0; i
< MAX_HWCOUNT
; i
++)
4364 if (!coll_params
.hw_aux_name
[i
])
4367 sb
.sprintf (GTXT (" %s, tag %d, interval %d, memop %d"),
4368 coll_params
.hw_aux_name
[i
], i
,
4369 coll_params
.hw_interval
[i
], coll_params
.hw_tpc
[i
]);
4370 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4373 if (coll_params
.sample_periodic
== 1)
4376 sb
.sprintf (GTXT (" Periodic sampling, %d secs."),
4377 coll_params
.sample_timer
);
4378 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4380 if (coll_params
.limit
!= 0)
4383 sb
.sprintf (GTXT (" Experiment size limit, %d"),
4385 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4387 if (coll_params
.linetrace
!= NULL
)
4390 sb
.sprintf (GTXT (" Follow descendant processes from: %s"),
4391 coll_params
.linetrace
);
4392 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4394 if (coll_params
.pause_sig
!= NULL
)
4397 sb
.sprintf (GTXT (" Pause signal %s"), coll_params
.pause_sig
);
4398 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4400 if (coll_params
.sample_sig
!= NULL
)
4403 sb
.sprintf (GTXT (" Sample signal %s"), coll_params
.sample_sig
);
4404 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4406 if (coll_params
.start_delay
!= NULL
)
4409 sb
.sprintf (GTXT (" Data collection delay start %s seconds"), coll_params
.start_delay
);
4410 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4412 if (coll_params
.terminate
!= NULL
)
4415 sb
.sprintf (GTXT (" Data collection termination after %s seconds"), coll_params
.terminate
);
4416 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4418 // add a blank line after data description
4419 commentq
->append (new Emsg (CMSG_COMMENT
, NTXT ("")));
4424 * Raw packet processing
4427 check_mstate (char *ptr
, PacketDescriptor
*pDscr
, int arg
)
4445 Vector
<FieldDescr
*> *fields
= pDscr
->getFields ();
4446 for (int i
= 0, sz
= fields
->size (); i
< sz
; i
++)
4448 FieldDescr
*fDscr
= fields
->fetch (i
);
4449 if (fDscr
->propID
== arg
)
4450 return *((int*) (ptr
+ fDscr
->offset
));
4455 #define PACKET_ALIGNMENT 4
4458 Experiment::readPacket (Data_window
*dwin
, Data_window::Span
*span
)
4460 Common_packet
*rcp
= (Common_packet
*) dwin
->bind (span
,
4461 sizeof (CommonHead_packet
));
4466 if ((((long) rcp
) % PACKET_ALIGNMENT
) != 0)
4469 size
= PROFILE_BUFFER_CHUNK
- span
->offset
% PROFILE_BUFFER_CHUNK
;
4472 v16
= (uint16_t) rcp
->tsize
;
4473 size
= dwin
->decode (v16
);
4476 size
= PROFILE_BUFFER_CHUNK
- span
->offset
% PROFILE_BUFFER_CHUNK
;
4479 rcp
= (Common_packet
*) dwin
->bind (span
, size
);
4484 if ((((long) rcp
) % PACKET_ALIGNMENT
) != 0)
4487 size
= PROFILE_BUFFER_CHUNK
- span
->offset
% PROFILE_BUFFER_CHUNK
;
4490 v16
= (uint16_t) rcp
->type
;
4491 uint32_t rcptype
= dwin
->decode (v16
);
4492 if (rcptype
== EMPTY_PCKT
)
4494 if (rcptype
== FRAME_PCKT
)
4496 RawFramePacket
*fp
= new RawFramePacket
;
4497 fp
->uid
= dwin
->decode (((Frame_packet
*) rcp
)->uid
);
4502 char *ptr
= (char*) rcp
+ dwin
->decode (((Frame_packet
*) rcp
)->hsize
);
4503 if ((((long) ptr
) % PACKET_ALIGNMENT
) != 0)
4509 v16
= (uint16_t) ((Frame_packet
*) rcp
)->tsize
;
4510 char *end
= (char*) rcp
+ dwin
->decode (v16
);
4513 Common_info
*cinfo
= (Common_info
*) ptr
;
4514 uint32_t hsize
= dwin
->decode (cinfo
->hsize
);
4515 if (hsize
== 0 || ptr
+ hsize
> end
)
4517 int kind
= dwin
->decode (cinfo
->kind
);
4518 bool compressed
= false;
4519 if (kind
& COMPRESSED_INFO
)
4522 kind
&= ~COMPRESSED_INFO
;
4528 char *stack
= ptr
+ sizeof (Stack_info
);
4529 size_t stack_size
= hsize
- sizeof (Stack_info
);
4530 uint64_t uidn
= dwin
->decode (((Stack_info
*) cinfo
)->uid
);
4531 if (stack_size
<= 0)
4533 fp
->uidn
= get_uid_node (uidn
);
4536 uint64_t link_uid
= (uint64_t) 0;
4539 stack_size
-= sizeof (uint64_t);
4540 unsigned char *s
= (unsigned char*) (stack
+ stack_size
);
4542 for (size_t i
= 0; i
<sizeof (link_uid
); i
++)
4544 link_uid
|= (uint64_t) * s
++ << shift
;
4549 fp
->uidn
= add_uid (dwin
, uidn
,
4550 (int) (stack_size
/ sizeof (uint32_t)),
4551 (uint32_t*) stack
, link_uid
);
4553 fp
->uidn
= add_uid (dwin
, uidn
,
4554 (int) (stack_size
/ sizeof (uint64_t)),
4555 (uint64_t*) stack
, link_uid
);
4560 char *stack
= ptr
+ sizeof (Java_info
);
4561 size_t stack_size
= hsize
- sizeof (Java_info
);
4562 uint64_t uidj
= dwin
->decode (((Java_info
*) cinfo
)->uid
);
4563 if (stack_size
<= 0)
4565 fp
->uidj
= get_uid_node (uidj
);
4569 uint64_t link_uid
= (uint64_t) 0;
4572 stack_size
-= sizeof (uint64_t);
4573 unsigned char *s
= (unsigned char*) (stack
+ stack_size
);
4575 for (size_t i
= 0; i
<sizeof (link_uid
); i
++)
4577 link_uid
|= (uint64_t) * s
++ << shift
;
4582 fp
->uidj
= add_uid (dwin
, uidj
,
4583 (int) (stack_size
/ sizeof (uint32_t)),
4584 (uint32_t*) stack
, link_uid
);
4587 // bug 6909545: garbage in 64-bit JAVA_INFO
4588 char *nstack
= (char*) xmalloc (stack_size
);
4590 char *srcmax
= stack
+ stack_size
- sizeof (uint64_t);
4591 for (char *src
= stack
; src
<= srcmax
;)
4593 int64_t val
= dwin
->decode (*(int32_t*) src
);
4594 *(uint64_t*) dst
= dwin
->decode (val
);
4595 src
+= sizeof (uint64_t);
4596 dst
+= sizeof (uint64_t);
4599 fprintf (stderr
, "er_print: Experiment::readPacket: Error in data: src=%llx greater than %llx\n",
4600 (long long) src
, (long long) srcmax
);
4603 *(uint64_t*) dst
= *(uint64_t*) src
;
4604 src
+= sizeof (uint64_t);
4605 dst
+= sizeof (uint64_t);
4607 fp
->uidj
= add_uid (dwin
, uidj
,
4608 (int) (stack_size
/ sizeof (uint64_t)),
4609 (uint64_t*) nstack
, link_uid
);
4615 fp
->omp_state
= dwin
->decode (((OMP_info
*) ptr
)->omp_state
);
4619 uint64_t omp_uid
= dwin
->decode (((OMP2_info
*) ptr
)->uid
);
4620 fp
->omp_uid
= get_uid_node (omp_uid
);
4621 fp
->omp_state
= dwin
->decode (((OMP2_info
*) ptr
)->omp_state
);
4629 frmpckts
->append (fp
);
4632 else if (rcptype
== UID_PCKT
)
4634 Uid_packet
*uidp
= (Uid_packet
*) rcp
;
4635 uint64_t uid
= dwin
->decode (uidp
->uid
);
4636 char *arr_bytes
= (char*) (uidp
+ 1);
4637 v16
= (uint16_t) rcp
->tsize
;
4638 size_t arr_length
= dwin
->decode (v16
) - sizeof (Uid_packet
);
4639 if (arr_length
<= 0)
4641 uint64_t link_uid
= (uint64_t) 0;
4642 if (dwin
->decode (uidp
->flags
) & COMPRESSED_INFO
)
4644 arr_length
-= sizeof (uint64_t);
4645 unsigned char *s
= (unsigned char*) (arr_bytes
+ arr_length
);
4647 for (size_t i
= 0; i
<sizeof (link_uid
); i
++)
4649 link_uid
|= (uint64_t) * s
++ << shift
;
4654 add_uid (dwin
, uid
, (int) (arr_length
/ sizeof (uint32_t)),
4655 (uint32_t*) arr_bytes
, link_uid
);
4657 add_uid (dwin
, uid
, (int) (arr_length
/ sizeof (uint64_t)),
4658 (uint64_t*) arr_bytes
, link_uid
);
4662 PacketDescriptor
*pcktDescr
= getPacketDescriptor (rcptype
);
4663 if (pcktDescr
== NULL
)
4665 DataDescriptor
*dataDescr
= pcktDescr
->getDataDescriptor ();
4666 if (dataDescr
== NULL
)
4669 /* omazur: TBR START -- old experiment */
4670 if (rcptype
== PROF_PCKT
)
4672 // For backward compatibility with older SS12 experiments
4673 int numstates
= get_params ()->lms_magic_id
; // ugly, for old experiments
4674 if (numstates
> LMS_NUM_SOLARIS_MSTATES
)
4675 numstates
= LMS_NUM_SOLARIS_MSTATES
;
4676 for (int i
= 0; i
< numstates
; i
++)
4677 if (check_mstate ((char*) rcp
, pcktDescr
, PROP_UCPU
+ i
))
4678 readPacket (dwin
, (char*) rcp
, pcktDescr
, dataDescr
, PROP_UCPU
+ i
,
4682 readPacket (dwin
, (char*) rcp
, pcktDescr
, dataDescr
, 0, size
);
4686 static uint32_t get_v32(char *p
)
4689 memcpy (&v
, p
, sizeof(uint32_t));
4693 static uint64_t get_v64(char *p
)
4696 memcpy (&v
, p
, sizeof(uint64_t));
4701 Experiment::readPacket (Data_window
*dwin
, char *ptr
, PacketDescriptor
*pDscr
,
4702 DataDescriptor
*dDscr
, int arg
, uint64_t pktsz
)
4704 long recn
= dDscr
->addRecord ();
4705 Vector
<FieldDescr
*> *fields
= pDscr
->getFields ();
4708 int sz
= fields
->size ();
4709 for (int i
= 0; i
< sz
; i
++)
4711 FieldDescr
*field
= fields
->fetch (i
);
4712 if (field
->propID
== arg
)
4714 v32
= get_v32(ptr
+ field
->offset
);
4715 dDscr
->setValue (PROP_NTICK
, recn
, dwin
->decode (v32
));
4716 dDscr
->setValue (PROP_MSTATE
, recn
, (uint32_t) (field
->propID
- PROP_UCPU
));
4718 if (field
->propID
== PROP_THRID
|| field
->propID
== PROP_LWPID
4719 || field
->propID
== PROP_CPUID
)
4722 switch (field
->vtype
)
4726 v32
= get_v32 (ptr
+ field
->offset
);
4727 tmp64
= dwin
->decode (v32
);
4731 v64
= get_v64 (ptr
+ field
->offset
);
4732 tmp64
= dwin
->decode (v64
);
4744 uint32_t tag
= mapTagValue ((Prop_type
) field
->propID
, tmp64
);
4745 dDscr
->setValue (field
->propID
, recn
, tag
);
4749 switch (field
->vtype
)
4753 v32
= get_v32 (ptr
+ field
->offset
);
4754 dDscr
->setValue (field
->propID
, recn
, dwin
->decode (v32
));
4758 v64
= get_v64 (ptr
+ field
->offset
);
4759 dDscr
->setValue (field
->propID
, recn
, dwin
->decode (v64
));
4763 int len
= (int) (pktsz
- field
->offset
);
4764 if ((len
> 0) && (ptr
[field
->offset
] != 0))
4766 StringBuilder
*sb
= new StringBuilder ();
4767 sb
->append (ptr
+ field
->offset
, 0, len
);
4768 dDscr
->setObjValue (field
->propID
, recn
, sb
);
4772 // ignoring the following cases (why?)
4786 #define PROG_BYTE 102400 // update progress bar every PROG_BYTE bytes
4789 Experiment::read_data_file (const char *fname
, const char *msg
)
4791 Data_window::Span span
;
4792 off64_t total_len
, remain_len
;
4793 char *progress_bar_msg
;
4794 int progress_bar_percent
= -1;
4796 char *data_file_name
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, fname
);
4797 Data_window
*dwin
= new Data_window (data_file_name
);
4798 // Here we can call stat(data_file_name) to get file size,
4799 // and call a function to reallocate vectors for clock profiling data
4800 free (data_file_name
);
4801 if (dwin
->not_opened ())
4806 dwin
->need_swap_endian
= need_swap_endian
;
4809 span
.length
= dwin
->get_fsize ();
4810 total_len
= remain_len
= span
.length
;
4811 progress_bar_msg
= dbe_sprintf (NTXT ("%s %s"), NTXT (" "), msg
);
4815 uint64_t pcktsz
= readPacket (dwin
, &span
);
4818 // Update progress bar
4819 if ((span
.length
<= remain_len
) && (remain_len
> 0))
4821 int percent
= (int) (100 * (total_len
- remain_len
) / total_len
);
4822 if (percent
> progress_bar_percent
)
4824 progress_bar_percent
+= 10;
4825 theApplication
->set_progress (percent
, progress_bar_msg
);
4827 remain_len
-= PROG_BYTE
;
4829 span
.length
-= pcktsz
;
4830 span
.offset
+= pcktsz
;
4837 sb
.sprintf (GTXT ("WARNING: There are %d invalid packet(s) in the %s file"),
4838 invalid_packet
, fname
);
4839 Emsg
*m
= new Emsg (CMSG_WARN
, sb
);
4843 theApplication
->set_progress (0, NTXT (""));
4844 free (progress_bar_msg
);
4848 Experiment::read_overview_file ()
4850 char *data_file_name
= dbe_sprintf ("%s/%s", expt_name
, SP_OVERVIEW_FILE
);
4851 Data_window
*dwin
= new Data_window (data_file_name
);
4852 free (data_file_name
);
4853 if (dwin
->not_opened ())
4858 dwin
->need_swap_endian
= need_swap_endian
;
4859 newDataDescriptor (DATA_SAMPLE
);
4861 Data_window::Span span
;
4863 span
.length
= dwin
->get_fsize ();
4865 PrUsage
*data
= NULL
, *data_prev
= NULL
;
4867 int sample_number
= 1;
4871 prDataSize
= PrUsage::bind32Size ();
4873 prDataSize
= PrUsage::bind64Size ();
4875 while (span
.length
> 0)
4878 data
= new PrUsage ();
4880 void *dw
= dwin
->bind (&span
, prDataSize
);
4881 if ((dw
== NULL
) || (prDataSize
> span
.length
))
4883 Emsg
*m
= new Emsg (CMSG_ERROR
, GTXT ("Warning: overview data file can't be read"));
4891 data
->bind32 (dw
, need_swap_endian
);
4893 data
->bind64 (dw
, need_swap_endian
);
4894 span
.length
-= prDataSize
;
4895 span
.offset
+= prDataSize
;
4897 // Skip the first packet
4898 if (data_prev
== NULL
)
4900 if (sample_number
> samples
->size ())
4901 { // inconsistent log/overview
4902 sample
= new Sample (sample_number
);
4903 char * label
= GTXT ("<unknown>");
4904 sample
->start_label
= dbe_strdup (label
);
4905 sample
->end_label
= dbe_strdup (label
);
4906 samples
->append (sample
);
4909 sample
= samples
->fetch (sample_number
- 1);
4911 sample
->start_time
= data_prev
->pr_tstamp
+ 1;
4912 sample
->end_time
= data
->pr_tstamp
;
4913 sample
->prusage
= data_prev
;
4915 data_prev
->pr_rtime
= data
->pr_rtime
- data_prev
->pr_rtime
;
4916 data_prev
->pr_utime
= data
->pr_utime
- data_prev
->pr_utime
;
4917 data_prev
->pr_stime
= data
->pr_stime
- data_prev
->pr_stime
;
4918 data_prev
->pr_ttime
= data
->pr_ttime
- data_prev
->pr_ttime
;
4919 data_prev
->pr_tftime
= data
->pr_tftime
- data_prev
->pr_tftime
;
4920 data_prev
->pr_dftime
= data
->pr_dftime
- data_prev
->pr_dftime
;
4921 data_prev
->pr_kftime
= data
->pr_kftime
- data_prev
->pr_kftime
;
4922 data_prev
->pr_ltime
= data
->pr_ltime
- data_prev
->pr_ltime
;
4923 data_prev
->pr_slptime
= data
->pr_slptime
- data_prev
->pr_slptime
;
4924 data_prev
->pr_wtime
= data
->pr_wtime
- data_prev
->pr_wtime
;
4925 data_prev
->pr_stoptime
= data
->pr_stoptime
- data_prev
->pr_stoptime
;
4926 data_prev
->pr_minf
= data
->pr_minf
- data_prev
->pr_minf
;
4927 data_prev
->pr_majf
= data
->pr_majf
- data_prev
->pr_majf
;
4928 data_prev
->pr_nswap
= data
->pr_nswap
- data_prev
->pr_nswap
;
4929 data_prev
->pr_inblk
= data
->pr_inblk
- data_prev
->pr_inblk
;
4930 data_prev
->pr_oublk
= data
->pr_oublk
- data_prev
->pr_oublk
;
4931 data_prev
->pr_msnd
= data
->pr_msnd
- data_prev
->pr_msnd
;
4932 data_prev
->pr_mrcv
= data
->pr_mrcv
- data_prev
->pr_mrcv
;
4933 data_prev
->pr_sigs
= data
->pr_sigs
- data_prev
->pr_sigs
;
4934 data_prev
->pr_vctx
= data
->pr_vctx
- data_prev
->pr_vctx
;
4935 data_prev
->pr_ictx
= data
->pr_ictx
- data_prev
->pr_ictx
;
4936 data_prev
->pr_sysc
= data
->pr_sysc
- data_prev
->pr_sysc
;
4937 data_prev
->pr_ioch
= data
->pr_ioch
- data_prev
->pr_ioch
;
4938 sample
->get_usage (); // force validation
4941 for (long smpNum
= samples
->size (); smpNum
>= sample_number
; smpNum
--)
4943 // overview file was truncated
4944 sample
= samples
->remove (smpNum
- 1);
4950 // Update last_event so that getEndTime() covers
4951 // all loadobjects, too.
4952 update_last_event (data
->pr_tstamp
);
4960 Experiment::uidNodeCmp (const void *a
, const void *b
)
4962 UIDnode
*nd1
= *(UIDnode
**) a
;
4963 UIDnode
*nd2
= *(UIDnode
**) b
;
4964 if (nd1
->uid
== nd2
->uid
)
4966 return nd1
->uid
< nd2
->uid
? -1 : 1;
4970 funcAddr (uint32_t val
)
4972 if (val
== (uint32_t) SP_LEAF_CHECK_MARKER
)
4973 return (uint64_t) SP_LEAF_CHECK_MARKER
;
4974 if (val
== (uint32_t) SP_TRUNC_STACK_MARKER
)
4975 return (uint64_t) SP_TRUNC_STACK_MARKER
;
4976 if (val
== (uint32_t) SP_FAILED_UNWIND_MARKER
)
4977 return (uint64_t) SP_FAILED_UNWIND_MARKER
;
4981 Experiment::UIDnode
*
4982 Experiment::add_uid (Data_window
*dwin
, uint64_t uid
, int size
,
4983 uint32_t *array
, uint64_t link_uid
)
4985 if (uid
== (uint64_t) 0)
4987 uint64_t val
= funcAddr (dwin
->decode (array
[0]));
4988 UIDnode
*node
= NULL
;
4989 UIDnode
*res
= get_uid_node (uid
, val
);
4990 UIDnode
*next
= res
;
4991 for (int i
= 0; i
< size
; i
++)
4993 val
= funcAddr (dwin
->decode (array
[i
]));
4996 next
= get_uid_node ((uint64_t) 0, val
);
5004 else if (node
->val
!= val
) // Algorithmic error (should never happen)
5005 node
->val
= (uint64_t) SP_LEAF_CHECK_MARKER
;
5007 if (next
== NULL
&& link_uid
!= (uint64_t) 0 && node
!= NULL
)
5008 node
->next
= get_uid_node (link_uid
);
5012 Experiment::UIDnode
*
5013 Experiment::add_uid (Data_window
*dwin
, uint64_t uid
, int size
, uint64_t *array
, uint64_t link_uid
)
5015 if (uid
== (uint64_t) 0)
5017 UIDnode
*node
= NULL
;
5018 uint64_t val
= dwin
->decode (array
[0]);
5019 UIDnode
*res
= get_uid_node (uid
, val
);
5020 UIDnode
*next
= res
;
5021 for (int i
= 0; i
< size
; i
++)
5023 val
= dwin
->decode (array
[i
]);
5026 next
= get_uid_node ((uint64_t) 0, val
);
5032 if (node
->val
== (uint64_t) 0)
5034 else if (node
->val
!= val
) // Algorithmic error (should never happen)
5035 node
->val
= (uint64_t) - 1;
5037 if (next
== NULL
&& link_uid
!= (uint64_t) 0 && node
!= NULL
)
5038 node
->next
= get_uid_node (link_uid
);
5042 Experiment::UIDnode
*
5043 Experiment::new_uid_node (uint64_t uid
, uint64_t val
)
5045 #define NCHUNKSTEP 1024
5046 if (nnodes
>= nchunks
* CHUNKSZ
)
5048 // Reallocate Node chunk array
5049 UIDnode
** old_chunks
= chunks
;
5050 chunks
= new UIDnode
*[nchunks
+ NCHUNKSTEP
];
5052 memcpy (chunks
, old_chunks
, nchunks
* sizeof (UIDnode
*));
5053 nchunks
+= NCHUNKSTEP
;
5054 delete[] old_chunks
;
5055 // Clean future pointers
5056 memset (&chunks
[nchunks
- NCHUNKSTEP
], 0, NCHUNKSTEP
* sizeof (UIDnode
*));
5059 if (NULL
== chunks
[nnodes
/ CHUNKSZ
]) // Allocate new chunk for nodes.
5060 chunks
[nnodes
/ CHUNKSZ
] = new UIDnode
[CHUNKSZ
];
5061 UIDnode
*node
= &chunks
[nnodes
/ CHUNKSZ
][nnodes
% CHUNKSZ
];
5069 Experiment::UIDnode
*
5070 Experiment::get_uid_node (uint64_t uid
, uint64_t val
)
5072 int hash
= (((int) uid
) >> 4) & (HTableSize
- 1);
5073 if (uid
!= (uint64_t) 0)
5075 UIDnode
*node
= uidHTable
[hash
];
5076 if (node
&& node
->uid
== uid
)
5079 UIDnode
*node
= new_uid_node (uid
, val
);
5080 if (uid
!= (uint64_t) 0)
5082 uidHTable
[hash
] = node
;
5083 uidnodes
->append (node
);
5088 Experiment::UIDnode
*
5089 Experiment::get_uid_node (uint64_t uid
)
5091 if (uid
== (uint64_t) 0)
5093 int hash
= (((int) uid
) >> 4) & (HTableSize
- 1);
5094 UIDnode
*node
= uidHTable
[hash
];
5095 if (node
&& node
->uid
== uid
)
5097 node
= new_uid_node (uid
, (uint64_t) 0);
5102 Experiment::UIDnode
*
5103 Experiment::find_uid_node (uint64_t uid
)
5105 int hash
= (((int) uid
) >> 4) & (HTableSize
- 1);
5106 UIDnode
*node
= uidHTable
[hash
];
5107 if (node
&& node
->uid
== uid
)
5110 int rt
= uidnodes
->size () - 1;
5113 int md
= (lt
+ rt
) / 2;
5114 node
= uidnodes
->fetch (md
);
5115 if (node
->uid
< uid
)
5117 else if (node
->uid
> uid
)
5121 uidHTable
[hash
] = node
;
5129 Experiment::frUidCmp (const void *a
, const void *b
)
5131 RawFramePacket
*fp1
= *(RawFramePacket
**) a
;
5132 RawFramePacket
*fp2
= *(RawFramePacket
**) b
;
5133 if (fp1
->uid
== fp2
->uid
)
5135 return fp1
->uid
< fp2
->uid
? -1 : 1;
5138 Experiment::RawFramePacket
*
5139 Experiment::find_frame_packet (uint64_t uid
)
5142 int rt
= frmpckts
->size () - 1;
5145 int md
= (lt
+ rt
) / 2;
5146 RawFramePacket
*fp
= frmpckts
->fetch (md
);
5149 else if (fp
->uid
> uid
)
5158 #define FRINFO_CACHEOPT_SIZE_LIMIT 4000000
5159 #define FRINFO_PIPELINE_SIZE_LIMIT 500000
5160 #define FRINFO_PIPELINE_NUM_STAGES 3
5162 // Pipelined execution of resolve_frame_info() and add_stack().
5163 // Since this is the largest time consuming part of loading an experiment (especially
5164 // so for large java experiments) - executing this part as a 3 stage pipeline can
5165 // give significant performance gain - and this concept can be aggressively applied
5166 // to enhance the gain further in future. The three stages are:
5167 // Phase 1: resolve_frame_info()
5168 // Phase 2: first part of add_stack() where the native stack is built
5169 // Phase 3: second part og add_stack() where the java stack is built
5170 // Phase 4: insert the native and java stacks into the stack map
5171 // The main thread operates in the first Phase and the other stages are
5172 // operated by a ssplib sequential queue - The threads working on the queues run concurrently
5173 // with each other and with the main thread. But within a particular queue, jobs are
5174 // executed sequentially
5177 // This is the second phase of the pipeline of resolve_frame_info and add_stack
5178 // It works on a chunk of iterations (size CSTCTX_CHUNK_SZ) and invokes add_stack()
5179 // for each one of them
5182 Experiment::resolve_frame_info (DataDescriptor
*dDscr
)
5184 if (!resolveFrameInfo
)
5188 dDscr
->setResolveFrInfoDone ();
5191 int propID
= dbeSession
->getPropIdByName (NTXT ("TSTAMP"));
5192 Data
*dataTStamp
= dDscr
->getData (propID
);
5193 if (dataTStamp
== NULL
)
5196 propID
= dbeSession
->getPropIdByName (NTXT ("FRINFO"));
5197 Data
*dataFrinfo
= dDscr
->getData (propID
);
5199 propID
= dbeSession
->getPropIdByName (NTXT ("THRID"));
5200 Data
*dataThrId
= dDscr
->getData (propID
);
5202 // We can get frame info either by FRINFO or by [THRID,STKIDX]
5203 if (dataFrinfo
== NULL
)
5206 char *propName
= NTXT ("MSTACK");
5207 propID
= dbeSession
->getPropIdByName (propName
);
5208 PropDescr
*prMStack
= new PropDescr (propID
, propName
);
5209 prMStack
->uname
= dbe_strdup (GTXT ("Machine Call Stack"));
5210 prMStack
->vtype
= TYPE_OBJ
;
5211 dDscr
->addProperty (prMStack
);
5213 propName
= NTXT ("USTACK");
5214 propID
= dbeSession
->getPropIdByName (propName
);
5215 PropDescr
*prUStack
= new PropDescr (propID
, propName
);
5216 prUStack
->uname
= dbe_strdup (GTXT ("User Call Stack"));
5217 prUStack
->vtype
= TYPE_OBJ
;
5218 dDscr
->addProperty (prUStack
);
5220 propName
= NTXT ("XSTACK");
5221 propID
= dbeSession
->getPropIdByName (propName
);
5222 PropDescr
*prXStack
= new PropDescr (propID
, propName
);
5223 prXStack
->uname
= dbe_strdup (GTXT ("Expert Call Stack"));
5224 prXStack
->vtype
= TYPE_OBJ
;
5225 dDscr
->addProperty (prXStack
);
5227 propName
= NTXT ("HSTACK");
5228 propID
= dbeSession
->getPropIdByName (propName
);
5229 PropDescr
*prHStack
= new PropDescr (propID
, propName
);
5230 prHStack
->uname
= dbe_strdup (GTXT ("ShowHide Call Stack"));
5231 prHStack
->vtype
= TYPE_OBJ
;
5232 dDscr
->addProperty (prHStack
);
5236 propName
= NTXT ("JTHREAD");
5237 propID
= dbeSession
->getPropIdByName (propName
);
5238 PropDescr
*prJThread
= new PropDescr (propID
, propName
);
5239 prJThread
->uname
= dbe_strdup (GTXT ("Java Thread"));
5240 prJThread
->vtype
= TYPE_OBJ
;
5241 dDscr
->addProperty (prJThread
);
5246 PropDescr
*prop
= new PropDescr (PROP_OMPSTATE
, NTXT ("OMPSTATE"));
5247 prop
->uname
= dbe_strdup (GTXT ("OpenMP state"));
5248 prop
->vtype
= TYPE_UINT32
;
5249 char * stateNames
[OMP_LAST_STATE
] = OMP_THR_STATE_STRINGS
;
5250 char * stateUNames
[OMP_LAST_STATE
] = OMP_THR_STATE_USTRINGS
;
5251 for (int ii
= 0; ii
< OMP_LAST_STATE
; ii
++)
5252 prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
5253 dDscr
->addProperty (prop
);
5255 // add PROP_CPRID to profiling data (not same as omptrace's PROP_CPRID)
5256 prop
= dDscr
->getProp (PROP_CPRID
);
5259 VType_type type
= prop
->vtype
;
5260 assert (type
== TYPE_OBJ
); //see 7040526
5262 prop
= new PropDescr (PROP_CPRID
, NTXT ("CPRID")); //profiling PROP_CPRID
5263 prop
->uname
= dbe_strdup (GTXT ("OpenMP parallel region"));
5264 prop
->vtype
= TYPE_OBJ
;
5265 dDscr
->addProperty (prop
);
5267 // add PROP_TSKID to profiling data (not same as omptrace's PROP_TSKID)
5268 prop
= dDscr
->getProp (PROP_TSKID
);
5271 VType_type type
= prop
->vtype
;
5272 assert (type
== TYPE_OBJ
); //see 7040526
5274 prop
= new PropDescr (PROP_TSKID
, NTXT ("TSKID")); //profiling PROP_TSKID
5275 prop
->uname
= dbe_strdup (GTXT ("OpenMP task"));
5276 prop
->vtype
= TYPE_OBJ
;
5277 dDscr
->addProperty (prop
);
5279 char *progress_bar_msg
= dbe_sprintf (NTXT ("%s %s: %s"), NTXT (" "),
5280 GTXT ("Processing CallStack Data"),
5281 get_basename (expt_name
));
5282 int progress_bar_percent
= -1;
5283 long deltaReport
= 5000;
5284 long nextReport
= 0;
5286 long size
= dDscr
->getSize ();
5287 // bool resolve_frinfo_pipelined = size > FRINFO_PIPELINE_SIZE_LIMIT && !ompavail;
5288 bool resolve_frinfo_pipelined
= false;
5290 Map
<uint64_t, uint64_t> *nodeCache
= NULL
;
5291 Map
<uint64_t, uint64_t> *frameInfoCache
= NULL
;
5292 if (size
> FRINFO_CACHEOPT_SIZE_LIMIT
&& dversion
== NULL
)
5294 frameInfoCache
= new CacheMap
<uint64_t, uint64_t>;
5295 nodeCache
= new CacheMap
<uint64_t, uint64_t>;
5298 pushCnt
= popCnt
= pushCnt3
= popCnt3
= 0;
5301 FramePacket
*fp
= NULL
;
5302 // DbeThreadPool * threadPool = new DbeThreadPool(5);
5303 fp
= new FramePacket
;
5304 fp
->stack
= new Vector
<Vaddr
>;
5305 fp
->jstack
= new Vector
<Vaddr
>;
5306 fp
->ompstack
= new Vector
<Vaddr
>;
5310 // piggyback on post-processing to calculate exp->last_event
5311 const hrtime_t _exp_start_time
= getStartTime (); // wall clock time
5312 hrtime_t exp_duration
= getLastEvent () == ZERO_TIME
? 0
5313 : getLastEvent () - _exp_start_time
; // zero-based
5318 for (long i
= 0; i
< size
; i
++)
5320 if (i
== nextReport
)
5322 int percent
= (int) (i
* 100 / size
);
5323 if (percent
> progress_bar_percent
)
5325 progress_bar_percent
+= 10;
5326 theApplication
->set_progress (percent
, progress_bar_msg
);
5328 nextReport
+= deltaReport
;
5331 uint32_t thrid
= (uint32_t) dataThrId
->fetchInt (i
);
5332 hrtime_t tstamp
= (hrtime_t
) dataTStamp
->fetchLong (i
);
5334 // piggyback on post-processing to calculate exp->last_event
5336 hrtime_t relative_timestamp
= tstamp
- _exp_start_time
;
5337 if (exp_duration
< relative_timestamp
)
5338 exp_duration
= relative_timestamp
;
5340 uint64_t frinfo
= (uint64_t) dataFrinfo
->fetchLong (i
);
5342 RawFramePacket
*rfp
= NULL
;
5345 // CacheMap does not work with NULL key
5346 if (frameInfoCache
!= NULL
)
5347 rfp
= (RawFramePacket
*) frameInfoCache
->get (frinfo
);
5351 rfp
= find_frame_packet (frinfo
);
5354 if (frameInfoCache
!= NULL
)
5355 frameInfoCache
->put (frinfo
, (uint64_t) rfp
);
5362 // Process OpenMP properties
5365 fp
->omp_state
= rfp
? rfp
->omp_state
: 0;
5366 dDscr
->setValue (PROP_OMPSTATE
, i
, fp
->omp_state
);
5368 fp
->omp_cprid
= mapPRid
->get (thrid
, tstamp
, mapPRid
->REL_EQLE
);
5369 void *omp_preg
= mapPReg
->get (thrid
, tstamp
, mapPReg
->REL_EQLE
);
5372 char *idxname
= NTXT ("OMP_preg");
5373 int idxtype
= dbeSession
->findIndexSpaceByName (idxname
);
5376 Histable
*preg0
= dbeSession
->findObjectById (Histable::INDEXOBJ
, idxtype
, (int64_t) 0);
5379 Vector
<Histable
*> pregs
;
5380 pregs
.append (preg0
);
5381 omp_preg
= cstack
->add_stack (&pregs
);
5382 mapPReg
->put (thrid
, tstamp
, omp_preg
);
5386 dDscr
->setObjValue (PROP_CPRID
, i
, omp_preg
); //profiling PROP_CPRID
5387 void *omp_task
= mapTask
->get (thrid
, tstamp
, mapTask
->REL_EQLE
);
5390 char *idxname
= NTXT ("OMP_task");
5391 int idxtype
= dbeSession
->findIndexSpaceByName (idxname
);
5394 Histable
*task0
= dbeSession
->findObjectById (Histable::INDEXOBJ
, idxtype
, (int64_t) 0);
5397 Vector
<Histable
*> tasks
;
5398 tasks
.append (task0
);
5399 omp_task
= cstack
->add_stack (&tasks
);
5400 mapTask
->put (thrid
, tstamp
, omp_task
);
5404 dDscr
->setObjValue (PROP_TSKID
, i
, omp_task
); //profiling PROP_TSKID
5412 // Construct the native stack
5413 fp
->stack
->reset ();
5414 Vaddr leafpc
= dDscr
->getULongValue (PROP_LEAFPC
, i
);
5416 fp
->stack
->append (leafpc
);
5417 UIDnode
*node
= rfp
? rfp
->uidn
: NULL
;
5420 if (node
->next
== node
)
5421 // this node contains link_uid
5422 node
= find_uid_node (node
->uid
);
5425 fp
->stack
->append (node
->val
);
5430 int last
= fp
->stack
->size () - 1;
5433 switch (fp
->stack
->fetch (last
))
5435 case SP_TRUNC_STACK_MARKER
:
5436 fp
->truncated
= (Vaddr
) SP_TRUNC_STACK_MARKER
;
5437 fp
->stack
->remove (last
);
5439 case SP_FAILED_UNWIND_MARKER
:
5440 fp
->truncated
= (Vaddr
) SP_FAILED_UNWIND_MARKER
;
5441 fp
->stack
->remove (last
);
5446 // Construct the Java stack
5447 fp
->jstack
->reset ();
5448 node
= rfp
? rfp
->uidj
: NULL
;
5451 if (node
->next
== node
)
5453 // this node contains link_uid
5457 // CacheMap does not work with NULL key
5458 if (nodeCache
!= NULL
)
5459 n
= (UIDnode
*) nodeCache
->get (node
->uid
);
5463 n
= find_uid_node (node
->uid
);
5466 if (nodeCache
!= NULL
)
5467 nodeCache
->put (node
->uid
, (uint64_t) n
);
5474 fp
->jstack
->append (node
->val
);
5478 fp
->jtruncated
= false;
5479 last
= fp
->jstack
->size () - 1;
5480 if (last
>= 1 && fp
->jstack
->fetch (last
) == SP_TRUNC_STACK_MARKER
)
5482 fp
->jtruncated
= true;
5483 fp
->jstack
->remove (last
);
5484 fp
->jstack
->remove (last
- 1);
5487 // Construct the OpenMP stack
5490 fp
->ompstack
->reset ();
5491 if (rfp
&& rfp
->omp_uid
)
5494 fp
->ompstack
->append (leafpc
);
5495 node
= rfp
->omp_uid
;
5498 if (node
->next
== node
)
5499 // this node contains link_uid
5500 node
= find_uid_node (node
->uid
);
5503 fp
->ompstack
->append (node
->val
);
5507 fp
->omptruncated
= false;
5508 last
= fp
->ompstack
->size () - 1;
5511 switch (fp
->ompstack
->fetch (last
))
5513 case SP_TRUNC_STACK_MARKER
:
5514 fp
->omptruncated
= (Vaddr
) SP_TRUNC_STACK_MARKER
;
5515 fp
->ompstack
->remove (last
);
5517 case SP_FAILED_UNWIND_MARKER
:
5518 fp
->omptruncated
= (Vaddr
) SP_FAILED_UNWIND_MARKER
;
5519 fp
->ompstack
->remove (last
);
5525 cstack
->add_stack (dDscr
, i
, fp
, NULL
);
5528 // piggyback on post-processing to calculate exp->last_event
5530 hrtime_t exp_end_time
= _exp_start_time
+ exp_duration
;
5531 update_last_event (exp_end_time
);
5538 GTXT ("*** Warning: %d frameinfo packets are missing from total of %d when resolving %s."),
5539 missed_fi
, total_fi
, dDscr
->getName ());
5540 warnq
->append (new Emsg (CMSG_WARN
, sb
));
5543 // threadPool->wait_group();
5544 // delete threadPool;
5545 theApplication
->set_progress (0, NTXT (""));
5546 free (progress_bar_msg
);
5547 if (!resolve_frinfo_pipelined
&& fp
!= NULL
)
5549 delete fp
->ompstack
;
5554 delete frameInfoCache
;
5555 frameInfoCache
= NULL
;
5561 Experiment::post_process ()
5563 // update non_paused_time after final update to "last_event"
5564 if (resume_ts
!= MAX_TIME
&& last_event
)
5566 hrtime_t ts
= last_event
- exp_start_time
;
5567 hrtime_t delta
= ts
- resume_ts
;
5568 non_paused_time
+= delta
;
5569 resume_ts
= MAX_TIME
; // collection is paused
5572 // GC: prune events outside of experiment duration, calculate GC duration, update indices
5575 gc_duration
= ZERO_TIME
;
5576 if (gcevents
!= NULL
)
5578 // delete events that finish before exp_start_time or start after last_event
5579 for (int ii
= 0; ii
< gcevents
->size ();)
5581 gcevent
= gcevents
->fetch (ii
);
5582 if (gcevent
->end
- exp_start_time
< 0
5583 || last_event
- gcevent
->start
< 0)
5584 delete gcevents
->remove (ii
);
5589 Vec_loop (GCEvent
*, gcevents
, index
, gcevent
)
5591 gcevent
->id
= index
+ 1; // renumber to account for any deleted events
5592 if (gcevent
->start
- exp_start_time
< 0 || gcevent
->start
== ZERO_TIME
)
5593 // truncate events that start before experiment start
5594 gcevent
->start
= exp_start_time
;
5595 if (last_event
- gcevent
->end
< 0)
5596 // truncate events that end after experiment end
5597 gcevent
->end
= last_event
;
5598 gc_duration
+= gcevent
->end
- gcevent
->start
;
5602 Experiment::Exp_status
5603 Experiment::find_expdir (char *path
)
5605 // This function checks that the experiment directory
5606 // is of the proper form, and accessible
5610 expt_name
= dbe_strdup (path
);
5612 // Check that the name ends in .er
5613 size_t i
= strlen (path
);
5614 if (i
> 0 && path
[i
- 1] == '/')
5617 if (i
< 4 || strcmp (&path
[i
- 3], NTXT (".er")) != 0)
5619 Emsg
*m
= new Emsg (CMSG_FATAL
,
5620 GTXT ("*** Error: not a valid experiment name"));
5626 // Check if new directory structure (i.e., no pointer file)
5627 if (dbe_stat (path
, &sbuf
))
5629 Emsg
*m
= new Emsg (CMSG_FATAL
, GTXT ("*** Error: experiment not found"));
5634 if (S_ISDIR (sbuf
.st_mode
) == 0)
5636 // ignore pointer-file experiments
5637 Emsg
*m
= new Emsg (CMSG_FATAL
,
5638 GTXT ("*** Error: experiment was recorded with an earlier version, and can not be read"));
5648 Experiment::purge ()
5650 // This routine will purge all of the caches of releasable storage.
5651 for (int i
= 0; i
< dataDscrs
->size (); ++i
)
5653 DataDescriptor
*dataDscr
= dataDscrs
->fetch (i
);
5654 if (dataDscr
== NULL
)
5659 delete cstackShowHide
;
5660 cstack
= CallStack::getInstance (this);
5661 cstackShowHide
= CallStack::getInstance (this);
5665 Experiment::resetShowHideStack ()
5667 delete cstackShowHide
;
5668 cstackShowHide
= CallStack::getInstance (this);
5671 #define GET_INT_VAL(v, s, len) \
5672 for (v = len = 0; isdigit(*s); s++, len++) { v = v * 10 + (*s -'0'); }
5675 dir_name_cmp (const void *a
, const void *b
)
5677 char *s1
= *((char **) a
);
5678 char *s2
= *((char **) b
);
5681 if (isdigit (*s1
) && isdigit (*s2
))
5683 int v1
, v2
, len1
, len2
;
5684 GET_INT_VAL (v1
, s1
, len1
);
5685 GET_INT_VAL (v2
, s2
, len2
);
5701 Experiment::get_descendants_names ()
5703 char *dir_name
= get_expt_name ();
5704 if (dir_name
== NULL
)
5706 DIR *exp_dir
= opendir (dir_name
);
5707 if (exp_dir
== NULL
)
5709 Vector
<char*> *exp_names
= new Vector
<char*>();
5710 for (struct dirent
*entry
= readdir (exp_dir
); entry
;
5711 entry
= readdir (exp_dir
))
5713 if (entry
->d_name
[0] == '_' || strncmp (entry
->d_name
, "M_r", 3) == 0)
5715 char *dpath
= dbe_sprintf (NTXT ("%s/%s"), dir_name
, entry
->d_name
);
5717 if (dbe_stat (dpath
, &sbuf
) == 0 && S_ISDIR (sbuf
.st_mode
))
5718 exp_names
->append (dpath
);
5724 if (exp_names
->size () == 0)
5729 exp_names
->sort (dir_name_cmp
);
5734 Experiment::create_dir (char *dname
)
5736 if (mkdir (dname
, S_IRWXU
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
) == 0)
5741 if (dbe_stat (dname
, &sbuf
) != 0 || S_ISDIR (sbuf
.st_mode
) == 0)
5743 char *buf
= dbe_sprintf (GTXT ("Unable to create directory `%s'\n"),
5745 errorq
->append (new Emsg (CMSG_ERROR
, buf
));
5753 Experiment::get_arch_name ()
5755 if (arch_name
== NULL
)
5757 // Determine the master experiment directory.
5758 // omazur: should do it in a less hacky way. XXXX
5759 char *ptr
= strstr_r (expt_name
, DESCENDANT_EXPT_KEY
);
5760 ptr
= ptr
? ptr
+ 3 : expt_name
+ strlen (expt_name
);
5761 arch_name
= dbe_sprintf (NTXT ("%.*s/%s"), (int) (ptr
- expt_name
),
5762 expt_name
, SP_ARCHIVES_DIR
);
5768 Experiment::get_fndr_arch_name ()
5770 if (fndr_arch_name
== NULL
)
5771 // Determine the founder experiment directory.
5772 fndr_arch_name
= dbe_strdup (get_arch_name ());
5773 return fndr_arch_name
;
5778 HASH_NAME_LEN
= 11 // (64 / 6 + 1) = 11
5782 get_hash_string (char buf
[HASH_NAME_LEN
+ 1], uint64_t hash
)
5784 static const char *har
=
5785 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
5786 for (int i
= 0; i
< HASH_NAME_LEN
; i
++)
5788 buf
[i
] = har
[hash
& 0x3f];
5791 buf
[HASH_NAME_LEN
] = 0;
5796 Experiment::getNameInArchive (const char *fname
, bool archiveFile
)
5798 char *aname
= get_archived_name (fname
, archiveFile
);
5799 char *ret
= dbe_sprintf (NTXT ("%s/%s"), get_arch_name (), aname
);
5804 #define MAX_ARCHIVE_FILENAME_LEN (256 - HASH_NAME_LEN - 2)
5807 Experiment::get_archived_name (const char *fname
, bool archiveFile
)
5809 char *bname
= get_basename (fname
);
5812 char dirnameHash
[HASH_NAME_LEN
+ 1];
5813 // Treat "a.out" and "./a.out" equally
5814 uint64_t hash
= bname
!= fname
? crc64 (fname
, bname
- fname
)
5815 : crc64 (NTXT ("./"), 2);
5816 get_hash_string (dirnameHash
, hash
);
5819 long bname_len
= dbe_sstrlen (bname
);
5820 if (bname_len
> MAX_ARCHIVE_FILENAME_LEN
)
5822 char basenameHash
[HASH_NAME_LEN
+ 1];
5823 hash
= crc64 (bname
, bname_len
);
5824 get_hash_string (basenameHash
, hash
);
5825 ret
= dbe_sprintf ("%.*s%c%s_%s",
5826 MAX_ARCHIVE_FILENAME_LEN
- HASH_NAME_LEN
- 1,
5827 bname
, archiveFile
? '.' : '_',
5828 dirnameHash
, basenameHash
);
5831 ret
= dbe_sprintf ("%s%c%s", bname
, archiveFile
? '.' : '_', dirnameHash
);
5836 Experiment::checkFileInArchive (const char *fname
, bool archiveFile
)
5840 char *aname
= get_archived_name (fname
, archiveFile
);
5841 DbeFile
*df
= archiveMap
->get (aname
);
5844 return xstrdup (df
->get_location ());
5848 return founder_exp
->checkFileInArchive (fname
, archiveFile
);
5856 SegMemCmp (const void *a
, const void *b
)
5858 SegMem
*item1
= *((SegMem
**) a
);
5859 SegMem
*item2
= *((SegMem
**) b
);
5860 return item1
->unload_time
> item2
->unload_time
? 1 :
5861 item1
->unload_time
== item2
->unload_time
? 0 : -1;
5865 Experiment::update_ts_in_maps (Vaddr addr
, hrtime_t ts
)
5867 Vector
<void *> *segMems
= maps
->values ();
5868 if (segMems
&& !segMems
->is_sorted ())
5870 Dprintf (DEBUG_MAPS
, NTXT ("update_ts_in_maps: segMems.size=%lld\n"), (long long) segMems
->size ());
5871 segMems
->sort (SegMemCmp
);
5873 for (int i
= 0, sz
= segMems
? segMems
->size () : 0; i
< sz
; i
++)
5875 SegMem
*sm
= (SegMem
*) segMems
->fetch (i
);
5876 if (ts
< sm
->unload_time
)
5880 sm
= (SegMem
*) segMems
->fetch (i
);
5881 if ((addr
>= sm
->base
) && (addr
< sm
->base
+ sm
->size
))
5883 Dprintf (DEBUG_MAPS
,
5884 "update_ts_in_maps: old:%u.%09u -> %u.%09u addr=0x%08llx size=%lld\n",
5885 (unsigned) (sm
->load_time
/ NANOSEC
),
5886 (unsigned) (sm
->load_time
% NANOSEC
),
5887 (unsigned) (ts
/ NANOSEC
), (unsigned) (ts
% NANOSEC
),
5888 (unsigned long long) sm
->base
, (long long) sm
->size
);
5889 maps
->remove (sm
->base
, sm
->load_time
);
5891 maps
->insert (sm
->base
, ts
, sm
);
5897 Dprintf (DEBUG_MAPS
, "update_ts_in_maps: NOT FOUND %u.%09u addr=0x%08llx\n",
5898 (unsigned) (ts
/ NANOSEC
), (unsigned) (ts
% NANOSEC
),
5899 (unsigned long long) addr
);
5904 Experiment::map_Vaddr_to_PC (Vaddr addr
, hrtime_t ts
)
5906 // Look up in the hash table first
5907 int hash
= (((int) addr
) >> 8) & (HTableSize
- 1);
5908 SegMem
*si
= smemHTable
[hash
];
5909 if (si
== NULL
|| addr
< si
->base
|| addr
>= si
->base
+ si
->size
5910 || ts
< si
->load_time
|| ts
>= si
->unload_time
)
5912 // Not in the hash table
5913 si
= (SegMem
*) maps
->locate (addr
, ts
);
5914 if (si
== NULL
|| addr
< si
->base
|| addr
>= si
->base
+ si
->size
5915 || ts
< si
->load_time
|| ts
>= si
->unload_time
)
5917 si
= update_ts_in_maps (addr
, ts
);
5919 return dbeSession
->get_Unknown_Function ()->find_dbeinstr (PCInvlFlag
, addr
);
5921 smemHTable
[hash
] = si
;
5924 // Calculate the file offset of 'addr'
5925 uint64_t f_offset
= si
->get_file_offset () + (addr
- si
->base
);
5928 if (si
->obj
->get_type () == Histable::LOADOBJECT
)
5930 LoadObject
*lo
= (LoadObject
*) si
->obj
;
5931 lo
->sync_read_stabs ();
5932 instr
= lo
->find_dbeinstr (f_offset
);
5936 int hash2
= ((((int) addr
) & 0xFFFC00) | (((int) f_offset
) >> 2))
5938 instr
= instHTable
[hash2
];
5939 if (instr
== NULL
|| instr
->func
!= si
->obj
|| instr
->addr
!= f_offset
)
5941 // Not in the hash table
5942 Function
*fp
= (Function
*) si
->obj
;
5943 instr
= fp
->find_dbeinstr (0, f_offset
);
5944 instHTable
[hash2
] = instr
;
5947 if (!instr
->func
->isUsed
)
5949 instr
->func
->isUsed
= true;
5950 instr
->func
->module
->isUsed
= true;
5951 instr
->func
->module
->loadobject
->isUsed
= true;
5957 Experiment::map_event_to_Sample (hrtime_t ts
)
5962 // Check if the last used sample is the right one,
5963 // if not then find it.
5964 if (sample_last_used
&& ts
>= sample_last_used
->start_time
5965 && ts
<= sample_last_used
->end_time
)
5966 return sample_last_used
;
5968 Vec_loop (Sample
*, samples
, index
, sample
)
5970 if ((ts
>= sample
->start_time
) &&
5971 (ts
<= sample
->end_time
))
5973 sample_last_used
= sample
;
5977 return (Sample
*) NULL
;
5981 Experiment::map_event_to_GCEvent (hrtime_t ts
)
5986 // Check if the last used sample is the right one,
5987 // if not then find it.
5988 if (gcevent_last_used
&& ts
>= gcevent_last_used
->start
5989 && ts
<= gcevent_last_used
->end
)
5990 return gcevent_last_used
;
5991 Vec_loop (GCEvent
*, gcevents
, index
, gcevent
)
5993 if ((ts
>= gcevent
->start
) &&
5994 (ts
<= gcevent
->end
))
5996 gcevent_last_used
= gcevent
;
6000 return (GCEvent
*) NULL
;
6004 Experiment::map_jmid_to_PC (Vaddr mid
, int bci
, hrtime_t ts
)
6006 if (mid
== 0 || jmaps
== NULL
)
6007 // special case: no Java stack was recorded, bci - error code
6008 return dbeSession
->get_JUnknown_Function ()->find_dbeinstr (0, bci
);
6010 JMethod
*jmthd
= jmidHTable
->get (mid
);
6013 jmthd
= (JMethod
*) jmaps
->locate_exact_match (mid
, ts
);
6015 jmidHTable
->put (mid
, jmthd
);
6017 if (jmthd
== NULL
|| jmthd
->get_type () != Histable::FUNCTION
)
6018 return dbeSession
->get_JUnknown_Function ()->find_dbeinstr (0, (uint64_t) mid
);
6019 return jmthd
->find_dbeinstr (0, bci
);
6023 Experiment::fetch_comments ()
6025 return commentq
->fetch ();
6029 Experiment::fetch_runlogq ()
6031 return runlogq
->fetch ();
6035 Experiment::fetch_errors ()
6037 return errorq
->fetch ();
6041 Experiment::fetch_warnings ()
6043 return warnq
->fetch ();
6047 Experiment::fetch_notes ()
6049 return notesq
->fetch ();
6053 Experiment::fetch_ifreq ()
6055 return ifreqq
->fetch ();
6059 Experiment::fetch_pprocq ()
6061 return pprocq
->fetch ();
6065 Experiment::read_dyntext_file ()
6067 dyntext_name
= dbe_sprintf ("%s/%s", expt_name
, SP_DYNTEXT_FILE
);
6068 Data_window
*dwin
= new Data_window (dyntext_name
);
6069 if (dwin
->not_opened ())
6074 dwin
->need_swap_endian
= need_swap_endian
;
6076 Function
*fp
= NULL
;
6077 char *progress_msg
= NULL
; // Message for the progress bar
6078 for (int64_t offset
= 0;;)
6080 DT_common
*cpckt
= (DT_common
*) dwin
->bind (offset
, sizeof (DT_common
));
6083 size_t cpcktsize
= dwin
->decode (cpckt
->size
);
6084 cpckt
= (DT_common
*) dwin
->bind (offset
, cpcktsize
);
6087 switch (dwin
->decode (cpckt
->type
))
6091 DT_header
*hdr
= (DT_header
*) cpckt
;
6092 hrtime_t ts
= dwin
->decode (hdr
->time
) + exp_start_time
;
6093 SegMem
*si
= (SegMem
*) maps
->locate (dwin
->decode (hdr
->vaddr
), ts
);
6094 fp
= si
? (Function
*) si
->obj
: NULL
;
6095 if (fp
&& (fp
->get_type () != Histable::FUNCTION
6096 || !(fp
->flags
& FUNC_FLAG_DYNAMIC
)))
6103 fp
->img_fname
= dyntext_name
;
6104 fp
->img_offset
= offset
+ sizeof (DT_common
);
6105 if ((platform
!= Intel
) && (platform
!= Amd64
))
6107 // Find out 'save' instruction address for SPARC
6108 char *ptr
= ((char*) cpckt
) + sizeof (DT_common
);
6109 size_t img_size
= cpcktsize
- sizeof (DT_common
);
6110 for (size_t i
= 0; i
< img_size
; i
+= 4)
6111 if (ptr
[i
] == (char) 0x9d && ptr
[i
+ 1] == (char) 0xe3)
6122 char *srcname
= dbe_strndup (((char*) cpckt
) + sizeof (DT_common
),
6123 cpcktsize
- sizeof (DT_common
));
6124 LoadObject
*ds
= fp
->module
? fp
->module
->loadobject
: NULL
;
6125 assert (ds
!= NULL
);
6126 Module
*mod
= dbeSession
->createModule (ds
, NULL
);
6127 mod
->set_file_name (srcname
);
6131 // It's most likely (unknown). Remove fp from it.
6132 long idx
= fp
->module
->functions
->find (fp
);
6134 fp
->module
->functions
->remove (idx
);
6137 mod
->functions
->append (fp
);
6143 DT_lineno
*ltab
= (DT_lineno
*) ((char*) cpckt
+ sizeof (DT_common
));
6144 size_t sz
= (cpcktsize
- sizeof (DT_common
)) / sizeof (DT_lineno
);
6147 // Take care of the progress bar
6148 static int percent
= 0;
6149 static long deltaReport
= sz
/ 100; // 1000;
6150 static long nextReport
= 0;
6151 static long progress_count
= 0;
6152 fp
->pushSrcFile (fp
->getDefSrc (), 0);
6153 for (size_t i
= 0; i
< sz
; i
++)
6155 int lineno
= dwin
->decode (ltab
[i
].lineno
);
6156 if (fp
->usrfunc
!= NULL
)
6158 // Update progress bar
6159 if (dbeSession
->is_interactive ())
6161 if (progress_count
== nextReport
)
6166 if (NULL
== progress_msg
)
6168 progress_msg
= dbe_sprintf (GTXT ("Processing Dynamic Text: %s"),
6169 get_basename (expt_name
));
6171 theApplication
->set_progress (percent
, progress_msg
);
6172 nextReport
+= deltaReport
;
6177 DbeLine
*dbeline
= fp
->usrfunc
->mapPCtoLine (lineno
, NULL
);
6178 lineno
= dbeline
!= NULL
? dbeline
->lineno
: -1;
6180 fp
->add_PC_info (dwin
->decode (ltab
[i
].offset
), lineno
);
6186 // skip unknown records
6189 offset
+= cpcktsize
;
6191 free (progress_msg
);
6197 Experiment::mapTagValue (Prop_type prop
, uint64_t value
)
6199 Vector
<Histable
*> *objs
= tagObjs
->fetch (prop
);
6201 int rt
= objs
->size () - 1;
6204 int md
= (lt
+ rt
) / 2;
6205 Other
*obj
= (Other
*) objs
->fetch (md
);
6206 if (obj
->value64
< value
)
6208 else if (obj
->value64
> value
)
6215 if (sparse_threads
&& (prop
== PROP_THRID
|| prop
== PROP_LWPID
))
6216 tag
= objs
->size () + 1; // "+ 1" related to 7038295
6218 tag
= (int) value
; // truncation; See 6788767
6220 Other
*obj
= new Other ();
6221 obj
->value64
= value
;
6223 if (lt
== objs
->size ())
6226 objs
->insert (lt
, obj
);
6228 // Update min and max tags
6229 if (prop
== PROP_LWPID
)
6231 if ((uint64_t) tag
< min_lwp
)
6232 min_lwp
= (uint64_t) tag
;
6233 if ((uint64_t) tag
> max_lwp
)
6234 max_lwp
= (uint64_t) tag
;
6237 else if (prop
== PROP_THRID
)
6239 if ((uint64_t) tag
< min_thread
)
6240 min_thread
= (uint64_t) tag
;
6241 if ((uint64_t) tag
> max_thread
)
6242 max_thread
= (uint64_t) tag
;
6245 else if (prop
== PROP_CPUID
)
6247 // On Solaris 8, we don't get CPU id -- don't change
6248 if (value
!= (uint64_t) - 1)
6249 {//YXXX is this related only to solaris 8?
6250 if ((uint64_t) tag
< min_cpu
)
6251 min_cpu
= (uint64_t) tag
;
6252 if ((uint64_t) tag
> max_cpu
)
6253 max_cpu
= (uint64_t) tag
;
6261 Experiment::getTagObjs (Prop_type prop
)
6263 return tagObjs
->fetch (prop
);
6267 Experiment::getTagObj (Prop_type prop
, uint32_t tag
)
6269 Vector
<Histable
*> *objs
= tagObjs
->fetch (prop
);
6272 for (int i
= 0; i
< objs
->size (); i
++)
6274 Other
*obj
= (Other
*) objs
->fetch (i
);
6275 if (obj
->tag
== tag
)
6282 Experiment::map_pckt_to_Jthread (uint32_t tid
, hrtime_t tstamp
)
6285 return JTHREAD_DEFAULT
;
6287 int rt
= jthreads_idx
->size () - 1;
6290 int md
= (lt
+ rt
) / 2;
6291 JThread
*jthread
= jthreads_idx
->fetch (md
);
6292 if (jthread
->tid
< tid
)
6294 else if (jthread
->tid
> tid
)
6298 for (; jthread
; jthread
= jthread
->next
)
6299 if (tstamp
>= jthread
->start
&& tstamp
< jthread
->end
)
6305 return JTHREAD_NONE
;
6309 Experiment::get_jthread (uint32_t tid
)
6312 return JTHREAD_DEFAULT
;
6314 int rt
= jthreads_idx
->size () - 1;
6317 int md
= (lt
+ rt
) / 2;
6318 JThread
*jthread
= jthreads_idx
->fetch (md
);
6319 if (jthread
->tid
< tid
)
6321 else if (jthread
->tid
> tid
)
6325 JThread
*jthread_first
= jthread
;
6326 while ((jthread
= jthread
->next
) != NULL
)
6327 if (!jthread
->is_system () &&
6328 jthread
->jthr_id
< jthread_first
->jthr_id
)
6329 jthread_first
= jthread
;
6330 return jthread_first
;
6334 return JTHREAD_NONE
;
6339 Experiment::newDataDescriptor (int data_id
, int flags
,
6340 DataDescriptor
*master_dDscr
)
6342 DataDescriptor
*dataDscr
= NULL
;
6343 if (data_id
>= 0 && data_id
< dataDscrs
->size ())
6345 dataDscr
= dataDscrs
->fetch (data_id
);
6346 if (dataDscr
!= NULL
)
6350 assert (data_id
>= 0 && data_id
< DATA_LAST
);
6351 const char *nm
= get_prof_data_type_name (data_id
);
6352 const char *uname
= get_prof_data_type_uname (data_id
);
6355 dataDscr
= new DataDescriptor (data_id
, nm
, uname
, master_dDscr
);
6357 dataDscr
= new DataDescriptor (data_id
, nm
, uname
, flags
);
6358 dataDscrs
->store (data_id
, dataDscr
);
6362 Vector
<DataDescriptor
*> *
6363 Experiment::getDataDescriptors ()
6365 Vector
<DataDescriptor
*> *result
= new Vector
<DataDescriptor
*>;
6366 for (int i
= 0; i
< dataDscrs
->size (); ++i
)
6369 dd
= get_raw_events (i
); // force data fetch
6371 result
->append (dd
);
6377 Experiment::getDataDescriptor (int data_id
)
6379 if (data_id
< 0 || data_id
>= dataDscrs
->size ())
6381 return dataDscrs
->fetch (data_id
);
6385 Experiment::newPacketDescriptor (int kind
, DataDescriptor
*dDscr
)
6387 PacketDescriptor
*pDscr
= new PacketDescriptor (dDscr
);
6388 pcktDscrs
->store (kind
, pDscr
);
6393 Experiment::getPacketDescriptor (int kind
)
6395 if (kind
< 0 || kind
>= pcktDscrs
->size ())
6397 return pcktDscrs
->fetch (kind
);
6401 Experiment::set_clock (int clk
)
6410 if (minclock
== 0 || minclock
> clk
)
6416 JThread::is_system ()
6418 if (group_name
== NULL
)
6420 return strcmp (group_name
, NTXT ("system")) == 0;
6424 Experiment::dump_stacks (FILE *outfile
)
6426 cstack
->print (outfile
);
6430 Experiment::dump_map (FILE *outfile
)
6434 fprintf (outfile
, GTXT ("Experiment %s\n"), get_expt_name ());
6435 fprintf (outfile
, GTXT ("Address Size (hex) Load time Unload time Checksum Name\n"));
6436 Vec_loop (SegMem
*, seg_items
, index
, s
)
6440 hr2timestruc (&load
, (s
->load_time
- exp_start_time
));
6441 if (load
.tv_nsec
< 0)
6444 load
.tv_nsec
+= NANOSEC
;
6446 if (s
->unload_time
== MAX_TIME
)
6452 hr2timestruc (&unload
, (s
->unload_time
- exp_start_time
));
6453 if (load
.tv_nsec
< 0)
6456 load
.tv_nsec
+= NANOSEC
;
6459 "0x%08llx %8lld (0x%08llx) %5lld.%09lld %5lld.%09lld \"%s\"\n",
6460 (long long) s
->base
, (long long) s
->size
, (long long) s
->size
,
6461 (long long) load
.tv_sec
, (long long) load
.tv_nsec
,
6462 (long long) unload
.tv_sec
, (long long) unload
.tv_nsec
,
6463 s
->obj
->get_name ());
6465 fprintf (outfile
, NTXT ("\n"));
6469 * Copy file to archive
6473 * @return 0 - success, 1 - error
6476 Experiment::copy_file_to_archive (const char *name
, const char *aname
, int hide_msg
)
6479 int fd_w
= ::open64 (aname
, O_WRONLY
| O_CREAT
| O_EXCL
, 0644);
6482 if (errno
== EEXIST
)
6484 fprintf (stderr
, GTXT ("gprofng-archive: unable to copy `%s': %s\n"),
6485 name
, STR (strerror (errno
)));
6489 if (dbe_stat_file (name
, NULL
) != 0)
6491 fprintf (stderr
, GTXT ("gprofng-archive: cannot access file `%s': %s\n"),
6492 name
, STR (strerror (errno
)));
6497 int fd_r
= ::open64 (name
, O_RDONLY
);
6500 fprintf (stderr
, GTXT ("gprofng-archive: unable to open `%s': %s\n"),
6501 name
, strerror (errno
));
6508 fprintf (stderr
, GTXT ("Copying `%s' to `%s'\n"), name
, aname
);
6509 bool do_unlink
= false;
6512 unsigned char buf
[65536];
6514 n
= (int) read (fd_r
, (void *) buf
, sizeof (buf
));
6517 n1
= (int) write (fd_w
, buf
, n
);
6520 fprintf (stderr
, GTXT ("gprofng-archive: unable to write %d bytes to `%s': %s\n"),
6521 n
, aname
, STR (strerror (errno
)));
6529 if (fstat64 (fd_r
, &s_buf
) == 0)
6531 struct utimbuf u_buf
;
6532 u_buf
.actime
= s_buf
.st_atime
;
6533 u_buf
.modtime
= s_buf
.st_mtime
;
6534 utime (aname
, &u_buf
);
6540 fprintf (stderr
, GTXT ("gprofng-archive: remove %s\n"), aname
);
6548 * Copy file to common archive
6550 * Calculate checksum
6551 * Generate file name to be created in common archive
6552 * Check if it is not in common archive yet
6553 * Copy file to the common archive directory if it is not there yet
6554 * Create symbolic link: "aname" -> "caname", where "caname" is the name in common archive
6555 * @param name - original file name
6556 * @param aname - file name in experiment archive
6557 * @param common_archive - common archive directory
6558 * @return 0 - success, 1 - error
6561 Experiment::copy_file_to_common_archive (const char *name
, const char *aname
,
6563 const char *common_archive
,
6566 if (!name
|| !aname
|| !common_archive
)
6569 fprintf (stderr
, GTXT ("gprofng-archive: Internal error: file name is NULL\n"));
6571 fprintf (stderr
, GTXT ("gprofng-archive: Internal error: file name in archive is NULL\n"));
6572 if (!common_archive
)
6573 fprintf (stderr
, GTXT ("gprofng-archive: Internal error: path to common archive is NULL\n"));
6576 // Check if file is already archived
6577 if (dbe_stat (aname
, NULL
) == 0)
6578 return 0; // File is already archived
6579 // Generate full path to common archive directory
6581 char *abs_aname
= NULL
;
6582 if ((common_archive
[0] != '/') || (aname
[0] != '/'))
6584 long size
= pathconf (NTXT ("."), _PC_PATH_MAX
);
6587 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: pathconf(\".\", _PC_PATH_MAX) failed\n"));
6590 char *buf
= (char *) xmalloc ((size_t) size
);
6591 char *ptr
= getcwd (buf
, (size_t) size
);
6594 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: cannot determine current directory\n"));
6598 if (common_archive
[0] != '/')
6599 cad
= dbe_sprintf (NTXT ("%s/%s"), ptr
, common_archive
);
6601 cad
= dbe_strdup (common_archive
);
6602 if (aname
[0] != '/')
6603 abs_aname
= dbe_sprintf (NTXT ("%s/%s"), ptr
, aname
);
6605 abs_aname
= dbe_strdup (aname
);
6610 cad
= dbe_strdup (common_archive
);
6611 abs_aname
= dbe_strdup (aname
);
6613 // Calculate checksum
6614 char * errmsg
= NULL
;
6615 uint32_t crcval
= get_cksum (name
, &errmsg
);
6622 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: %s\n"), errmsg
);
6627 GTXT ("gprofng-archive: Fatal error: get_cksum(%s) returned %d\n"),
6631 // Generate file name to be created in common archive
6632 char *fname
= get_basename (name
);
6633 char *abs_caname
= dbe_sprintf (NTXT ("%s/%u_%s"), cad
, crcval
, fname
);
6634 if (abs_caname
== NULL
)
6639 GTXT ("gprofng-archive: Fatal error: unable to allocate memory\n"));
6642 // Check if full name is not too long
6643 long len
= dbe_sstrlen (abs_caname
);
6644 long max
= pathconf (cad
, _PC_PATH_MAX
);
6645 if ((max
< 0) || (len
<= 0))
6647 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: pathconf(%s, _PC_PATH_MAX) failed\n"),
6656 // Try to truncate the name
6657 if ((len
- max
) <= dbe_sstrlen (fname
))
6659 // Yes, we can do it
6660 abs_caname
[max
- 1] = 0;
6662 fprintf (stderr
, GTXT ("gprofng-archive: file path is too long - truncated:%s\n"),
6666 // Check if file name is not too long
6667 char *cafname
= get_basename (abs_caname
);
6668 len
= dbe_sstrlen (cafname
);
6669 max
= pathconf (cad
, _PC_NAME_MAX
);
6670 if ((max
< 0) || (len
<= 0))
6672 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: pathconf(%s, _PC_NAME_MAX) failed\n"),
6681 // Try to truncate the name
6682 if ((len
- max
) <= dbe_sstrlen (fname
))
6684 // Yes, we can do it
6685 cafname
[max
- 1] = 0;
6687 fprintf (stderr
, GTXT ("gprofng-archive: file name is too long - truncated:%s\n"),
6691 // Copy file to the common archive directory if it is not there yet
6693 if (dbe_stat_file (abs_caname
, NULL
) != 0)
6695 // Use temporary file to avoid synchronization problems
6696 char *t
= dbe_sprintf ("%s/archive_%llx", cad
, (unsigned long long) gethrtime());
6698 // Copy file to temporary file
6699 res
= copy_file_to_archive (name
, t
, hide_msg
); // hide messages
6702 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: cannot copy file %s to temporary file: %s\n"),
6710 // Set read-only permissions
6712 if (0 == dbe_stat_file (name
, &statbuf
))
6714 mode_t mask
= S_IRUSR
| S_IXUSR
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
;
6715 mode_t mode
= statbuf
.st_mode
& mask
;
6718 // Try to rename temporary file "t" to "abs_caname"
6719 // res = link(t, abs_caname); // link() fails on some f/s - use rename()
6720 res
= rename (t
, abs_caname
);
6723 if (errno
!= EEXIST
)
6725 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: rename(%s, %s) returned error: %d\n"),
6726 t
, abs_caname
, res
);
6733 // File "abs_caname" is already there - continue
6743 if (common_archive
[0] != '/' && aname
[0] != '/')
6745 // compare one relative path to another and find common beginning
6746 char *rel_caname
= dbe_sprintf ("%s/%s", common_archive
, cafname
);
6747 if (rel_caname
== NULL
)
6749 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: unable to allocate memory\n"));
6752 lname
= get_relative_link (rel_caname
, aname
);
6757 if (abs_aname
== NULL
)
6759 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: unable to allocate memory\n"));
6762 lname
= get_relative_link (abs_caname
, abs_aname
);
6765 else // absolute path
6766 lname
= dbe_strdup (abs_caname
);
6770 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: unable to allocate memory\n"));
6773 // Create symbolic link: aname -> lname
6774 if (dbe_stat_file (abs_caname
, NULL
) == 0)
6776 res
= symlink (lname
, aname
);
6779 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: symlink(%s, %s) returned error: %d (errno=%s)\n"),
6780 lname
, aname
, res
, strerror (errno
));
6786 fprintf (stderr
, GTXT ("Created symbolic link %s to file in common archive: %s\n"),
6791 fprintf (stderr
, GTXT ("gprofng-archive: Internal error: file does not exist in common archive: %s\n"),
6801 * Copy file to archive
6805 * @param common_archive
6806 * @return 0 - success
6809 Experiment::copy_file (char *name
, char *aname
, int hide_msg
, char *common_archive
, int relative_path
)
6813 if (0 == copy_file_to_common_archive (name
, aname
, hide_msg
,
6814 common_archive
, relative_path
))
6816 // Error. For now - fatal error. Message is already printed.
6817 fprintf (stderr
, GTXT ("gprofng-archive: Fatal error: cannot copy file %s to common archive %s\n"),
6818 name
, common_archive
);
6821 return (copy_file_to_archive (name
, aname
, hide_msg
));
6825 Experiment::createLoadObject (const char *path
, uint64_t chksum
)
6827 LoadObject
*lo
= dbeSession
->createLoadObject (path
, chksum
);
6828 if (lo
->firstExp
== NULL
)
6829 lo
->firstExp
= this;
6834 Experiment::createLoadObject (const char *path
, const char *runTimePath
)
6836 DbeFile
*df
= findFileInArchive (path
, runTimePath
);
6837 if (df
&& (df
->get_stat () == NULL
))
6838 df
= NULL
; // No access to file
6839 LoadObject
*lo
= dbeSession
->createLoadObject (path
, runTimePath
, df
);
6840 if (df
&& (lo
->dbeFile
->get_location (false) == NULL
))
6842 lo
->dbeFile
->set_location (df
->get_location ());
6843 lo
->dbeFile
->inArchive
= df
->inArchive
;
6844 lo
->dbeFile
->sbuf
= df
->sbuf
;
6845 lo
->dbeFile
->experiment
= df
->experiment
;
6846 lo
->firstExp
= df
->experiment
;
6848 if (lo
->firstExp
== NULL
)
6850 lo
->firstExp
= this;
6851 lo
->dbeFile
->experiment
= this;
6857 Experiment::get_source (const char *path
)
6859 if (founder_exp
&& (founder_exp
!= this))
6860 return founder_exp
->get_source (path
);
6861 if (sourcesMap
== NULL
)
6862 sourcesMap
= new StringMap
<SourceFile
*>(1024, 1024);
6863 if (strncmp (path
, NTXT ("./"), 2) == 0)
6865 SourceFile
*sf
= sourcesMap
->get (path
);
6868 char *fnm
= checkFileInArchive (path
, false);
6871 sf
= new SourceFile (path
);
6872 dbeSession
->append (sf
);
6873 DbeFile
*df
= sf
->dbeFile
;
6874 df
->set_location (fnm
);
6875 df
->inArchive
= true;
6876 df
->check_access (fnm
); // init 'sbuf'
6877 df
->sbuf
.st_mtime
= 0; // Don't check timestamps
6881 sf
= dbeSession
->createSourceFile (path
);
6882 sourcesMap
->put (path
, sf
);
6887 Experiment::get_comparable_objs ()
6889 update_comparable_objs ();
6890 if (comparable_objs
|| dbeSession
->expGroups
->size () <= 1)
6891 return comparable_objs
;
6892 comparable_objs
= new Vector
<Histable
*>(dbeSession
->expGroups
->size ());
6893 for (long i
= 0, sz
= dbeSession
->expGroups
->size (); i
< sz
; i
++)
6895 ExpGroup
*gr
= dbeSession
->expGroups
->get (i
);
6896 if (groupId
== gr
->groupId
)
6898 comparable_objs
->append (this);
6902 for (long i1
= 0, sz1
= gr
->exps
? gr
->exps
->size () : 0; i1
< sz1
; i1
++)
6904 Experiment
*exp
= gr
->exps
->get (i1
);
6905 if ((exp
->comparable_objs
== NULL
) && (dbe_strcmp (utargname
, exp
->utargname
) == 0))
6907 exp
->phaseCompareIdx
= phaseCompareIdx
;
6909 h
->comparable_objs
= comparable_objs
;
6913 comparable_objs
->append (h
);
6915 dump_comparable_objs ();
6916 return comparable_objs
;
6920 Experiment::findFileInArchive (const char *fname
)
6924 char *aname
= get_archived_name (fname
);
6925 DbeFile
*df
= archiveMap
->get (aname
);
6930 return founder_exp
->findFileInArchive (fname
);
6935 Experiment::findFileInArchive (const char *className
, const char *runTimePath
)
6940 const char *fnm
= NULL
;
6941 if (strncmp (runTimePath
, NTXT ("zip:"), 4) == 0)
6942 fnm
= runTimePath
+ 4;
6943 else if (strncmp (runTimePath
, NTXT ("jar:file:"), 9) == 0)
6944 fnm
= runTimePath
+ 9;
6947 const char *s
= strchr (fnm
, '!');
6950 char *s1
= dbe_strndup (fnm
, s
- fnm
);
6951 df
= findFileInArchive (s1
);
6955 df
= findFileInArchive (fnm
);
6957 df
->filetype
|= DbeFile::F_JAR_FILE
;
6959 else if (strncmp (runTimePath
, NTXT ("file:"), 5) == 0)
6961 fnm
= runTimePath
+ 5;
6962 df
= findFileInArchive (fnm
);
6965 df
= findFileInArchive (runTimePath
);
6968 df
= findFileInArchive (className
);