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 *) malloc (bufsz
);
258 buffer
[bufsz
- 1] = (char) 1; // sentinel
260 char *res
= ::fgets (buffer
, bufsz
, fh
);
263 while (buffer
[bufsz
- 1] == (char) 0)
265 int newsz
= bufsz
+ 1024;
266 char *newbuf
= (char *) malloc (newsz
);
269 memcpy (newbuf
, buffer
, bufsz
);
272 buffer
[newsz
- 1] = (char) 1; // sentinel
273 // we don't care about fgets result here
274 ::fgets (buffer
+ bufsz
- 1, newsz
- bufsz
+ 1, fh
);
281 Experiment::ExperimentFile::close ()
285 offset
= ftello64 (fh
);
287 ef_status
= EF_CLOSED
;
293 //-------------------------------------------------- Experiment XML parser
295 Experiment::ExperimentHandler::toInt (Attributes
*attrs
, const char *atr
)
297 const char *str
= attrs
->getValue (atr
);
298 return str
? atoi (str
) : 0;
302 Experiment::ExperimentHandler::toStr (Attributes
*attrs
, const char *atr
)
304 const char *str
= attrs
->getValue (atr
);
305 return dbe_strdup (str
? str
: NTXT (""));
308 Experiment::ExperimentHandler::ExperimentHandler (Experiment
*_exp
)
311 stack
= new Vector
<Element
>;
313 dynfuncModule
= NULL
;
318 mkind
= (Cmsg_warn
) - 1; // CMSG_NONE
323 Experiment::ExperimentHandler::~ExperimentHandler ()
330 Experiment::ExperimentHandler::endDocument ()
332 { // SP_TAG_STATE should be used to describe states, but it isn't
334 DataDescriptor
*dd
= exp
->getDataDescriptor (DATA_HEAP
);
337 PropDescr
*prop
= dd
->getProp (PROP_HTYPE
);
340 char * stateNames
[HEAPTYPE_LAST
] = HEAPTYPE_STATE_STRINGS
;
341 char * stateUNames
[HEAPTYPE_LAST
] = HEAPTYPE_STATE_USTRINGS
;
342 for (int ii
= 0; ii
< HEAPTYPE_LAST
; ii
++)
343 prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
346 dd
= exp
->getDataDescriptor (DATA_IOTRACE
);
349 PropDescr
*prop
= dd
->getProp (PROP_IOTYPE
);
352 char * stateNames
[IOTRACETYPE_LAST
] = IOTRACETYPE_STATE_STRINGS
;
353 char * stateUNames
[IOTRACETYPE_LAST
] = IOTRACETYPE_STATE_USTRINGS
;
354 for (int ii
= 0; ii
< IOTRACETYPE_LAST
; ii
++)
355 prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
362 Experiment::ExperimentHandler::pushElem (Element elem
)
365 stack
->append (curElem
);
369 Experiment::ExperimentHandler::popElem ()
371 stack
->remove (stack
->size () - 1);
372 curElem
= stack
->fetch (stack
->size () - 1);
376 Experiment::ExperimentHandler::startElement (char*, char*, char *qName
, Attributes
*attrs
)
378 DEBUG_CODE
if (DEBUG_SAXPARSER
) dump_startElement (qName
, attrs
);
379 if (strcmp (qName
, SP_TAG_EXPERIMENT
) == 0)
381 pushElem (EL_EXPERIMENT
);
382 const char *str
= attrs
->getValue (NTXT ("version"));
385 int major
= atoi (str
);
386 str
= strchr (str
, '.');
387 int minor
= str
? atoi (str
+ 1) : 0;
388 exp
->exp_maj_version
= major
;
389 exp
->exp_min_version
= minor
;
390 if (major
!= SUNPERF_VERNUM
|| minor
!= SUNPERF_VERNUM_MINOR
)
392 // not the current version, see if we support some earlier versions
396 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"),
397 exp
->get_expt_name (), major
, minor
);
398 // exp->errorq->append( new Emsg(CMSG_FATAL, sb) );
399 exp
->status
= FAILURE
;
401 throw new SAXException (sb
.toString ());
406 else if (strcmp (qName
, SP_TAG_COLLECTOR
) == 0)
407 pushElem (EL_COLLECTOR
);
408 else if (strcmp (qName
, SP_TAG_SETTING
) == 0)
411 pushElem (EL_SETTING
);
412 const char *str
= attrs
->getValue (SP_JCMD_LIMIT
);
416 exp
->coll_params
.limit
= atoi (str
);
418 str
= attrs
->getValue (SP_JCMD_BLKSZ
);
422 exp
->blksz
= strtol (str
, NULL
, 0);
424 str
= attrs
->getValue (SP_JCMD_STACKBASE
);
428 exp
->stack_base
= strtoull (str
, NULL
, 0);
430 str
= attrs
->getValue (SP_JCMD_HWC_DEFAULT
);
434 exp
->hwc_default
= true;
436 str
= attrs
->getValue (SP_JCMD_NOIDLE
);
440 exp
->commentq
->append (new Emsg (CMSG_COMMENT
,
441 GTXT ("*** Note: experiment does not have events from idle CPUs")));
443 str
= attrs
->getValue (SP_JCMD_FAKETIME
);
447 exp
->timelineavail
= false;
448 exp
->commentq
->append (new Emsg (CMSG_COMMENT
,
449 GTXT ("*** Note: experiment does not have timestamps; timeline unavailable")));
451 str
= attrs
->getValue (SP_JCMD_DELAYSTART
);
455 exp
->coll_params
.start_delay
= strdup (str
);
457 str
= attrs
->getValue (SP_JCMD_TERMINATE
);
461 exp
->coll_params
.terminate
= strdup (str
);
463 str
= attrs
->getValue (SP_JCMD_PAUSE_SIG
);
467 exp
->coll_params
.pause_sig
= strdup (str
);
469 str
= attrs
->getValue (SP_JCMD_SAMPLE_PERIOD
);
473 exp
->coll_params
.sample_periodic
= 1;
474 exp
->coll_params
.sample_timer
= atoi (str
);
476 str
= attrs
->getValue (SP_JCMD_SAMPLE_SIG
);
480 exp
->coll_params
.sample_sig
= str
;
482 str
= attrs
->getValue (SP_JCMD_SRCHPATH
);
487 sb
.sprintf (GTXT ("Search path: %s"), str
);
488 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
489 dbeSession
->add_classpath ((char*) str
);
491 str
= attrs
->getValue (SP_JCMD_LINETRACE
);
495 exp
->coll_params
.linetrace
= strdup (str
);
498 str
= attrs
->getValue (SP_JCMD_COLLENV
);
503 sb
.sprintf (GTXT (" Data collection environment variable: %s"), str
);
504 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
508 int nattr
= attrs
->getLength ();
511 fprintf (stderr
, "XXX Unexpected setting found; %d attributes:\n",
513 for (int k
= 0; k
< nattr
; k
++)
515 const char *qn
= attrs
->getQName (k
);
516 const char *vl
= attrs
->getValue (k
);
517 fprintf (stderr
, "XXX %s = %s\n", qn
, vl
);
521 // END OF CODE FOR "setting"
523 else if (strcmp (qName
, SP_TAG_SYSTEM
) == 0)
525 pushElem (EL_SYSTEM
);
526 const char *str
= attrs
->getValue (NTXT ("hostname"));
528 exp
->hostname
= strdup (str
);
529 str
= attrs
->getValue (NTXT ("os"));
532 exp
->os_version
= strdup (str
);
533 /* For Linux experiments expect sparse thread ID's */
534 if (strncmp (str
, NTXT ("SunOS"), 5) != 0)
535 exp
->sparse_threads
= true;
537 str
= attrs
->getValue (NTXT ("arch"));
540 if (strcmp (str
, "i86pc") == 0 || strcmp (str
, "i686") == 0
541 || strcmp (str
, "x86_64") == 0)
542 exp
->platform
= Intel
;
543 else if (strcmp (str
, "aarch64") == 0)
544 exp
->platform
= Aarch64
;
546 exp
->platform
= Sparc
;
547 exp
->need_swap_endian
= (DbeSession::platform
== Sparc
) ?
548 (exp
->platform
!= Sparc
) : (exp
->platform
== Sparc
);
549 exp
->architecture
= strdup (str
);
551 str
= attrs
->getValue (NTXT ("pagesz"));
553 exp
->page_size
= atoi (str
);
554 str
= attrs
->getValue (NTXT ("npages"));
556 exp
->npages
= atoi (str
);
558 else if (strcmp (qName
, SP_TAG_POWERM
) == 0)
559 pushElem (EL_POWERM
);
560 else if (strcmp (qName
, SP_TAG_FREQUENCY
) == 0)
562 pushElem (EL_FREQUENCY
);
563 const char *str
= attrs
->getValue (NTXT ("clk"));
565 exp
->set_clock (atoi (str
));
566 // check for frequency_scaling or turbo_mode recorded from libcollector under dbx
567 str
= attrs
->getValue (NTXT ("frequency_scaling"));
568 const char *str2
= attrs
->getValue (NTXT ("turbo_mode"));
569 if (str
!= NULL
|| str2
!= NULL
)
572 else if (strcmp (qName
, SP_TAG_CPU
) == 0)
576 const char *str
= attrs
->getValue (NTXT ("clk"));
579 int clk
= atoi (str
);
580 if (exp
->maxclock
== 0)
587 if (clk
< exp
->minclock
)
589 if (clk
> exp
->maxclock
)
594 // check for frequency_scaling or turbo_mode
595 str
= attrs
->getValue (NTXT ("frequency_scaling"));
596 const char *str2
= attrs
->getValue (NTXT ("turbo_mode"));
597 if (str
!= NULL
|| str2
!= NULL
)
600 else if (strcmp (qName
, SP_TAG_PROCESS
) == 0)
602 pushElem (EL_PROCESS
);
603 const char *str
= attrs
->getValue (NTXT ("wsize"));
606 int wsz
= atoi (str
);
612 str
= attrs
->getValue (NTXT ("pid"));
614 exp
->pid
= atoi (str
);
615 str
= attrs
->getValue (NTXT ("ppid"));
617 exp
->ppid
= atoi (str
);
618 str
= attrs
->getValue (NTXT ("pgrp"));
620 exp
->pgrp
= atoi (str
);
621 str
= attrs
->getValue (NTXT ("sid"));
623 exp
->sid
= atoi (str
);
624 str
= attrs
->getValue (NTXT ("cwd"));
626 exp
->ucwd
= strdup (str
);
627 str
= attrs
->getValue (NTXT ("pagesz"));
629 exp
->page_size
= atoi (str
);
631 else if (strcmp (qName
, SP_TAG_EVENT
) == 0)
632 { // Start code for event
634 hrtime_t ts
= (hrtime_t
) 0;
635 const char *str
= attrs
->getValue (NTXT ("tstamp"));
637 ts
= parseTStamp (str
);
638 str
= attrs
->getValue (NTXT ("kind"));
641 if (strcmp (str
, SP_JCMD_RUN
) == 0)
644 exp
->exp_start_time
= ts
;
645 str
= attrs
->getValue (NTXT ("time"));
647 exp
->start_sec
= atoll (str
);
648 str
= attrs
->getValue (NTXT ("pid"));
650 exp
->pid
= atoi (str
);
651 str
= attrs
->getValue (NTXT ("ppid"));
653 exp
->ppid
= atoi (str
);
654 str
= attrs
->getValue (NTXT ("pgrp"));
656 exp
->pgrp
= atoi (str
);
657 str
= attrs
->getValue (NTXT ("sid"));
659 exp
->sid
= atoi (str
);
660 exp
->status
= Experiment::INCOMPLETE
;
662 else if (strcmp (str
, SP_JCMD_ARCHIVE
) == 0)
665 sb
.sprintf (GTXT ("gp-archive run: XXXXXXX"));
666 exp
->pprocq
->append (new Emsg (CMSG_WARN
, sb
));
668 else if (strcmp (str
, SP_JCMD_SAMPLE
) == 0)
670 exp
->update_last_event (exp
->exp_start_time
+ ts
); // ts is 0-based
671 str
= attrs
->getValue (NTXT ("id"));
672 int id
= str
? atoi (str
) : -1;
673 char *label
= dbe_strdup (attrs
->getValue (NTXT ("label")));
674 exp
->process_sample_cmd (NULL
, ts
, id
, label
);
676 else if (strcmp (str
, SP_JCMD_EXIT
) == 0)
678 // don't treat EXIT as an event w.r.t. last_event and non_paused_time
679 exp
->status
= Experiment::SUCCESS
;
681 else if (strcmp (str
, SP_JCMD_CERROR
) == 0)
684 str
= attrs
->getValue (NTXT ("id"));
689 str
= attrs
->getValue (NTXT ("ec"));
695 else if (strcmp (str
, SP_JCMD_CWARN
) == 0)
698 str
= attrs
->getValue (NTXT ("id"));
702 else if (strcmp (str
, SP_JCMD_COMMENT
) == 0)
704 mkind
= CMSG_COMMENT
;
705 str
= attrs
->getValue (NTXT ("id"));
708 str
= attrs
->getValue (NTXT ("text"));
712 sb
.sprintf (GTXT ("*** Note: %s"), str
);
713 exp
->commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
716 else if (strcmp (str
, SP_JCMD_DESC_START
) == 0)
718 char *variant
= toStr (attrs
, NTXT ("variant"));
719 char *lineage
= toStr (attrs
, NTXT ("lineage"));
720 int follow
= toInt (attrs
, NTXT ("follow"));
721 char *msg
= toStr (attrs
, NTXT ("msg"));
722 exp
->process_desc_start_cmd (NULL
, ts
, variant
, lineage
, follow
, msg
);
724 else if (strcmp (str
, SP_JCMD_DESC_STARTED
) == 0)
726 char *variant
= toStr (attrs
, NTXT ("variant"));
727 char *lineage
= toStr (attrs
, NTXT ("lineage"));
728 int follow
= toInt (attrs
, NTXT ("follow"));
729 char *msg
= toStr (attrs
, NTXT ("msg"));
730 exp
->process_desc_started_cmd (NULL
, ts
, variant
, lineage
, follow
, msg
);
732 else if (strcmp (str
, SP_JCMD_EXEC_START
) == 0)
734 // if successful, acts like experiment termination - no "exit" entry will follow
735 exp
->update_last_event (exp
->exp_start_time
+ ts
); // ts is 0-based
736 char *variant
= toStr (attrs
, NTXT ("variant"));
737 char *lineage
= toStr (attrs
, NTXT ("lineage"));
738 int follow
= toInt (attrs
, NTXT ("follow"));
739 char *msg
= toStr (attrs
, NTXT ("msg"));
740 exp
->process_desc_start_cmd (NULL
, ts
, variant
, lineage
, follow
, msg
);
741 exp
->exec_started
= true;
743 else if (strcmp (str
, SP_JCMD_EXEC_ERROR
) == 0)
745 exp
->update_last_event (exp
->exp_start_time
+ ts
); // ts is 0-based
746 char *variant
= toStr (attrs
, NTXT ("variant"));
747 char *lineage
= toStr (attrs
, NTXT ("lineage"));
748 int follow
= toInt (attrs
, NTXT ("follow"));
749 char *msg
= toStr (attrs
, NTXT ("msg"));
750 exp
->process_desc_started_cmd (NULL
, ts
, variant
, lineage
, follow
, msg
);
751 exp
->exec_started
= false;
753 else if (strcmp (str
, SP_JCMD_JTHRSTART
) == 0)
755 char *name
= dbe_strdup (attrs
->getValue (NTXT ("name")));
756 char *grpname
= dbe_strdup (attrs
->getValue (NTXT ("grpname")));
757 char *prntname
= dbe_strdup (attrs
->getValue (NTXT ("prntname")));
758 str
= attrs
->getValue (NTXT ("tid"));
759 uint64_t tid
= str
? strtoull (str
, NULL
, 0) : 0;
760 str
= attrs
->getValue (NTXT ("jthr"));
761 Vaddr jthr
= str
? strtoull (str
, NULL
, 0) : 0;
762 str
= attrs
->getValue (NTXT ("jenv"));
763 Vaddr jenv
= str
? strtoull (str
, NULL
, 0) : 0;
764 exp
->process_jthr_start_cmd (NULL
, name
, grpname
, prntname
, tid
, jthr
, jenv
, ts
);
766 else if (strcmp (str
, SP_JCMD_JTHREND
) == 0)
768 str
= attrs
->getValue (NTXT ("tid"));
769 uint64_t tid
= str
? strtoull (str
, NULL
, 0) : 0;
770 str
= attrs
->getValue (NTXT ("jthr"));
771 Vaddr jthr
= str
? strtoull (str
, NULL
, 0) : 0;
772 str
= attrs
->getValue (NTXT ("jenv"));
773 Vaddr jenv
= str
? strtoull (str
, NULL
, 0) : 0;
774 exp
->process_jthr_end_cmd (NULL
, tid
, jthr
, jenv
, ts
);
776 else if (strcmp (str
, SP_JCMD_GCEND
) == 0)
778 if (exp
->getDataDescriptor (DATA_GCEVENT
) == NULL
)
779 exp
->newDataDescriptor (DATA_GCEVENT
);
780 exp
->process_gc_end_cmd (ts
);
782 else if (strcmp (str
, SP_JCMD_GCSTART
) == 0)
784 if (exp
->getDataDescriptor (DATA_GCEVENT
) == NULL
)
785 exp
->newDataDescriptor (DATA_GCEVENT
);
786 exp
->process_gc_start_cmd (ts
);
788 else if (strcmp (str
, SP_JCMD_PAUSE
) == 0)
790 if (exp
->resume_ts
!= MAX_TIME
)
792 // data collection was active
793 hrtime_t delta
= ts
- exp
->resume_ts
;
794 exp
->non_paused_time
+= delta
;
795 exp
->resume_ts
= MAX_TIME
; // collection is paused
798 str
= attrs
->getValue (NTXT ("name"));
800 sb
.sprintf (GTXT ("Pause: %ld.%09ld"), (long) (ts
/ NANOSEC
),
801 (long) (ts
% NANOSEC
));
803 sb
.sprintf (GTXT ("Pause (%s): %ld.%09ld"), str
,
804 (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
));
805 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
807 else if (strcmp (str
, SP_JCMD_RESUME
) == 0)
809 if (exp
->resume_ts
== MAX_TIME
)
810 // data collection was paused
811 exp
->resume_ts
= ts
; // remember start time
813 sb
.sprintf (GTXT ("Resume: %ld.%09ld"), (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
));
814 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
815 if (exp
->exp_start_time
== ZERO_TIME
)
816 exp
->exp_start_time
= ts
;
818 else if (strcmp (str
, SP_JCMD_THREAD_PAUSE
) == 0)
820 str
= attrs
->getValue (NTXT ("tid"));
821 uint64_t tid
= str
? strtoull (str
, NULL
, 0) : 0;
823 sb
.sprintf (GTXT ("Thread %llu pause: %ld.%09ld"), (unsigned long long) tid
,
824 (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
));
825 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
827 else if (strcmp (str
, SP_JCMD_THREAD_RESUME
) == 0)
829 str
= attrs
->getValue (NTXT ("tid"));
830 uint64_t tid
= str
? strtoull (str
, NULL
, 0) : 0;
832 sb
.sprintf (GTXT ("Thread %llu resume: %ld.%09ld"), (unsigned long long) tid
,
833 (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
));
834 exp
->runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
836 else if (strcmp (str
, NTXT ("map")) == 0)
838 ts
+= exp
->exp_start_time
;
839 str
= attrs
->getValue (NTXT ("vaddr"));
840 Vaddr vaddr
= str
? strtoull (str
, NULL
, 0) : 0;
841 str
= attrs
->getValue (NTXT ("size"));
842 int msize
= str
? atoi (str
) : 0;
843 str
= attrs
->getValue (NTXT ("foffset"));
844 int64_t offset
= str
? strtoll (str
, NULL
, 0) : 0;
845 str
= attrs
->getValue (NTXT ("modes"));
846 int64_t modes
= str
? strtoll (str
, NULL
, 0) : 0;
847 str
= attrs
->getValue (NTXT ("chksum"));
850 chksum
= Elf::normalize_checksum (strtoll (str
, NULL
, 0));
851 char *name
= (char *) attrs
->getValue (NTXT ("name"));
852 str
= attrs
->getValue (NTXT ("object"));
853 if (strcmp (str
, NTXT ("segment")) == 0)
855 if (strcmp (name
, NTXT ("LinuxKernel")) == 0)
856 exp
->process_Linux_kernel_cmd (ts
);
858 exp
->process_seg_map_cmd (NULL
, ts
, vaddr
, msize
, 0,
859 offset
, modes
, chksum
, name
);
861 else if (strcmp (str
, NTXT ("function")) == 0)
863 exp
->process_fn_load_cmd (dynfuncModule
, name
, vaddr
, msize
, ts
);
864 dynfuncModule
= NULL
;
866 else if (strcmp (str
, NTXT ("dynfunc")) == 0)
868 if (dynfuncModule
== NULL
)
870 dynfuncModule
= dbeSession
->createModule (exp
->get_dynfunc_lo (DYNFUNC_SEGMENT
), name
);
871 dynfuncModule
->flags
|= MOD_FLAG_UNKNOWN
;
872 dynfuncModule
->set_file_name (dbe_strdup (dynfuncModule
->getMainSrc ()->get_name ()));
874 (void) exp
->create_dynfunc (dynfuncModule
,
875 (char*) attrs
->getValue (NTXT ("funcname")), vaddr
, msize
);
877 else if (strcmp (str
, NTXT ("jcm")) == 0)
879 str
= attrs
->getValue (NTXT ("methodId"));
880 Vaddr mid
= str
? strtoull (str
, NULL
, 0) : 0;
881 exp
->process_jcm_load_cmd (NULL
, mid
, vaddr
, msize
, ts
);
884 else if (strcmp (str
, NTXT ("unmap")) == 0)
886 ts
+= exp
->exp_start_time
;
887 str
= attrs
->getValue (NTXT ("vaddr"));
888 Vaddr vaddr
= str
? strtoull (str
, NULL
, 0) : 0;
889 exp
->process_seg_unmap_cmd (NULL
, ts
, vaddr
);
892 // end of code for event
894 else if (strcmp (qName
, SP_TAG_PROFILE
) == 0)
896 pushElem (EL_PROFILE
);
897 const char *str
= attrs
->getValue (NTXT ("name"));
900 if (strcmp (str
, NTXT ("profile")) == 0)
902 exp
->coll_params
.profile_mode
= 1;
903 str
= attrs
->getValue (NTXT ("numstates"));
905 exp
->coll_params
.lms_magic_id
= atoi (str
);
906 str
= attrs
->getValue (NTXT ("ptimer"));
908 exp
->coll_params
.ptimer_usec
= atoi (str
); // microseconds
910 PropDescr
*mstate_prop
= NULL
;
911 char * stateNames
[/*LMS_NUM_STATES*/] = LMS_STATE_STRINGS
;
912 char * stateUNames
[/*LMS_NUM_STATES*/] = LMS_STATE_USTRINGS
;
914 dDscr
= exp
->newDataDescriptor (DATA_CLOCK
);
915 PropDescr
*prop
= new PropDescr (PROP_MSTATE
, NTXT ("MSTATE"));
916 prop
->uname
= dbe_strdup (GTXT ("Thread state"));
917 prop
->vtype
= TYPE_UINT32
;
918 // (states added below)
919 dDscr
->addProperty (prop
);
922 prop
= new PropDescr (PROP_NTICK
, NTXT ("NTICK"));
923 prop
->uname
= dbe_strdup (GTXT ("Number of Profiling Ticks"));
924 prop
->vtype
= TYPE_UINT32
;
925 dDscr
->addProperty (prop
);
928 switch (exp
->coll_params
.lms_magic_id
)
930 case LMS_MAGIC_ID_SOLARIS
:
931 exp
->register_metric (Metric::CP_TOTAL
);
932 exp
->register_metric (Metric::CP_TOTAL_CPU
);
933 exp
->register_metric (Metric::CP_LMS_USER
);
934 exp
->register_metric (Metric::CP_LMS_SYSTEM
);
935 exp
->register_metric (Metric::CP_LMS_TRAP
);
936 exp
->register_metric (Metric::CP_LMS_DFAULT
);
937 exp
->register_metric (Metric::CP_LMS_TFAULT
);
938 exp
->register_metric (Metric::CP_LMS_KFAULT
);
939 exp
->register_metric (Metric::CP_LMS_STOPPED
);
940 exp
->register_metric (Metric::CP_LMS_WAIT_CPU
);
941 exp
->register_metric (Metric::CP_LMS_SLEEP
);
942 exp
->register_metric (Metric::CP_LMS_USER_LOCK
);
943 for (int ii
= 0; ii
< LMS_NUM_SOLARIS_MSTATES
; ii
++)
944 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
946 case LMS_MAGIC_ID_ERKERNEL_KERNEL
:
947 exp
->register_metric (Metric::CP_KERNEL_CPU
);
949 int ii
= LMS_KERNEL_CPU
;
950 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
953 case LMS_MAGIC_ID_ERKERNEL_USER
:
954 exp
->register_metric (Metric::CP_TOTAL_CPU
);
955 exp
->register_metric (Metric::CP_LMS_USER
);
956 exp
->register_metric (Metric::CP_LMS_SYSTEM
);
958 int ii
= LMS_KERNEL_CPU
;
959 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
961 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
963 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
966 case LMS_MAGIC_ID_LINUX
:
967 exp
->register_metric (Metric::CP_TOTAL_CPU
);
969 int ii
= LMS_LINUX_CPU
;
970 mstate_prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
978 else if (strcmp (str
, NTXT ("heaptrace")) == 0)
980 exp
->coll_params
.heap_mode
= 1;
981 exp
->leaklistavail
= true;
982 exp
->heapdataavail
= true;
983 exp
->register_metric (Metric::HEAP_ALLOC_BYTES
);
984 exp
->register_metric (Metric::HEAP_ALLOC_CNT
);
985 exp
->register_metric (Metric::HEAP_LEAK_BYTES
);
986 exp
->register_metric (Metric::HEAP_LEAK_CNT
);
987 dDscr
= exp
->newDataDescriptor (DATA_HEAP
);
989 else if (strcmp (str
, NTXT ("iotrace")) == 0)
991 exp
->coll_params
.io_mode
= 1;
992 exp
->iodataavail
= true;
993 exp
->register_metric (Metric::IO_READ_TIME
);
994 exp
->register_metric (Metric::IO_READ_BYTES
);
995 exp
->register_metric (Metric::IO_READ_CNT
);
996 exp
->register_metric (Metric::IO_WRITE_TIME
);
997 exp
->register_metric (Metric::IO_WRITE_BYTES
);
998 exp
->register_metric (Metric::IO_WRITE_CNT
);
999 exp
->register_metric (Metric::IO_OTHER_TIME
);
1000 exp
->register_metric (Metric::IO_OTHER_CNT
);
1001 exp
->register_metric (Metric::IO_ERROR_TIME
);
1002 exp
->register_metric (Metric::IO_ERROR_CNT
);
1003 dDscr
= exp
->newDataDescriptor (DATA_IOTRACE
);
1005 else if (strcmp (str
, NTXT ("synctrace")) == 0)
1007 exp
->coll_params
.sync_mode
= 1;
1008 str
= attrs
->getValue (NTXT ("threshold"));
1010 exp
->coll_params
.sync_threshold
= atoi (str
);
1011 str
= attrs
->getValue (NTXT ("scope"));
1013 exp
->coll_params
.sync_scope
= atoi (str
);
1014 else // Should only happen with old experiments; use the old default
1015 exp
->coll_params
.sync_scope
= SYNCSCOPE_NATIVE
| SYNCSCOPE_JAVA
;
1016 exp
->register_metric (Metric::SYNC_WAIT_TIME
);
1017 exp
->register_metric (Metric::SYNC_WAIT_COUNT
);
1018 dDscr
= exp
->newDataDescriptor (DATA_SYNCH
);
1020 else if (strcmp (str
, NTXT ("omptrace")) == 0)
1022 exp
->coll_params
.omp_mode
= 1;
1023 dDscr
= exp
->newDataDescriptor (DATA_OMP
, DDFLAG_NOSHOW
);
1025 else if (strcmp (str
, NTXT ("hwcounter")) == 0)
1027 str
= attrs
->getValue (NTXT ("cpuver"));
1028 int cpuver
= str
? atoi (str
) : 0;
1029 char *counter
= dbe_strdup (attrs
->getValue (NTXT ("hwcname")));
1030 char *int_name
= dbe_strdup (attrs
->getValue (NTXT ("int_name"))); // may not be present
1031 str
= attrs
->getValue (NTXT ("interval"));
1032 int interval
= str
? atoi (str
) : 0;
1033 str
= attrs
->getValue (NTXT ("tag"));
1034 int tag
= str
? atoi (str
) : 0;
1035 str
= attrs
->getValue (NTXT ("memop"));
1036 int i_tpc
= str
? atoi (str
) : 0;
1037 char *modstr
= dbe_strdup (attrs
->getValue (NTXT ("modstr")));
1038 exp
->process_hwcounter_cmd (NULL
, cpuver
, counter
, int_name
, interval
, tag
, i_tpc
, modstr
);
1039 dDscr
= exp
->newDataDescriptor (DATA_HWC
);
1041 else if (strcmp (str
, NTXT ("hwsimctr")) == 0)
1043 int cpuver
= toInt (attrs
, NTXT ("cpuver"));
1044 char *hwcname
= dbe_strdup (attrs
->getValue (NTXT ("hwcname")));
1045 char *int_name
= dbe_strdup (attrs
->getValue (NTXT ("int_name")));
1046 char *metric
= dbe_strdup (attrs
->getValue (NTXT ("metric")));
1047 int reg
= toInt (attrs
, NTXT ("reg_num"));
1048 int interval
= toInt (attrs
, NTXT ("interval"));
1049 int timecvt
= toInt (attrs
, NTXT ("timecvt"));
1050 int i_tpc
= toInt (attrs
, NTXT ("memop"));
1051 int tag
= toInt (attrs
, NTXT ("tag"));
1052 exp
->process_hwsimctr_cmd (NULL
, cpuver
, hwcname
, int_name
, metric
, reg
,
1053 interval
, timecvt
, i_tpc
, tag
);
1054 dDscr
= exp
->newDataDescriptor (DATA_HWC
);
1056 else if (strcmp (str
, NTXT ("dversion")) == 0)
1057 exp
->dversion
= dbe_strdup (attrs
->getValue (NTXT ("version")));
1058 else if (strcmp (str
, NTXT ("jprofile")) == 0)
1060 exp
->has_java
= true;
1061 str
= attrs
->getValue (NTXT ("jversion"));
1063 exp
->jversion
= strdup (str
);
1065 else if (strcmp (str
, NTXT ("datarace")) == 0)
1067 exp
->coll_params
.race_mode
= 1;
1068 exp
->racelistavail
= true;
1069 str
= attrs
->getValue (NTXT ("scheme"));
1070 exp
->coll_params
.race_stack
= str
? atoi (str
) : 0;
1071 exp
->register_metric (Metric::RACCESS
);
1072 dDscr
= exp
->newDataDescriptor (DATA_RACE
);
1074 else if (strcmp (str
, NTXT ("deadlock")) == 0)
1076 exp
->coll_params
.deadlock_mode
= 1;
1077 exp
->deadlocklistavail
= true;
1078 exp
->register_metric (Metric::DEADLOCKS
);
1079 dDscr
= exp
->newDataDescriptor (DATA_DLCK
);
1082 /* XXX -- obsolete tag, but is still written to experiments */
1083 else if (strcmp (qName
, SP_TAG_DATAPTR
) == 0)
1085 pushElem (EL_DATAPTR
);
1088 else if (strcmp (qName
, SP_TAG_PROFDATA
) == 0)
1090 pushElem (EL_PROFDATA
);
1091 // SS12 HWC experiments are not well structured
1092 const char *fname
= attrs
->getValue (NTXT ("fname"));
1093 if (fname
&& strcmp (fname
, SP_HWCNTR_FILE
) == 0)
1094 dDscr
= exp
->newDataDescriptor (DATA_HWC
);
1096 else if (strcmp (qName
, SP_TAG_PROFPCKT
) == 0)
1098 pushElem (EL_PROFPCKT
);
1099 const char *str
= attrs
->getValue (NTXT ("kind")); // see Pckt_type
1100 int kind
= str
? atoi (str
) : -1;
1103 if (exp
->coll_params
.omp_mode
== 1)
1105 if (kind
== OMP_PCKT
)
1106 dDscr
= exp
->newDataDescriptor (DATA_OMP
, DDFLAG_NOSHOW
);
1107 else if (kind
== OMP2_PCKT
)
1108 dDscr
= exp
->newDataDescriptor (DATA_OMP2
, DDFLAG_NOSHOW
);
1109 else if (kind
== OMP3_PCKT
)
1110 dDscr
= exp
->newDataDescriptor (DATA_OMP3
, DDFLAG_NOSHOW
);
1111 else if (kind
== OMP4_PCKT
)
1112 dDscr
= exp
->newDataDescriptor (DATA_OMP4
, DDFLAG_NOSHOW
);
1113 else if (kind
== OMP5_PCKT
)
1114 dDscr
= exp
->newDataDescriptor (DATA_OMP5
, DDFLAG_NOSHOW
);
1116 pDscr
= exp
->newPacketDescriptor (kind
, dDscr
);
1119 else if (strcmp (qName
, SP_TAG_FIELD
) == 0)
1121 pushElem (EL_FIELD
);
1124 const char *name
= attrs
->getValue (NTXT ("name"));
1127 int propID
= dbeSession
->registerPropertyName (name
);
1128 propDscr
= new PropDescr (propID
, name
);
1129 FieldDescr
*fldDscr
= new FieldDescr (propID
, name
);
1131 const char *str
= attrs
->getValue (NTXT ("type"));
1134 if (strcmp (str
, NTXT ("INT32")) == 0)
1135 fldDscr
->vtype
= TYPE_INT32
;
1136 else if (strcmp (str
, NTXT ("UINT32")) == 0)
1137 fldDscr
->vtype
= TYPE_UINT32
;
1138 else if (strcmp (str
, NTXT ("INT64")) == 0)
1139 fldDscr
->vtype
= TYPE_INT64
;
1140 else if (strcmp (str
, NTXT ("UINT64")) == 0)
1141 fldDscr
->vtype
= TYPE_UINT64
;
1142 else if (strcmp (str
, NTXT ("STRING")) == 0)
1143 fldDscr
->vtype
= TYPE_STRING
;
1144 else if (strcmp (str
, NTXT ("DOUBLE")) == 0)
1145 fldDscr
->vtype
= TYPE_DOUBLE
;
1146 else if (strcmp (str
, NTXT ("DATE")) == 0)
1148 fldDscr
->vtype
= TYPE_DATE
;
1149 const char *fmt
= attrs
->getValue (NTXT ("format"));
1150 fldDscr
->format
= strdup (fmt
? fmt
: "");
1153 propDscr
->vtype
= fldDscr
->vtype
;
1155 // TYPE_DATE is converted to TYPE_UINT64 in propDscr
1156 if (fldDscr
->vtype
== TYPE_DATE
)
1157 propDscr
->vtype
= TYPE_UINT64
;
1159 // Fix some types until they are fixed in libcollector
1160 if (propID
== PROP_VIRTPC
|| propID
== PROP_PHYSPC
)
1162 if (fldDscr
->vtype
== TYPE_INT32
)
1163 propDscr
->vtype
= TYPE_UINT32
;
1164 else if (fldDscr
->vtype
== TYPE_INT64
)
1165 propDscr
->vtype
= TYPE_UINT64
;
1168 // The following props get mapped to 32-bit values in readPacket
1169 if (propID
== PROP_CPUID
|| propID
== PROP_THRID
1170 || propID
== PROP_LWPID
)
1171 propDscr
->vtype
= TYPE_UINT32
; // override experiment property
1173 str
= attrs
->getValue (NTXT ("uname"));
1175 propDscr
->uname
= strdup (PTXT ((char*) str
));
1176 str
= attrs
->getValue (NTXT ("noshow"));
1177 if (str
&& atoi (str
) != 0)
1178 propDscr
->flags
|= PRFLAG_NOSHOW
;
1183 sb
.sprintf (GTXT ("*** Error: data parsing failed. Log file is corrupted."));
1184 exp
->warnq
->append (new Emsg (CMSG_ERROR
, sb
));
1185 throw new SAXException (sb
.toString ());
1188 dDscr
->addProperty (propDscr
);
1189 str
= attrs
->getValue (NTXT ("offset"));
1191 fldDscr
->offset
= atoi (str
);
1192 pDscr
->addField (fldDscr
);
1195 else if (strcmp (qName
, SP_TAG_STATE
) == 0)
1197 pushElem (EL_STATE
);
1198 if (propDscr
!= NULL
)
1200 const char *str
= attrs
->getValue (NTXT ("value"));
1201 int value
= str
? atoi (str
) : -1;
1202 str
= attrs
->getValue (NTXT ("name"));
1203 const char *ustr
= attrs
->getValue (NTXT ("uname"));
1204 propDscr
->addState (value
, str
, ustr
);
1207 else if (strcmp (qName
, SP_TAG_DTRACEFATAL
) == 0)
1208 pushElem (EL_DTRACEFATAL
);
1212 sb
.sprintf (GTXT ("*** Warning: unrecognized element %s"), qName
);
1213 exp
->warnq
->append (new Emsg (CMSG_WARN
, sb
));
1219 Experiment::ExperimentHandler::characters (char *ch
, int start
, int length
)
1224 exp
->cversion
= dbe_strndup (ch
+ start
, length
);
1227 exp
->process_arglist_cmd (NULL
, dbe_strndup (ch
+ start
, length
));
1231 text
= dbe_strndup (ch
+ start
, length
);
1239 Experiment::ExperimentHandler::endElement (char*, char*, char*)
1241 if (curElem
== EL_EVENT
&& mkind
>= 0 && mnum
>= 0)
1245 str
= dbe_sprintf ("%s -- %s", text
!= NULL
? text
: "", strerror (mec
));
1247 str
= dbe_sprintf ("%s", text
!= NULL
? text
: "");
1248 Emsg
*msg
= new Emsg (mkind
, mnum
, str
);
1249 if (mkind
== CMSG_WARN
)
1251 if (mnum
!= COL_WARN_FSTYPE
1252 || dbeSession
->check_ignore_fs_warn () == false)
1253 exp
->warnq
->append (msg
);
1255 exp
->commentq
->append (msg
);
1257 else if (mkind
== CMSG_ERROR
|| mkind
== CMSG_FATAL
)
1258 exp
->errorq
->append (msg
);
1259 else if (mkind
== CMSG_COMMENT
)
1260 exp
->commentq
->append (msg
);
1263 mkind
= (Cmsg_warn
) - 1;
1267 else if (curElem
== EL_PROFILE
)
1269 else if (curElem
== EL_PROFPCKT
)
1271 else if (curElem
== EL_FIELD
)
1279 Experiment::ExperimentHandler::error (SAXParseException
*e
)
1282 sb
.sprintf (GTXT ("%s at line %d, column %d"),
1283 e
->getMessage (), e
->getLineNumber (), e
->getColumnNumber ());
1284 char *msg
= sb
.toString ();
1285 SAXException
*e1
= new SAXException (msg
);
1290 //-------------------------------------------------- Experiment
1292 Experiment::Experiment ()
1295 userExpId
= expIdx
= -1;
1298 children_exps
= new Vector
<Experiment
*>;
1299 loadObjs
= new Vector
<LoadObject
*>;
1300 loadObjMap
= new StringMap
<LoadObject
*>(128, 128);
1303 // Initialize configuration information.
1309 architecture
= NULL
;
1317 exp_maj_version
= 0;
1318 exp_min_version
= 0;
1323 stack_base
= 0xf0000000;
1329 hwc_default
= false;
1332 // clear HWC event stats
1336 memset (&coll_params
, 0, sizeof (coll_params
));
1342 exec_started
= false;
1343 timelineavail
= true;
1344 leaklistavail
= false;
1345 heapdataavail
= false;
1346 iodataavail
= false;
1347 dataspaceavail
= false;
1349 racelistavail
= false;
1350 deadlocklistavail
= false;
1352 tiny_threshold
= -1;
1358 gc_duration
= ZERO_TIME
;
1359 exp_start_time
= ZERO_TIME
; // not known. Wall-clock hrtime (not zero based)
1360 last_event
= ZERO_TIME
; // not known. Wall-clock hrtime (not zero based)
1361 non_paused_time
= 0; // 0 non-paused time (will sum as experiment is processed)
1362 resume_ts
= 0; // by default, collection is "resumed" (not paused) from time=0
1363 need_swap_endian
= false;
1364 exp_rel_start_time_set
= false;
1365 exp_rel_start_time
= ZERO_TIME
;
1367 hex_field_width
= 8;
1368 hw_cpuver
= CPUVER_UNDEFINED
;
1369 machinemodel
= NULL
;
1372 fndr_arch_name
= NULL
;
1373 dyntext_name
= NULL
;
1376 dataDscrs
= new Vector
<DataDescriptor
*>;
1377 for (int i
= 0; i
< DATA_LAST
; ++i
)
1378 dataDscrs
->append (NULL
);
1380 pcktDscrs
= new Vector
<PacketDescriptor
*>;
1381 blksz
= PROFILE_BUFFER_CHUNK
;
1382 jthreads
= new Vector
<JThread
*>;
1383 jthreads_idx
= new Vector
<JThread
*>;
1384 gcevents
= new Vector
<GCEvent
*>;
1385 gcevent_last_used
= (GCEvent
*) NULL
;
1386 heapUnmapEvents
= new Vector
<UnmapChunk
*>;
1388 cstackShowHide
= NULL
;
1389 frmpckts
= new Vector
<RawFramePacket
*>;
1390 typedef DefaultMap2D
<uint32_t, hrtime_t
, uint64_t> OmpMap0
;
1391 mapPRid
= new OmpMap0 (OmpMap0::Interval
);
1392 typedef DefaultMap2D
<uint32_t, hrtime_t
, void*> OmpMap
;
1393 mapPReg
= new OmpMap (OmpMap::Interval
);
1394 mapTask
= new OmpMap (OmpMap::Interval
);
1401 uidnodes
= new Vector
<UIDnode
*>;
1402 mrecs
= new Vector
<MapRecord
*>;
1403 samples
= new Vector
<Sample
*>;
1404 sample_last_used
= (Sample
*) NULL
;
1405 first_sample_label
= (char*) NULL
;
1408 resolveFrameInfo
= true;
1409 discardTiny
= false;
1413 Experiment::~Experiment ()
1416 free (coll_params
.linetrace
);
1417 for (int i
= 0; i
< MAX_HWCOUNT
; i
++)
1419 free (coll_params
.hw_aux_name
[i
]);
1420 free (coll_params
.hw_username
[i
]);
1424 free (architecture
);
1435 free (fndr_arch_name
);
1436 free (dyntext_name
);
1437 delete jthreads_idx
;
1439 delete cstackShowHide
;
1444 destroy_map (DbeFile
*, archiveMap
);
1448 delete children_exps
;
1452 free (first_sample_label
);
1453 free (machinemodel
);
1455 dataDscrs
->destroy ();
1457 pcktDscrs
->destroy ();
1459 jthreads
->destroy ();
1461 gcevents
->destroy ();
1463 heapUnmapEvents
->destroy ();
1464 delete heapUnmapEvents
;
1465 frmpckts
->destroy ();
1467 samples
->destroy ();
1472 for (long i
= 0; i
< nchunks
; i
++)
1478 Experiment::init_cache ()
1482 smemHTable
= new SegMem
*[HTableSize
];
1483 instHTable
= new DbeInstr
*[HTableSize
];
1484 for (int i
= 0; i
< HTableSize
; i
++)
1486 smemHTable
[i
] = NULL
;
1487 instHTable
[i
] = NULL
;
1489 uidHTable
= new UIDnode
*[HTableSize
];
1490 for (int i
= 0; i
< HTableSize
; i
++)
1491 uidHTable
[i
] = NULL
;
1493 cstack
= CallStack::getInstance (this);
1494 cstackShowHide
= CallStack::getInstance (this);
1501 seg_items
= new Vector
<SegMem
*>;
1502 maps
= new PRBTree ();
1503 jmaps
= NULL
; // used by JAVA_CLASSES only
1507 min_thread
= (uint64_t) - 1;
1510 min_lwp
= (uint64_t) - 1;
1513 min_cpu
= (uint64_t) - 1;
1517 commentq
= new Emsgqueue (NTXT ("commentq"));
1518 runlogq
= new Emsgqueue (NTXT ("runlogq"));
1519 errorq
= new Emsgqueue (NTXT ("errorq"));
1520 warnq
= new Emsgqueue (NTXT ("warnq"));
1521 notesq
= new Emsgqueue (NTXT ("notesq"));
1522 pprocq
= new Emsgqueue (NTXT ("pprocq"));
1525 metrics
= new Vector
<BaseMetric
*>;
1526 tagObjs
= new Vector
<Vector
<Histable
*>*>;
1527 tagObjs
->store (PROP_THRID
, new Vector
<Histable
*>);
1528 tagObjs
->store (PROP_LWPID
, new Vector
<Histable
*>);
1529 tagObjs
->store (PROP_CPUID
, new Vector
<Histable
*>);
1530 tagObjs
->store (PROP_EXPID
, new Vector
<Histable
*>);
1531 sparse_threads
= false;
1537 seg_items
->destroy ();
1541 delete[] smemHTable
;
1542 delete[] instHTable
;
1558 Vec_loop (BaseMetric
*, metrics
, index
, mtr
)
1560 dbeSession
->drop_metric (mtr
);
1563 tagObjs
->fetch (PROP_THRID
)->destroy ();
1564 tagObjs
->fetch (PROP_LWPID
)->destroy ();
1565 tagObjs
->fetch (PROP_CPUID
)->destroy ();
1566 tagObjs
->fetch (PROP_EXPID
)->destroy ();
1567 tagObjs
->destroy ();
1571 // These are the data files which can be read in parallel
1572 // for multiple sub-experiments.
1573 // Postpone calling resolve_frame_info()
1575 Experiment::read_experiment_data (bool read_ahead
)
1578 read_frameinfo_file ();
1581 resolveFrameInfo
= false;
1582 (void) get_profile_events ();
1583 resolveFrameInfo
= true;
1587 Experiment::Exp_status
1588 Experiment::open_epilogue ()
1591 // set up mapping for tagObj(PROP_EXPID)
1592 (void) mapTagValue (PROP_EXPID
, userExpId
);
1595 if (last_event
!= ZERO_TIME
)
1596 { // if last_event is known
1598 hrtime_t ts
= last_event
- exp_start_time
;
1599 sb
.sprintf (GTXT ("Experiment Ended: %ld.%09ld\nData Collection Duration: %ld.%09ld"),
1600 (long) (ts
/ NANOSEC
), (long) (ts
% NANOSEC
),
1601 (long) (non_paused_time
/ NANOSEC
),
1602 (long) (non_paused_time
% NANOSEC
));
1603 runlogq
->append (new Emsg (CMSG_COMMENT
, sb
));
1606 // Check for incomplete experiment, and inform the user
1607 if (status
== INCOMPLETE
)
1609 if (exec_started
== true)
1610 // experiment ended with the exec, not abnormally
1614 char * cmnt
= GTXT ("*** Note: experiment was not closed");
1615 commentq
->append (new Emsg (CMSG_COMMENT
, cmnt
));
1616 // runlogq->append(new Emsg(CMSG_COMMENT, cmnt));
1619 // write a descriptive header for the experiment
1624 Experiment::Exp_status
1625 Experiment::open (char *path
)
1628 // Find experiment directory
1629 if (find_expdir (path
) != SUCCESS
)
1630 // message will have been queued and status set
1633 // Get creation time for experiment
1635 if (dbe_stat (path
, &st
) == 0)
1636 mtime
= st
.st_mtime
;
1638 // Read the warnings file
1641 // Open the log file
1643 if (status
== SUCCESS
&& last_event
// last event is initialized
1644 && (last_event
- exp_start_time
) / 1000000 < tiny_threshold
)
1646 // Process "tiny_threshold" (SP_ANALYZER_DISCARD_TINY_EXPERIMENTS)
1647 // At this point, we've only processed log.xml.
1648 // Note: if an experiment terminated abnormally, last_event will not yet
1649 // represent events from clock profiling and other metrics.
1650 // Other events will often have timestamps after the last log.xml entry.
1654 if (status
== FAILURE
)
1656 if (logFile
->get_status () == ExperimentFile::EF_FAILURE
)
1658 Emsg
*m
= new Emsg (CMSG_FATAL
, GTXT ("*** Error: log file in experiment cannot be read"));
1661 else if (fetch_errors () == NULL
)
1665 Emsg
*m
= new Emsg (CMSG_FATAL
, GTXT ("*** Error: log does not show target starting"));
1670 Emsg
*m
= new Emsg (CMSG_FATAL
, GTXT ("*** Error: log file in experiment could not be parsed"));
1681 GTXT ("*** Warning: system has variable clock frequency, which may cause variable execution times and inaccurate conversions of cycle counts into time."));
1682 warnq
->append (new Emsg (CMSG_WARN
, sb
));
1685 // Read the notes file
1687 read_labels_file ();
1690 // The log file shows experiment started
1691 read_java_classes_file ();
1695 // Dyntext file has to be processed after loadobjects file
1696 // as we need to be able to map (vaddr,ts) to dynamic functions.
1697 read_dyntext_file ();
1699 // Read the overview file and create samples.
1700 // Profiling data hasn't been read yet so we may have
1701 // events after the last recorded sample.
1702 // We'll create a fake sample to cover all those
1704 read_overview_file ();
1706 // Check if instruction frequency data is available
1709 // Check if OMP data is available
1715 /* XXX -- update() is a no-op now, but may be needed for auto-update */
1716 Experiment::Exp_status
1717 Experiment::update ()
1723 Experiment::append (LoadObject
*lo
)
1725 loadObjs
->append (lo
);
1726 char *obj_name
= lo
->get_pathname ();
1727 char *bname
= get_basename (obj_name
);
1728 loadObjMap
->put (obj_name
, lo
);
1729 loadObjMap
->put (bname
, lo
);
1730 if (lo
->flags
& SEG_FLAG_EXE
)
1731 loadObjMap
->put (COMP_EXE_NAME
, lo
);
1735 Experiment::read_notes_file ()
1740 char *fname
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_NOTES_FILE
);
1741 FILE *f
= fopen (fname
, NTXT ("r"));
1745 if (!dbeSession
->is_interactive ())
1747 m
= new Emsg (CMSG_COMMENT
, NTXT ("Notes:"));
1753 char str
[MAXPATHLEN
];
1754 char *e
= fgets (str
, ((int) sizeof (str
)) - 1, f
);
1757 if (!dbeSession
->is_interactive ())
1759 m
= new Emsg (CMSG_COMMENT
,
1760 "============================================================");
1765 size_t i
= strlen (str
);
1766 if (i
> 0 && str
[i
- 1] == '\n')
1767 // remove trailing nl
1769 m
= new Emsg (CMSG_COMMENT
, str
);
1776 Experiment::save_notes (char* text
, bool handle_file
)
1781 char *fname
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_NOTES_FILE
);
1782 fnotes
= fopen (fname
, NTXT ("w"));
1786 (void) fprintf (fnotes
, NTXT ("%s"), text
);
1790 return 1; // Cannot write file
1793 Emsg
*m
= new Emsg (CMSG_COMMENT
, text
);
1800 Experiment::delete_notes (bool handle_file
)
1804 char *fname
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_NOTES_FILE
);
1805 if (unlink (fname
) != 0)
1808 return 1; // Cannot delete file
1817 Experiment::read_warn_file ()
1819 int local_status
= SUCCESS
;
1821 ExperimentFile
*warnFile
= new ExperimentFile (this, SP_WARN_FILE
);
1822 if (warnFile
== NULL
)
1824 if (!warnFile
->open ())
1829 SAXParserFactory
*factory
= SAXParserFactory::newInstance ();
1830 SAXParser
*saxParser
= factory
->newSAXParser ();
1831 DefaultHandler
*dh
= new ExperimentHandler (this);
1834 saxParser
->parse ((File
*) warnFile
->fh
, dh
);
1836 catch (SAXException
*e
)
1838 // Fatal error in the parser
1840 sb
.sprintf (NTXT ("%s: %s"), SP_WARN_FILE
, e
->getMessage ());
1841 char *str
= sb
.toString ();
1842 Emsg
*m
= new Emsg (CMSG_FATAL
, str
);
1844 local_status
= FAILURE
;
1852 return local_status
;
1856 Experiment::read_log_file ()
1858 if (logFile
== NULL
)
1859 logFile
= new ExperimentFile (this, SP_LOG_FILE
);
1860 if (!logFile
->open ())
1866 SAXParserFactory
*factory
= SAXParserFactory::newInstance ();
1867 SAXParser
*saxParser
= factory
->newSAXParser ();
1868 DefaultHandler
*dh
= new ExperimentHandler (this);
1871 saxParser
->parse ((File
*) logFile
->fh
, dh
);
1873 catch (SAXException
*e
)
1875 // Fatal error in the parser
1878 sb
.sprintf (NTXT ("%s"), e
->getMessage ());
1880 sb
.sprintf (NTXT ("%s: %s"), SP_LOG_FILE
, e
->getMessage ());
1881 char *str
= sb
.toString ();
1882 Emsg
*m
= new Emsg (CMSG_FATAL
, str
);
1888 dbeSession
->register_metric (GTXT ("IPC"), GTXT ("Instructions Per Cycle"),
1889 NTXT ("insts/cycles"));
1890 dbeSession
->register_metric (GTXT ("CPI"), GTXT ("Cycles Per Instruction"),
1891 NTXT ("cycles/insts"));
1892 dbeSession
->register_metric (GTXT ("K_IPC"),
1893 GTXT ("Kernel Instructions Per Cycle"),
1894 NTXT ("K_insts/K_cycles"));
1895 dbeSession
->register_metric (GTXT ("K_CPI"),
1896 GTXT ("Kernel Cycles Per Instruction"),
1897 NTXT ("K_cycles/K_insts"));
1906 ////////////////////////////////////////////////////////////////////////////////
1907 // class Experiment::ExperimentLabelsHandler
1910 class Experiment::ExperimentLabelsHandler
: public DefaultHandler
1914 ExperimentLabelsHandler (Experiment
*_exp
)
1919 ~ExperimentLabelsHandler () { };
1920 void startDocument () { }
1921 void endDocument () { }
1922 void endElement (char * /*uri*/, char * /*localName*/, char * /*qName*/) { }
1923 void characters (char * /*ch*/, int /*start*/, int /*length*/) { }
1924 void ignorableWhitespace (char*, int, int) { }
1925 void error (SAXParseException
* /*e*/) { }
1927 void startElement (char *uri
, char *localName
, char *qName
, Attributes
*attrs
);
1934 return s
? s
: "NULL";
1939 hrtime_t time
, tstamp
;
1943 Experiment::ExperimentLabelsHandler::startElement (char*, char*, char *qName
,
1946 DEBUG_CODE
if (DEBUG_SAXPARSER
) dump_startElement (qName
, attrs
);
1947 if (qName
== NULL
|| strcmp (qName
, NTXT ("id")) != 0)
1949 char *name
= NULL
, *all_times
= NULL
, *comment
= NULL
, *hostName
= NULL
;
1951 // long tm_zone = 0;
1952 hrtime_t startHrtime
= (hrtime_t
) 0;
1953 long long lbl_ts
= 0;
1956 start_tv
.tv_usec
= start_tv
.tv_sec
= 0;
1957 for (int i
= 0, sz
= attrs
? attrs
->getLength () : 0; i
< sz
; i
++)
1959 const char *qn
= attrs
->getQName (i
);
1960 const char *vl
= attrs
->getValue (i
);
1961 if (strcmp (qn
, NTXT ("name")) == 0)
1962 name
= dbe_xml2str (vl
);
1963 else if (strcmp (qn
, NTXT ("cmd")) == 0)
1964 all_times
= dbe_xml2str (vl
);
1965 else if (strcmp (qn
, NTXT ("comment")) == 0)
1966 comment
= dbe_xml2str (vl
);
1967 else if (strcmp (qn
, NTXT ("relative")) == 0)
1968 relative
= atoi (vl
);
1969 else if (strcmp (qn
, NTXT ("hostname")) == 0)
1970 hostName
= dbe_xml2str (vl
);
1971 else if (strcmp (qn
, NTXT ("time")) == 0)
1972 startSec
= atol (vl
);
1973 else if (strcmp (qn
, NTXT ("tstamp")) == 0)
1974 startHrtime
= parseTStamp (vl
);
1975 else if (strcmp (qn
, NTXT ("lbl_ts")) == 0)
1978 lbl_ts
= -parseTStamp (vl
+ 1);
1980 lbl_ts
= parseTStamp (vl
);
1983 if (name
== NULL
|| hostName
== NULL
|| (all_times
== NULL
&& comment
== NULL
))
1991 UserLabel
*lbl
= new UserLabel (name
);
1992 lbl
->comment
= comment
;
1993 lbl
->hostname
= hostName
;
1994 lbl
->start_sec
= startSec
;
1995 lbl
->start_hrtime
= startHrtime
;
1996 exp
->userLabels
->append (lbl
);
1999 lbl
->all_times
= all_times
;
2000 lbl
->start_tv
= start_tv
;
2001 lbl
->relative
= relative
;
2002 if (relative
== UserLabel::REL_TIME
)
2003 lbl
->atime
= lbl_ts
;
2005 { // relative == UserLabel::CUR_TIME
2006 long long delta
= 0;
2007 if (exp
->hostname
&& strcmp (lbl
->hostname
, exp
->hostname
) == 0)
2008 delta
= lbl_ts
+ (lbl
->start_hrtime
- exp
->exp_start_time
);
2010 for (int i
= 0; i
< exp
->userLabels
->size (); i
++)
2012 UserLabel
*firstLbl
= exp
->userLabels
->fetch (i
);
2013 if (strcmp (lbl
->hostname
, firstLbl
->hostname
) == 0)
2015 delta
= lbl_ts
+ (lbl
->start_hrtime
- firstLbl
->start_hrtime
) +
2016 ((long long) (firstLbl
->start_sec
- exp
->start_sec
)) * NANOSEC
;
2020 lbl
->atime
= delta
> 0 ? delta
: 0;
2026 sortUserLabels (const void *a
, const void *b
)
2028 UserLabel
*l1
= *((UserLabel
**) a
);
2029 UserLabel
*l2
= *((UserLabel
**) b
);
2030 int v
= dbe_strcmp (l1
->name
, l2
->name
);
2033 if (l1
->atime
< l2
->atime
)
2035 else if (l1
->atime
> l2
->atime
)
2037 if (l1
->id
< l2
->id
)
2039 else if (l1
->id
> l2
->id
)
2045 append_string (char *s
, char *str
)
2048 return dbe_strdup (str
);
2049 char *new_s
= dbe_sprintf (NTXT ("%s %s"), s
, str
);
2055 Experiment::read_labels_file ()
2057 ExperimentFile
*fp
= new ExperimentFile (this, SP_LABELS_FILE
);
2063 userLabels
= new Vector
<UserLabel
*>();
2064 SAXParserFactory
*factory
= SAXParserFactory::newInstance ();
2065 SAXParser
*saxParser
= factory
->newSAXParser ();
2066 DefaultHandler
*dh
= new ExperimentLabelsHandler (this);
2069 saxParser
->parse ((File
*) fp
->fh
, dh
);
2071 catch (SAXException
*e
)
2073 // Fatal error in the parser
2075 sb
.sprintf (NTXT ("%s: %s"), SP_LABELS_FILE
, e
->getMessage ());
2076 char *str
= sb
.toString ();
2077 Emsg
*m
= new Emsg (CMSG_FATAL
, str
);
2087 userLabels
->sort (sortUserLabels
);
2088 UserLabel::dump ("After sortUserLabels:", userLabels
);
2089 UserLabel
*ulbl
= NULL
;
2090 for (int i
= 0, sz
= userLabels
->size (); i
< sz
; i
++)
2092 UserLabel
*lbl
= userLabels
->fetch (i
);
2094 ulbl
= new UserLabel (lbl
->name
);
2095 else if (dbe_strcmp (lbl
->name
, ulbl
->name
) != 0)
2097 ulbl
->register_user_label (groupId
);
2098 if (ulbl
->expr
== NULL
)
2100 ulbl
= new UserLabel (lbl
->name
);
2104 if (strncmp (lbl
->all_times
, NTXT ("start"), 5) == 0)
2108 ulbl
->start_f
= true;
2109 ulbl
->timeStart
= lbl
->atime
;
2116 ulbl
->all_times
= append_string (ulbl
->all_times
, lbl
->all_times
);
2117 ulbl
->stop_f
= true;
2118 ulbl
->timeStop
= lbl
->atime
;
2122 if (lbl
->comment
!= NULL
)
2123 ulbl
->comment
= append_string (ulbl
->comment
, lbl
->comment
);
2127 ulbl
->register_user_label (groupId
);
2128 if (ulbl
->expr
== NULL
)
2131 Destroy (userLabels
);
2135 Experiment::read_archives ()
2139 char *allocated_str
= NULL
;
2140 char *nm
= get_arch_name ();
2141 DIR *exp_dir
= opendir (nm
);
2142 if (exp_dir
== NULL
)
2144 if (founder_exp
== NULL
)
2146 // Check if the user uses a subexperiment only
2147 nm
= dbe_sprintf (NTXT ("%s/../%s"), expt_name
, SP_ARCHIVES_DIR
);
2148 exp_dir
= opendir (nm
);
2149 if (exp_dir
== NULL
)
2163 int dlen
= sb
.length ();
2164 free (allocated_str
);
2165 archiveMap
= new StringMap
<DbeFile
*>();
2167 struct dirent
*entry
= NULL
;
2168 while ((entry
= readdir (exp_dir
)) != NULL
)
2170 char *dname
= entry
->d_name
;
2172 && (dname
[1] == '\0' || (dname
[1] == '.' && dname
[2] == '\0')))
2173 // skip links to ./ or ../
2175 sb
.setLength (dlen
);
2177 char *fnm
= sb
.toString ();
2178 DbeFile
*df
= new DbeFile (fnm
);
2179 df
->set_location (fnm
);
2180 df
->filetype
|= DbeFile::F_FILE
;
2181 df
->inArchive
= true;
2182 df
->experiment
= this;
2183 archiveMap
->put (dname
, df
);
2190 gen_file_name (const char *packet_name
, const char *src_name
)
2192 char *fnm
, *bname
= get_basename (packet_name
);
2193 if (bname
== packet_name
)
2194 fnm
= dbe_strdup (src_name
);
2196 fnm
= dbe_sprintf ("%.*s%s", (int) (bname
- packet_name
),
2197 packet_name
, src_name
);
2199 // convert "java.lang.Object/Integer.java" => "java/lang/Object/Integer.java"
2200 bname
= get_basename (fnm
);
2201 for (char *s
= fnm
; s
< bname
; s
++)
2208 get_jlass_name (const char *nm
)
2210 // Convert "Ljava/lang/Object;" => "java/lang/Object.class"
2213 size_t len
= strlen (nm
);
2214 if (nm
[len
- 1] == ';')
2215 return dbe_sprintf ("%.*s.class", (int) (len
- 2), nm
+ 1);
2217 return dbe_strdup (nm
);
2221 get_jmodule_name (const char *nm
)
2223 // convert "Ljava/lang/Object;" => "java.lang.Object"
2226 size_t len
= strlen (nm
);
2227 if (nm
[len
- 1] == ';')
2229 char *mname
= dbe_sprintf (NTXT ("%.*s"), (int) (len
- 2), nm
+ 1);
2230 for (char *s
= mname
; *s
; s
++)
2236 return dbe_strdup (nm
);
2240 Experiment::get_j_lo (const char *className
, const char *fileName
)
2242 char *class_name
= get_jlass_name (className
);
2243 Dprintf (DUMP_JCLASS_READER
,
2244 "Experiment::get_j_lo: className='%s' class_name='%s' fileName='%s'\n",
2245 STR (className
), STR (class_name
), STR (fileName
));
2246 LoadObject
*lo
= loadObjMap
->get (class_name
);
2249 lo
= createLoadObject (class_name
, fileName
);
2250 lo
->type
= LoadObject::SEG_TEXT
;
2251 lo
->mtime
= (time_t) 0;
2253 lo
->set_platform (Java
, wsize
);
2254 lo
->dbeFile
->filetype
|= DbeFile::F_FILE
| DbeFile::F_JAVACLASS
;
2256 Dprintf (DUMP_JCLASS_READER
,
2257 "Experiment::get_j_lo: creates '%s' location='%s'\n",
2258 STR (lo
->get_name ()), STR (lo
->dbeFile
->get_location (false)));
2265 Experiment::get_jclass (const char *className
, const char *fileName
)
2267 LoadObject
*lo
= get_j_lo (className
, NULL
);
2268 char *mod_name
= get_jmodule_name (className
);
2269 Module
*mod
= lo
->find_module (mod_name
);
2272 mod
= dbeSession
->createClassFile (mod_name
);
2273 mod
->loadobject
= lo
;
2274 if (strcmp (fileName
, NTXT ("<Unknown>")) != 0)
2275 mod
->set_file_name (gen_file_name (lo
->get_pathname (), fileName
));
2277 mod
->set_file_name (dbe_strdup (fileName
));
2278 lo
->append_module (mod
);
2281 else if (mod
->file_name
&& (strcmp (mod
->file_name
, "<Unknown>") == 0)
2282 && strcmp (fileName
, "<Unknown>") != 0)
2283 mod
->set_file_name (gen_file_name (lo
->get_pathname (), fileName
));
2284 Dprintf (DUMP_JCLASS_READER
,
2285 "Experiment::get_jclass: class_name='%s' mod_name='%s' fileName='%s'\n",
2286 mod
->loadobject
->get_pathname (), mod
->get_name (), mod
->file_name
);
2291 #define ARCH_STRLEN(s) ( ( strlen(s) + 4 ) & ~0x3 )
2294 Experiment::read_java_classes_file ()
2296 char *data_file_name
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_JCLASSES_FILE
);
2297 Data_window
*dwin
= new Data_window (data_file_name
);
2298 free (data_file_name
);
2299 if (dwin
->not_opened ())
2304 dwin
->need_swap_endian
= need_swap_endian
;
2305 jmaps
= new PRBTree ();
2306 jmidHTable
= new DbeCacheMap
<unsigned long long, JMethod
>;
2308 hrtime_t cur_loaded
= 0;
2309 Module
*cur_mod
= NULL
;
2310 for (int64_t offset
= 0;;)
2312 CM_Packet
*cpkt
= (CM_Packet
*) dwin
->bind (offset
, sizeof (CM_Packet
));
2315 uint16_t v16
= (uint16_t) cpkt
->tsize
;
2316 size_t cpktsize
= dwin
->decode (v16
);
2317 cpkt
= (CM_Packet
*) dwin
->bind (offset
, cpktsize
);
2318 if ((cpkt
== NULL
) || (cpktsize
== 0))
2320 char *buf
= dbe_sprintf (GTXT ("archive file malformed %s"),
2322 errorq
->append (new Emsg (CMSG_ERROR
, buf
));
2326 v16
= (uint16_t) cpkt
->type
;
2327 v16
= dwin
->decode (v16
);
2332 ARCH_jclass
*ajcl
= (ARCH_jclass
*) cpkt
;
2333 uint64_t class_id
= dwin
->decode (ajcl
->class_id
);
2334 char *className
= ((char*) ajcl
) + sizeof (*ajcl
);
2335 char *fileName
= className
+ ARCH_STRLEN (className
);
2336 Dprintf (DUMP_JCLASS_READER
,
2337 "read_java_classes_file: ARCH_JCLASS(Ox%x)"
2338 "class_id=Ox%llx className='%s' fileName='%s' \n",
2339 (int) v16
, (long long) class_id
, className
, fileName
);
2341 if (*className
== 'L')
2342 { // Old libcollector generated '[' (one array dimension).
2343 cur_mod
= get_jclass (className
, fileName
);
2344 cur_loaded
= dwin
->decode (ajcl
->tstamp
);
2345 jmaps
->insert (class_id
, cur_loaded
, cur_mod
);
2349 case ARCH_JCLASS_LOCATION
:
2351 ARCH_jclass_location
*ajcl
= (ARCH_jclass_location
*) cpkt
;
2352 uint64_t class_id
= dwin
->decode (ajcl
->class_id
);
2353 char *className
= ((char*) ajcl
) + sizeof (*ajcl
);
2354 char *fileName
= className
+ ARCH_STRLEN (className
);
2355 Dprintf (DUMP_JCLASS_READER
,
2356 "read_java_classes_file: ARCH_JCLASS_LOCATION(Ox%x)"
2357 "class_id=Ox%llx className='%s' fileName='%s' \n",
2358 (int) v16
, (long long) class_id
, className
, fileName
);
2359 get_j_lo (className
, fileName
);
2364 if (cur_mod
== NULL
)
2366 ARCH_jmethod
*ajmt
= (ARCH_jmethod
*) cpkt
;
2367 uint64_t method_id
= dwin
->decode (ajmt
->method_id
);
2368 char *s_name
= ((char*) ajmt
) + sizeof (*ajmt
);
2369 char *s_signature
= s_name
+ ARCH_STRLEN (s_name
);
2370 char *fullname
= dbe_sprintf ("%s.%s", cur_mod
->get_name (), s_name
);
2371 Dprintf (DUMP_JCLASS_READER
,
2372 "read_java_classes_file: ARCH_JMETHOD(Ox%x) "
2373 "method_id=Ox%llx name='%s' signature='%s' fullname='%s'\n",
2374 (int) v16
, (long long) method_id
, s_name
,
2375 s_signature
, fullname
);
2376 JMethod
*jmthd
= cur_mod
->find_jmethod (fullname
, s_signature
);
2379 jmthd
= dbeSession
->createJMethod ();
2380 jmthd
->size
= (unsigned) - 1; // unknown until later (maybe)
2381 jmthd
->module
= cur_mod
;
2382 jmthd
->set_signature (s_signature
);
2383 jmthd
->set_name (fullname
);
2384 cur_mod
->functions
->append (jmthd
);
2385 cur_mod
->loadobject
->functions
->append (jmthd
);
2386 Dprintf (DUMP_JCLASS_READER
,
2387 "read_java_classes_file: ARCH_JMETHOD CREATE fullname=%s\n",
2390 jmaps
->insert (method_id
, cur_loaded
, jmthd
);
2395 Dprintf (DUMP_JCLASS_READER
,
2396 "read_java_classes_file: type=Ox%x (%d) cpktsize=%d\n",
2397 (int) v16
, (int) v16
, (int) cpktsize
);
2398 break; // ignore unknown packets
2407 Experiment::read_map_file ()
2409 ExperimentFile
*mapFile
= new ExperimentFile (this, SP_MAP_FILE
);
2410 if (!mapFile
->open ())
2416 SAXParserFactory
*factory
= SAXParserFactory::newInstance ();
2417 SAXParser
*saxParser
= factory
->newSAXParser ();
2418 DefaultHandler
*dh
= new ExperimentHandler (this);
2421 saxParser
->parse ((File
*) mapFile
->fh
, dh
);
2423 catch (SAXException
*e
)
2425 // Fatal error in the parser
2427 sb
.sprintf (NTXT ("%s: %s"), SP_MAP_FILE
, e
->getMessage ());
2428 char *str
= sb
.toString ();
2429 Emsg
*m
= new Emsg (CMSG_FATAL
, str
);
2440 for (int i
= 0, sz
= mrecs
? mrecs
->size () : 0; i
< sz
; i
++)
2442 MapRecord
*mrec
= mrecs
->fetch (i
);
2443 SegMem
*smem
, *sm_lo
, *sm_hi
;
2446 case MapRecord::LOAD
:
2448 smem
->base
= mrec
->base
;
2449 smem
->size
= mrec
->size
;
2450 smem
->load_time
= mrec
->ts
;
2451 smem
->unload_time
= MAX_TIME
;
2452 smem
->obj
= mrec
->obj
;
2453 smem
->set_file_offset (mrec
->foff
);
2454 seg_items
->append (smem
); // add to the master list
2456 // Check if the new segment overlaps other active segments
2457 sm_lo
= (SegMem
*) maps
->locate (smem
->base
, smem
->load_time
);
2458 if (sm_lo
&& sm_lo
->base
+ sm_lo
->size
> smem
->base
)
2460 // check to see if it is a duplicate record: same address and size, and
2461 if ((smem
->base
== sm_lo
->base
) && (smem
->size
== sm_lo
->size
))
2463 // addresses and sizes match, check name
2464 if (strstr (smem
->obj
->get_name (), sm_lo
->obj
->get_name ()) != NULL
2465 || strstr (sm_lo
->obj
->get_name (), smem
->obj
->get_name ()) != NULL
)
2466 // this is a duplicate; just move on the the next map record
2469 GTXT ("*** Warning: Segment `%s' loaded with same address, size as `%s' [0x%llx-0x%llx]\n"),
2470 smem
->obj
->get_name (), sm_lo
->obj
->get_name (),
2471 sm_lo
->base
, sm_lo
->base
+ sm_lo
->size
);
2474 // Not a duplicate; implicitly unload the old one
2475 // Note: implicit unloading causes high <Unknown>
2476 // when such overlapping is bogus
2478 sb
.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"),
2479 smem
->obj
->get_name (), smem
->base
, smem
->base
+ smem
->size
,
2480 sm_lo
->obj
->get_name (), sm_lo
->base
, sm_lo
->base
+ sm_lo
->size
);
2481 warnq
->append (new Emsg (CMSG_WARN
, sb
));
2484 // now look for other segments with which this might overlap
2485 sm_hi
= (SegMem
*) maps
->locate_up (smem
->base
, smem
->load_time
);
2486 while (sm_hi
&& sm_hi
->base
< smem
->base
+ smem
->size
)
2489 // Note: implicit unloading causes high <Unknown> when such overlapping is bogus
2490 // maps->remove( sm_hi->base, smem->load_time );
2492 sb
.sprintf (GTXT ("*** Warning: Segment %s [0x%llx-0x%llx] overlaps %s [0x%llx-0x%llx], which has been implicitly unloaded"),
2493 smem
->obj
->get_name (), smem
->base
,
2494 smem
->base
+ smem
->size
, sm_hi
->obj
->get_name (),
2495 sm_hi
->base
, sm_hi
->base
+ sm_hi
->size
);
2496 warnq
->append (new Emsg (CMSG_WARN
, sb
));
2497 sm_hi
= (SegMem
*) maps
->locate_up (sm_hi
->base
+ sm_hi
->size
,
2501 maps
->insert (smem
->base
, smem
->load_time
, smem
);
2503 case MapRecord::UNLOAD
:
2504 smem
= (SegMem
*) maps
->locate (mrec
->base
, mrec
->ts
);
2505 if (smem
&& smem
->base
== mrec
->base
)
2507 smem
->unload_time
= mrec
->ts
;
2508 maps
->remove (mrec
->base
, mrec
->ts
);
2515 // See if there are comments or warnings for a load object;
2516 // if so, queue them to Experiment
2517 for (long i
= 0, sz
= loadObjs
? loadObjs
->size () : 0; i
< sz
; i
++)
2519 LoadObject
*lo
= loadObjs
->get (i
);
2520 for (Emsg
*m
= lo
->fetch_warnings (); m
; m
= m
->next
)
2521 warnq
->append (m
->get_warn (), m
->get_msg ());
2522 for (Emsg
*m
= lo
->fetch_comments (); m
; m
= m
->next
)
2523 commentq
->append (m
->get_warn (), m
->get_msg ());
2528 Experiment::read_frameinfo_file ()
2531 char *base_name
= get_basename (expt_name
);
2532 char *msg
= dbe_sprintf (GTXT ("Loading CallStack Data: %s"), base_name
);
2533 read_data_file ("data." SP_FRINFO_FILE
, msg
);
2535 frmpckts
->sort (frUidCmp
);
2536 uidnodes
->sort (uidNodeCmp
);
2540 Experiment::read_omp_preg ()
2542 // Parallel region descriptions
2543 DataDescriptor
*pregDdscr
= getDataDescriptor (DATA_OMP4
);
2544 if (pregDdscr
== NULL
)
2546 DataView
*pregData
= pregDdscr
->createView ();
2547 pregData
->sort (PROP_CPRID
); // omptrace PROP_CPRID
2549 // OpenMP enter parreg events
2550 DataDescriptor
*dDscr
= getDataDescriptor (DATA_OMP2
);
2551 if (dDscr
== NULL
|| dDscr
->getSize () == 0)
2557 char *idxname
= NTXT ("OMP_preg");
2558 delete dbeSession
->indxobj_define (idxname
, GTXT ("OpenMP Parallel Region"),
2559 NTXT ("CPRID"), NULL
, NULL
);
2560 int idxtype
= dbeSession
->findIndexSpaceByName (idxname
);
2568 // Pre-create parallel region with id == 0
2569 Histable
*preg0
= dbeSession
->createIndexObject (idxtype
, (int64_t) 0);
2570 preg0
->set_name (dbe_strdup (GTXT ("Implicit OpenMP Parallel Region")));
2572 // Take care of the progress bar
2573 char *msg
= dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2574 get_basename (expt_name
));
2575 theApplication
->set_progress (0, msg
);
2577 long deltaReport
= 1000;
2578 long nextReport
= 0;
2579 long errors_found
= 0;
2580 Vector
<Histable
*> pregs
;
2582 long size
= dDscr
->getSize ();
2583 for (long i
= 0; i
< size
; ++i
)
2585 if (i
== nextReport
)
2587 int percent
= (int) (i
* 100 / size
);
2589 theApplication
->set_progress (percent
, NULL
);
2590 nextReport
+= deltaReport
;
2593 uint32_t thrid
= dDscr
->getIntValue (PROP_THRID
, i
);
2594 hrtime_t tstamp
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
2595 uint64_t cprid
= dDscr
->getLongValue (PROP_CPRID
, i
); // omptrace CPRID
2596 mapPRid
->put (thrid
, tstamp
, cprid
);
2600 * We will use 2 pointers to make sure there is no loop.
2601 * First pointer "curpreg" goes to the next element,
2602 * second pointer "curpreg_loop_control" goes to the next->next element.
2603 * If these pointers have the same value - there is a loop.
2605 uint64_t curpreg_loop_control
= cprid
;
2606 Datum tval_loop_control
;
2607 if (curpreg_loop_control
!= 0)
2609 tval_loop_control
.setUINT64 (curpreg_loop_control
);
2610 long idx
= pregData
->getIdxByVals (&tval_loop_control
, DataView::REL_EQ
);
2612 curpreg_loop_control
= 0;
2614 curpreg_loop_control
= pregData
->getLongValue (PROP_PPRID
, idx
);
2616 for (uint64_t curpreg
= cprid
; curpreg
!= 0;)
2618 Histable
*val
= NULL
;
2620 tval
.setUINT64 (curpreg
);
2621 long idx
= pregData
->getIdxByVals (&tval
, DataView::REL_EQ
);
2625 * Check if there is a loop
2627 if (0 != curpreg_loop_control
)
2629 if (curpreg
== curpreg_loop_control
)
2632 if (1 == errors_found
)
2634 Emsg
*m
= new Emsg (CMSG_WARN
, GTXT ("*** Warning: circular links in OMP regions; data may not be correct."));
2640 uint64_t pragmapc
= pregData
->getLongValue (PROP_PRPC
, idx
);
2641 DbeInstr
*instr
= map_Vaddr_to_PC (pragmapc
, tstamp
);
2647 DbeLine
*dbeline
= (DbeLine
*) instr
->convertto (Histable::LINE
);
2648 if (dbeline
->lineno
> 0)
2650 if (instr
->func
->usrfunc
)
2651 dbeline
= dbeline
->sourceFile
->find_dbeline
2652 (instr
->func
->usrfunc
, dbeline
->lineno
);
2653 dbeline
->set_flag (DbeLine::OMPPRAGMA
);
2656 val
= dbeSession
->createIndexObject (idxtype
, val
);
2659 curpreg
= pregData
->getLongValue (PROP_PPRID
, idx
);
2661 * Update curpreg_loop_control
2663 if (0 != curpreg_loop_control
)
2665 tval_loop_control
.setUINT64 (curpreg_loop_control
);
2666 idx
= pregData
->getIdxByVals
2667 (&tval_loop_control
, DataView::REL_EQ
);
2669 curpreg_loop_control
= 0;
2672 curpreg_loop_control
= pregData
->getLongValue
2674 tval_loop_control
.setUINT64 (curpreg_loop_control
);
2675 idx
= pregData
->getIdxByVals
2676 (&tval_loop_control
, DataView::REL_EQ
);
2678 curpreg_loop_control
= 0;
2680 curpreg_loop_control
= pregData
->getLongValue
2685 pregs
.append (preg0
);
2686 void *prstack
= cstack
->add_stack (&pregs
);
2687 mapPReg
->put (thrid
, tstamp
, prstack
);
2689 theApplication
->set_progress (0, NTXT (""));
2694 Experiment::read_omp_task ()
2697 DataDescriptor
*taskDataDdscr
= getDataDescriptor (DATA_OMP5
);
2698 if (taskDataDdscr
== NULL
)
2701 //7035272: previously, DataView was global; now it's local...is this OK?
2702 DataView
*taskData
= taskDataDdscr
->createView ();
2703 taskData
->sort (PROP_TSKID
); // omptrace PROP_TSKID
2705 // OpenMP enter task events
2706 DataDescriptor
*dDscr
= getDataDescriptor (DATA_OMP3
);
2707 if (dDscr
== NULL
|| dDscr
->getSize () == 0)
2713 char *idxname
= NTXT ("OMP_task");
2714 // delete a possible error message. Ugly.
2715 delete dbeSession
->indxobj_define (idxname
, GTXT ("OpenMP Task"), NTXT ("TSKID"), NULL
, NULL
);
2716 int idxtype
= dbeSession
->findIndexSpaceByName (idxname
);
2724 // Pre-create task with id == 0
2725 Histable
*task0
= dbeSession
->createIndexObject (idxtype
, (int64_t) 0);
2726 task0
->set_name (dbe_strdup (GTXT ("OpenMP Task from Implicit Parallel Region")));
2728 // Take care of the progress bar
2729 char *msg
= dbe_sprintf (GTXT ("Processing OpenMP Task Data: %s"), get_basename (expt_name
));
2730 theApplication
->set_progress (0, msg
);
2732 long deltaReport
= 1000;
2733 long nextReport
= 0;
2735 Vector
<Histable
*> tasks
;
2736 long size
= dDscr
->getSize ();
2737 long errors_found
= 0;
2738 for (long i
= 0; i
< size
; ++i
)
2740 if (i
== nextReport
)
2742 int percent
= (int) (i
* 100 / size
);
2744 theApplication
->set_progress (percent
, NULL
);
2745 nextReport
+= deltaReport
;
2748 uint32_t thrid
= dDscr
->getIntValue (PROP_THRID
, i
);
2749 hrtime_t tstamp
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
2750 uint64_t tskid
= dDscr
->getLongValue (PROP_TSKID
, i
); //omptrace TSKID
2753 * We will use 2 pointers to make sure there is no loop.
2754 * First pointer "curtsk" goes to the next element,
2755 * second pointer "curtsk_loop_control" goes to the next->next element.
2756 * If these pointers have the same value - there is a loop.
2758 uint64_t curtsk_loop_control
= tskid
;
2759 Datum tval_loop_control
;
2760 if (curtsk_loop_control
!= 0)
2762 tval_loop_control
.setUINT64 (curtsk_loop_control
);
2763 long idx
= taskData
->getIdxByVals (&tval_loop_control
, DataView::REL_EQ
);
2765 curtsk_loop_control
= 0;
2767 curtsk_loop_control
= taskData
->getLongValue (PROP_PTSKID
, idx
);
2769 for (uint64_t curtsk
= tskid
; curtsk
!= 0;)
2771 Histable
*val
= NULL
;
2774 tval
.setUINT64 (curtsk
);
2775 long idx
= taskData
->getIdxByVals (&tval
, DataView::REL_EQ
);
2779 * Check if there is a loop
2781 if (0 != curtsk_loop_control
)
2783 if (curtsk
== curtsk_loop_control
)
2786 if (1 == errors_found
)
2788 Emsg
*m
= new Emsg (CMSG_WARN
, GTXT ("*** Warning: circular links in OMP tasks; data may not be correct."));
2794 uint64_t pragmapc
= taskData
->getLongValue (PROP_PRPC
, idx
);
2795 DbeInstr
*instr
= map_Vaddr_to_PC (pragmapc
, tstamp
);
2799 DbeLine
*dbeline
= (DbeLine
*) instr
->convertto (Histable::LINE
);
2800 if (dbeline
->lineno
> 0)
2802 if (instr
->func
->usrfunc
)
2803 dbeline
= dbeline
->sourceFile
->find_dbeline
2804 (instr
->func
->usrfunc
, dbeline
->lineno
);
2805 dbeline
->set_flag (DbeLine::OMPPRAGMA
);
2808 val
= dbeSession
->createIndexObject (idxtype
, val
);
2811 curtsk
= taskData
->getLongValue (PROP_PTSKID
, idx
);
2813 * Update curtsk_loop_control
2815 if (0 != curtsk_loop_control
)
2817 tval_loop_control
.setUINT64 (curtsk_loop_control
);
2818 idx
= taskData
->getIdxByVals (&tval_loop_control
, DataView::REL_EQ
);
2820 curtsk_loop_control
= 0;
2823 curtsk_loop_control
= taskData
->getLongValue (PROP_PTSKID
, idx
);
2824 tval_loop_control
.setUINT64 (curtsk_loop_control
);
2825 idx
= taskData
->getIdxByVals (&tval_loop_control
,
2828 curtsk_loop_control
= 0;
2830 curtsk_loop_control
= taskData
->getLongValue (PROP_PTSKID
,
2835 tasks
.append (task0
);
2836 void *tskstack
= cstack
->add_stack (&tasks
);
2837 mapTask
->put (thrid
, tstamp
, tskstack
);
2839 theApplication
->set_progress (0, NTXT (""));
2844 Experiment::read_omp_file ()
2846 // DATA_OMP2 table is common between OpenMP 2.5 and 3.0 profiling
2847 DataDescriptor
*dDscr
= getDataDescriptor (DATA_OMP2
);
2850 if (dDscr
->getSize () == 0)
2852 char *base_name
= get_basename (expt_name
);
2853 char *msg
= dbe_sprintf (GTXT ("Loading OpenMP Data: %s"), base_name
);
2854 read_data_file (SP_OMPTRACE_FILE
, msg
);
2857 // OpenMP fork events
2858 dDscr
= getDataDescriptor (DATA_OMP
);
2859 long sz
= dDscr
->getSize ();
2863 msg
= dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2865 theApplication
->set_progress (0, msg
);
2867 long deltaReport
= 5000;
2868 long nextReport
= 0;
2869 for (int i
= 0; i
< sz
; ++i
)
2871 if (i
== nextReport
)
2873 int percent
= (int) (i
* 100 / sz
);
2875 theApplication
->set_progress (percent
, NULL
);
2876 nextReport
+= deltaReport
;
2878 uint32_t thrid
= dDscr
->getIntValue (PROP_THRID
, i
);
2879 hrtime_t tstamp
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
2880 uint64_t cprid
= dDscr
->getLongValue (PROP_CPRID
, i
); //omptrace
2881 mapPRid
->put (thrid
, tstamp
, cprid
);
2883 theApplication
->set_progress (0, NTXT (""));
2886 openMPdata
= dDscr
->createView ();
2887 openMPdata
->sort (PROP_CPRID
); // omptrace PROP_CPRID
2889 // thread enters parreg events
2890 dDscr
= getDataDescriptor (DATA_OMP2
);
2891 sz
= dDscr
->getSize ();
2894 msg
= dbe_sprintf (GTXT ("Processing OpenMP Parallel Region Data: %s"),
2896 theApplication
->set_progress (0, msg
);
2901 for (int i
= 0; i
< sz
; ++i
)
2903 if (i
== nextReport
)
2905 int percent
= (int) (i
* 100 / sz
);
2907 theApplication
->set_progress (percent
, NULL
);
2908 nextReport
+= deltaReport
;
2910 uint32_t thrid
= dDscr
->getIntValue (PROP_THRID
, i
);
2911 hrtime_t tstamp
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
2912 uint64_t cprid
= dDscr
->getLongValue (PROP_CPRID
, i
); //omptrace
2913 mapPRid
->put (thrid
, tstamp
, cprid
);
2915 theApplication
->set_progress (0, NTXT (""));
2922 if (ompavail
&& coll_params
.profile_mode
)
2924 dbeSession
->status_ompavail
= 1;
2925 register_metric (Metric::OMP_WORK
);
2926 register_metric (Metric::OMP_WAIT
);
2927 register_metric (Metric::OMP_OVHD
);
2928 if (coll_params
.lms_magic_id
== LMS_MAGIC_ID_SOLARIS
)
2929 register_metric (Metric::OMP_MASTER_THREAD
);
2935 Experiment::read_ifreq_file ()
2937 char *fname
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, SP_IFREQ_FILE
);
2938 FILE *f
= fopen (fname
, NTXT ("r"));
2946 ifreqq
= new Emsgqueue (NTXT ("ifreqq"));
2951 char str
[MAXPATHLEN
];
2952 char *e
= fgets (str
, ((int) sizeof (str
)) - 1, f
);
2955 // end the list from the experiment
2956 m
= new Emsg (CMSG_COMMENT
,
2957 GTXT ("============================================================"));
2962 size_t i
= strlen (str
);
2963 if (i
> 0 && str
[i
- 1] == '\n')
2964 // remove trailing nl
2967 m
= new Emsg (CMSG_COMMENT
, str
);
2974 Experiment::getBaseFounder ()
2978 Experiment
*founder
= this;
2979 Experiment
*parent
= founder
->founder_exp
;
2983 parent
= founder
->founder_exp
;
2985 baseFounder
= founder
;
2990 Experiment::getRelativeStartTime ()
2992 if (exp_rel_start_time_set
)
2993 return exp_rel_start_time
;
2994 Experiment
*founder
= getBaseFounder ();
2995 hrtime_t child_start
= this->getStartTime ();
2996 hrtime_t founder_start
= founder
->getStartTime ();
2997 exp_rel_start_time
= child_start
- founder_start
;
2998 if (child_start
== 0 && founder_start
)
2999 exp_rel_start_time
= 0; // when descendents have incomplete log.xml
3000 exp_rel_start_time_set
= true;
3001 return exp_rel_start_time
;
3005 Experiment::get_raw_events (int data_id
)
3007 DataDescriptor
*dDscr
;
3011 dDscr
= get_profile_events ();
3014 dDscr
= get_sync_events ();
3017 dDscr
= get_hwc_events ();
3020 dDscr
= get_heap_events ();
3023 dDscr
= get_heapsz_events ();
3026 dDscr
= get_iotrace_events ();
3029 dDscr
= get_race_events ();
3032 dDscr
= get_deadlock_events ();
3035 dDscr
= get_sample_events ();
3038 dDscr
= get_gc_events ();
3048 Experiment::base_data_id (int data_id
)
3053 return DATA_HEAP
; // DATA_HEAPSZ DataView is based on DATA_HEAP's DataView
3061 Experiment::create_derived_data_view (int data_id
, DataView
*dview
)
3063 // dview contains filtered packets
3067 return create_heapsz_data_view (dview
);
3075 Experiment::get_profile_events ()
3077 DataDescriptor
*dDscr
= getDataDescriptor (DATA_CLOCK
);
3080 if (dDscr
->getSize () == 0)
3082 char *base_name
= get_basename (expt_name
);
3083 char *msg
= dbe_sprintf (GTXT ("Loading Profile Data: %s"), base_name
);
3084 read_data_file (SP_PROFILE_FILE
, msg
);
3086 add_evt_time_to_profile_events (dDscr
);
3087 resolve_frame_info (dDscr
);
3089 else if (!dDscr
->isResolveFrInfoDone ())
3090 resolve_frame_info (dDscr
);
3095 Experiment::add_evt_time_to_profile_events (DataDescriptor
*dDscr
)
3097 if (coll_params
.lms_magic_id
!= LMS_MAGIC_ID_SOLARIS
)
3100 DataView
*dview
= dDscr
->createView ();
3101 dview
->sort (PROP_THRID
, PROP_TSTAMP
);
3103 // add PROP_EVT_TIME
3104 PropDescr
* tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, "EVT_TIME");
3105 tmp_propDscr
->uname
= dbe_strdup (GTXT ("Event duration"));
3106 tmp_propDscr
->vtype
= TYPE_INT64
;
3107 dDscr
->addProperty (tmp_propDscr
);
3109 long sz
= dview
->getSize ();
3110 long long ptimer_usec
= get_params ()->ptimer_usec
;
3111 for (long i
= 0; i
< sz
; i
++)
3116 hrtime_t this_tstamp
= dview
->getLongValue (PROP_TSTAMP
, i
);
3117 long this_thrid
= dview
->getLongValue (PROP_THRID
, i
);
3118 for (jj
= i
+ 1; jj
< sz
; jj
++)
3120 hrtime_t tmp_tstamp
= dview
->getLongValue (PROP_TSTAMP
, jj
);
3121 if (tmp_tstamp
!= this_tstamp
)
3123 long tmp_thrid
= dview
->getLongValue (PROP_THRID
, jj
);
3124 if (tmp_thrid
!= this_thrid
)
3131 for (jj
= i
; jj
< next_sample
; jj
++)
3132 nticks
+= dview
->getLongValue (PROP_NTICK
, jj
);
3134 continue; // no duration
3137 hrtime_t duration
= ptimer_usec
* 1000LL * nticks
; // nanoseconds
3138 for (jj
= i
; jj
< next_sample
; jj
++)
3139 dview
->setValue (PROP_EVT_TIME
, jj
, duration
);
3146 Experiment::get_sync_events ()
3148 DataDescriptor
*dDscr
= getDataDescriptor (DATA_SYNCH
);
3151 if (dDscr
->getSize () > 0)
3156 char *base_name
= get_basename (expt_name
);
3157 char *msg
= dbe_sprintf (GTXT ("Loading Synctrace Data: %s"), base_name
);
3158 read_data_file (SP_SYNCTRACE_FILE
, msg
);
3160 resolve_frame_info (dDscr
);
3163 // check for PROP_EVT_TIME
3164 PropDescr
*tmp_propDscr
= dDscr
->getProp (PROP_EVT_TIME
);
3168 // add PROP_EVT_TIME
3169 tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, "EVT_TIME");
3170 tmp_propDscr
->uname
= dbe_strdup (GTXT ("Event duration"));
3171 tmp_propDscr
->vtype
= TYPE_INT64
;
3172 dDscr
->addProperty (tmp_propDscr
);
3174 long sz
= dDscr
->getSize ();
3175 for (long i
= 0; i
< sz
; i
++)
3177 uint64_t event_duration
= dDscr
->getLongValue (PROP_TSTAMP
, i
);
3178 event_duration
-= dDscr
->getLongValue (PROP_SRQST
, i
);
3179 dDscr
->setValue (PROP_EVT_TIME
, i
, event_duration
);
3185 Experiment::get_hwc_events ()
3187 DataDescriptor
*dDscr
= getDataDescriptor (DATA_HWC
);
3190 if (dDscr
->getSize () == 0)
3192 char *base_name
= get_basename (expt_name
);
3193 char *msg
= dbe_sprintf (GTXT ("Loading HW Profile Data: %s"), base_name
);
3195 // clear HWC event stats
3198 read_data_file (SP_HWCNTR_FILE
, msg
);
3200 resolve_frame_info (dDscr
);
3202 // describe the HW counters in PropDescr
3203 PropDescr
*prop
= dDscr
->getProp (PROP_HWCTAG
);
3206 Collection_params
*cparam
= get_params ();
3207 if (cparam
->hw_mode
!= 0)
3208 for (int aux
= 0; aux
< MAX_HWCOUNT
; aux
++)
3209 if (cparam
->hw_aux_name
[aux
])
3211 const char* cmdname
= cparam
->hw_aux_name
[aux
];
3212 const char* uname
= cparam
->hw_username
[aux
];
3213 prop
->addState (aux
, cmdname
, uname
);
3219 double dserrrate
= 100.0 * ((double) dsnoxhwcevents
) / ((double) dsevents
);
3220 if ((dsevents
> 0) && (dserrrate
> 10.0))
3222 // warn the user that rate is high
3224 if (dbeSession
->check_ignore_no_xhwcprof ())
3226 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"),
3227 base_name
, dserrrate
, (long long) dsnoxhwcevents
,
3228 (long long) dsevents
);
3231 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"),
3232 base_name
, dserrrate
, (long long) dsnoxhwcevents
,
3233 (long long) dsevents
);
3234 errorq
->append (new Emsg (CMSG_WARN
, sb
));
3237 // see if we've scanned the data
3238 if (hwc_scanned
== 0)
3240 // no, scan the packets to see how many are bogus, or represent lost interrupts
3243 // loop over the packets, counting the bad ones
3244 if (hwc_bogus
!= 0 || hwc_lost_int
!= 0)
3246 // hwc counter data had bogus packets and/or packets reflecting lost interrupts
3247 double bogus_rate
= 100. * (double) hwc_bogus
/ (double) hwc_cnt
;
3248 if (bogus_rate
> 5.)
3252 GTXT ("WARNING: Too many invalid HW counter profile events (%ld/%ld = %3.2f%%) in experiment %d (`%s'); data may be unreliable"),
3253 (long) hwc_bogus
, (long) hwc_cnt
, bogus_rate
,
3254 (int) userExpId
, base_name
);
3255 Emsg
*m
= new Emsg (CMSG_WARN
, sb
);
3266 Experiment::get_iotrace_events ()
3268 DataDescriptor
*dDscr
= getDataDescriptor (DATA_IOTRACE
);
3272 if (dDscr
->getSize () > 0)
3275 char *base_name
= get_basename (expt_name
);
3276 char *msg
= dbe_sprintf (GTXT ("Loading IO Trace Data: %s"), base_name
);
3277 read_data_file (SP_IOTRACE_FILE
, msg
);
3280 if (dDscr
->getSize () == 0)
3282 resolve_frame_info (dDscr
);
3284 // check for PROP_EVT_TIME
3285 PropDescr
*tmp_propDscr
= dDscr
->getProp (PROP_EVT_TIME
);
3289 // add PROP_EVT_TIME
3290 tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, "EVT_TIME");
3291 tmp_propDscr
->uname
= dbe_strdup (GTXT ("Event duration"));
3292 tmp_propDscr
->vtype
= TYPE_INT64
;
3293 dDscr
->addProperty (tmp_propDscr
);
3296 tmp_propDscr
= new PropDescr (PROP_IOVFD
, "IOVFD");
3297 tmp_propDscr
->uname
= dbe_strdup (GTXT ("Virtual File Descriptor"));
3298 tmp_propDscr
->vtype
= TYPE_INT64
;
3299 dDscr
->addProperty (tmp_propDscr
);
3302 fDataMap
= new DefaultMap
<int64_t, FileData
*>;
3305 vFdMap
= new DefaultMap
<int, int64_t>;
3307 static int64_t virtualFd
= 0;
3311 fData
= fDataMap
->get (VIRTUAL_FD_STDIN
);
3314 fData
= new FileData (STDIN_FILENAME
);
3315 fData
->setVirtualFd (VIRTUAL_FD_STDIN
);
3316 fData
->id
= VIRTUAL_FD_STDIN
;
3317 fData
->setFileDes (STDIN_FD
);
3318 fDataMap
->put (VIRTUAL_FD_STDIN
, fData
);
3319 vFdMap
->put (STDIN_FD
, VIRTUAL_FD_STDIN
);
3322 fData
= fDataMap
->get (VIRTUAL_FD_STDOUT
);
3325 fData
= new FileData (STDOUT_FILENAME
);
3326 fData
->setVirtualFd (VIRTUAL_FD_STDOUT
);
3327 fData
->id
= VIRTUAL_FD_STDOUT
;
3328 fData
->setFileDes (STDOUT_FD
);
3329 fDataMap
->put (VIRTUAL_FD_STDOUT
, fData
);
3330 vFdMap
->put (STDOUT_FD
, VIRTUAL_FD_STDOUT
);
3333 fData
= fDataMap
->get (VIRTUAL_FD_STDERR
);
3336 fData
= new FileData (STDERR_FILENAME
);
3337 fData
->setVirtualFd (VIRTUAL_FD_STDERR
);
3338 fData
->id
= VIRTUAL_FD_STDERR
;
3339 fData
->setFileDes (STDERR_FD
);
3340 fDataMap
->put (VIRTUAL_FD_STDERR
, fData
);
3341 vFdMap
->put (STDERR_FD
, VIRTUAL_FD_STDERR
);
3344 fData
= fDataMap
->get (VIRTUAL_FD_OTHERIO
);
3347 fData
= new FileData (OTHERIO_FILENAME
);
3348 fData
->setVirtualFd (VIRTUAL_FD_OTHERIO
);
3349 fData
->id
= VIRTUAL_FD_OTHERIO
;
3350 fData
->setFileDes (OTHERIO_FD
);
3351 fDataMap
->put (VIRTUAL_FD_OTHERIO
, fData
);
3354 DataView
*dview
= dDscr
->createView ();
3355 dview
->sort (PROP_TSTAMP
);
3356 long sz
= dview
->getSize ();
3357 for (long i
= 0; i
< sz
; i
++)
3359 hrtime_t event_duration
= dview
->getLongValue (PROP_TSTAMP
, i
);
3360 hrtime_t event_start
= dview
->getLongValue (PROP_IORQST
, i
);
3361 if (event_start
> 0)
3362 event_duration
-= event_start
;
3365 dview
->setValue (PROP_EVT_TIME
, i
, event_duration
);
3368 int64_t vFd
= VIRTUAL_FD_NONE
;
3370 int32_t origFd
= -1;
3371 StringBuilder
*sb
= NULL
;
3372 FileData
*fDataOrig
= NULL
;
3373 FileSystem_type fsType
;
3375 IOTrace_type ioType
= (IOTrace_type
) dview
->getIntValue (PROP_IOTYPE
, i
);
3380 case READ_TRACE_ERROR
:
3381 case WRITE_TRACE_ERROR
:
3382 fd
= dview
->getIntValue (PROP_IOFD
, i
);
3383 vFd
= vFdMap
->get (fd
);
3384 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
3385 || (fData
= fDataMap
->get (vFd
)) == NULL
)
3387 fData
= new FileData (UNKNOWNFD_FILENAME
);
3388 fData
->setVirtualFd (virtualFd
);
3389 fData
->setFsType ("N/A");
3390 fData
->setFileDes (fd
);
3391 fDataMap
->put (virtualFd
, fData
);
3392 vFdMap
->put (fd
, virtualFd
);
3396 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3400 sb
= (StringBuilder
*) dview
->getObjValue (PROP_IOFNAME
, i
);
3401 if (sb
!= NULL
&& sb
->length () > 0)
3402 fName
= sb
->toString ();
3403 fd
= dview
->getIntValue (PROP_IOFD
, i
);
3404 origFd
= dview
->getIntValue (PROP_IOOFD
, i
);
3405 fsType
= (FileSystem_type
) dview
->getIntValue (PROP_IOFSTYPE
, i
);
3409 fData
= new FileData (fName
);
3410 fDataMap
->put (virtualFd
, fData
);
3411 vFdMap
->put (fd
, virtualFd
);
3412 fData
->setFileDes (fd
);
3413 fData
->setFsType (fsType
);
3414 fData
->setVirtualFd (virtualFd
);
3418 else if (origFd
> 0)
3420 vFd
= vFdMap
->get (origFd
);
3421 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
)
3424 "*** Error I/O tracing: (open) cannot get the virtual file descriptor, fd=%d origFd=%d\n",
3428 else if ((fDataOrig
= fDataMap
->get (vFd
)) == NULL
)
3431 "*** Error IO tracing: (open) cannot get original FileData object, fd=%d origFd=%d\n",
3437 fName
= fDataOrig
->getFileName ();
3438 fData
= new FileData (fName
);
3439 fData
->setFileDes (fd
);
3440 fData
->setFsType (fDataOrig
->getFsType ());
3441 fData
->setVirtualFd (virtualFd
);
3442 fDataMap
->put (virtualFd
, fData
);
3443 vFdMap
->put (fd
, virtualFd
);
3450 vFd
= vFdMap
->get (fd
);
3451 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
3452 || (fData
= fDataMap
->get (vFd
)) == NULL
)
3454 fData
= new FileData (UNKNOWNFD_FILENAME
);
3455 fData
->setVirtualFd (virtualFd
);
3456 fData
->setFsType ("N/A");
3457 fData
->setFileDes (fd
);
3458 fDataMap
->put (virtualFd
, fData
);
3459 vFdMap
->put (fd
, virtualFd
);
3467 NTXT ("*** Error IO tracing: (open) unknown open IO type, fd=%d origFd=%d\n"), fd
, origFd
);
3471 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3474 case OPEN_TRACE_ERROR
:
3477 sb
= (StringBuilder
*) dview
->getObjValue (PROP_IOFNAME
, i
);
3478 if (sb
!= NULL
&& sb
->length () > 0)
3479 fName
= sb
->toString ();
3480 fd
= dview
->getIntValue (PROP_IOFD
, i
);
3481 origFd
= dview
->getIntValue (PROP_IOOFD
, i
);
3482 fsType
= (FileSystem_type
) dview
->getIntValue (PROP_IOFSTYPE
, i
);
3486 fData
= new FileData (fName
);
3487 fDataMap
->put (virtualFd
, fData
);
3488 fData
->setFileDes (fd
);
3489 fData
->setFsType (fsType
);
3490 fData
->setVirtualFd (virtualFd
);
3494 else if (origFd
> 0)
3496 vFd
= vFdMap
->get (origFd
);
3497 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
)
3500 "*** Error IO tracing: (open error) cannot get the virtual file descriptor, fd=%d origFd=%d\n",
3504 else if ((fDataOrig
= fDataMap
->get (vFd
)) == NULL
)
3507 "*** Error IO tracing: (open error) cannot get original FileData object, fd=%d origFd=%d\n",
3513 fName
= fDataOrig
->getFileName ();
3514 fData
= new FileData (fName
);
3515 fData
->setFileDes (fd
);
3516 fData
->setFsType (fDataOrig
->getFsType ());
3517 fData
->setVirtualFd (virtualFd
);
3518 fDataMap
->put (virtualFd
, fData
);
3524 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3528 case CLOSE_TRACE_ERROR
:
3529 fd
= dview
->getIntValue (PROP_IOFD
, i
);
3530 vFd
= vFdMap
->get (fd
);
3531 if (vFd
== 0 || vFd
== VIRTUAL_FD_NONE
)
3534 "*** Error IO tracing: (close) cannot get the virtual file descriptor, fd=%d\n",
3538 fData
= fDataMap
->get (vFd
);
3542 "*** Error IO tracing: (close) cannot get the FileData object, fd=%d\n",
3547 vFdMap
->put (fd
, VIRTUAL_FD_NONE
);
3548 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3552 case OTHERIO_TRACE_ERROR
:
3553 vFd
= VIRTUAL_FD_OTHERIO
;
3554 fData
= fDataMap
->get (vFd
);
3558 "*** Error IO tracing: (other IO) cannot get the FileData object\n");
3562 dview
->setValue (PROP_IOVFD
, i
, vFd
);
3564 case IOTRACETYPE_LAST
:
3575 Experiment::get_heap_events ()
3577 DataDescriptor
*dDscr
= getDataDescriptor (DATA_HEAP
);
3580 if (dDscr
->getSize () > 0)
3583 char *base_name
= get_basename (expt_name
);
3584 char *msg
= dbe_sprintf (GTXT ("Loading Heap Trace Data: %s"), base_name
);
3585 read_data_file (SP_HEAPTRACE_FILE
, msg
);
3588 if (dDscr
->getSize () == 0)
3590 resolve_frame_info (dDscr
);
3592 // Match FREE to MALLOC
3593 PropDescr
*prop
= new PropDescr (PROP_HLEAKED
, NTXT ("HLEAKED"));
3594 prop
->uname
= dbe_strdup (GTXT ("Bytes Leaked"));
3595 prop
->vtype
= TYPE_UINT64
;
3596 dDscr
->addProperty (prop
);
3598 prop
= new PropDescr (PROP_HMEM_USAGE
, NTXT ("HMEM_USAGE"));
3599 prop
->uname
= dbe_strdup (GTXT ("Heap Memory Usage"));
3600 prop
->vtype
= TYPE_UINT64
;
3601 dDscr
->addProperty (prop
);
3603 prop
= new PropDescr (PROP_HFREED
, NTXT ("HFREED"));
3604 prop
->uname
= dbe_strdup (GTXT ("Bytes Freed"));
3605 prop
->vtype
= TYPE_UINT64
;
3606 dDscr
->addProperty (prop
);
3608 prop
= new PropDescr (PROP_HCUR_ALLOCS
, NTXT ("HCUR_ALLOCS"));
3609 prop
->uname
= dbe_strdup (GTXT ("Net Bytes Allocated"));
3610 prop
->vtype
= TYPE_INT64
;
3611 dDscr
->addProperty (prop
);
3613 prop
= new PropDescr (PROP_HCUR_LEAKS
, NTXT ("HCUR_LEAKS"));
3614 prop
->uname
= dbe_strdup (GTXT ("Net Bytes Leaked"));
3615 prop
->vtype
= TYPE_UINT64
;
3616 dDscr
->addProperty (prop
);
3618 prop
= new PropDescr (PROP_HCUR_NET_ALLOC
, NTXT ("HCUR_NET_ALLOC"));
3619 prop
->vtype
= TYPE_INT64
;
3620 prop
->flags
= DDFLAG_NOSHOW
;
3621 dDscr
->addProperty (prop
);
3623 prop
= new PropDescr (PROP_DDSCR_LNK
, NTXT ("DDSCR_LNK"));
3624 prop
->vtype
= TYPE_UINT64
;
3625 prop
->flags
= DDFLAG_NOSHOW
;
3626 dDscr
->addProperty (prop
);
3628 prop
= new PropDescr (PROP_VOIDP_OBJ
, NTXT ("VOIDP_OBJ"));
3629 prop
->vtype
= TYPE_OBJ
;
3630 prop
->flags
= DDFLAG_NOSHOW
;
3631 dDscr
->addProperty (prop
);
3633 prop
= new PropDescr (PROP_TSTAMP2
, NTXT ("TSTAMP2"));
3634 prop
->uname
= dbe_strdup (GTXT ("End Timestamp (nanoseconds)"));
3635 prop
->vtype
= TYPE_UINT64
;
3636 prop
->flags
= DDFLAG_NOSHOW
;
3637 dDscr
->addProperty (prop
);
3639 DataView
*dview
= dDscr
->createView ();
3640 dview
->sort (PROP_TSTAMP
);
3642 // Keep track of memory usage
3643 Size memoryUsage
= 0;
3645 HeapMap
*heapmap
= new HeapMap ();
3646 long sz
= dview
->getSize ();
3647 for (long i
= 0; i
< sz
; i
++)
3650 Heap_type mtype
= (Heap_type
) dview
->getIntValue (PROP_HTYPE
, i
);
3651 Vaddr vaddr
= dview
->getULongValue (PROP_HVADDR
, i
);
3652 Vaddr ovaddr
= dview
->getULongValue (PROP_HOVADDR
, i
);
3653 Size hsize
= dview
->getULongValue (PROP_HSIZE
, i
);
3654 hrtime_t tstamp
= dview
->getLongValue (PROP_TSTAMP
, i
);
3659 dview
->setValue (PROP_TSTAMP2
, i
, (uint64_t) MAX_TIME
);
3662 dview
->setValue (PROP_HLEAKED
, i
, hsize
);
3663 heapmap
->allocate (vaddr
, i
+ 1);
3665 // Increase heap size
3666 memoryUsage
+= hsize
;
3667 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3674 long idx
= heapmap
->deallocate (vaddr
) - 1;
3677 // Decrease heap size
3678 Size leaked
= dview
->getLongValue (PROP_HLEAKED
, idx
);
3679 memoryUsage
-= leaked
;
3680 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3682 Size alloc
= dview
->getLongValue (PROP_HSIZE
, idx
);
3683 // update allocation
3684 dview
->setValue (PROP_HLEAKED
, idx
, (uint64_t) 0);
3685 dview
->setValue (PROP_TSTAMP2
, idx
, tstamp
);
3686 dview
->setValue (PROP_DDSCR_LNK
, idx
, dview
->getIdByIdx (i
) + 1);
3687 // update this event
3688 dview
->setValue (PROP_HFREED
, i
, alloc
);
3694 dview
->setValue (PROP_TSTAMP2
, i
, (uint64_t) MAX_TIME
);
3697 long idx
= heapmap
->deallocate (ovaddr
) - 1;
3700 // Decrease heap size
3701 Size leaked
= dview
->getLongValue (PROP_HLEAKED
, idx
);
3702 memoryUsage
-= leaked
;
3703 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3705 Size alloc
= dview
->getLongValue (PROP_HSIZE
, idx
);
3706 // update allocation
3707 dview
->setValue (PROP_HLEAKED
, idx
, (uint64_t) 0);
3708 dview
->setValue (PROP_TSTAMP2
, idx
, tstamp
);
3709 dview
->setValue (PROP_DDSCR_LNK
, idx
, dview
->getIdByIdx (i
) + 1);
3710 // update this event
3711 dview
->setValue (PROP_HFREED
, i
, alloc
);
3716 dview
->setValue (PROP_HLEAKED
, i
, hsize
);
3717 heapmap
->allocate (vaddr
, i
+ 1);
3719 // Increase heap size
3720 memoryUsage
+= hsize
;
3721 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3726 // Adjust the size to be multiple of page_size
3727 //hsize = (( hsize - 1 ) / page_size + 1 ) * page_size;
3731 if (mtype
== MMAP_TRACE
)
3733 dview
->setValue (PROP_TSTAMP2
, i
, (uint64_t) MAX_TIME
);
3734 dview
->setValue (PROP_HLEAKED
, i
, hsize
);
3735 list
= heapmap
->mmap (vaddr
, hsize
, i
);
3737 // Increase heap size
3738 memoryUsage
+= hsize
;
3739 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3743 list
= heapmap
->munmap (vaddr
, hsize
);
3745 // Set allocation size to zero
3746 // Note: We're currently reusing PROP_HSIZE to mean allocation size
3747 // If we ever need to save the original HSIZE, we'll need to
3748 // create a new PROP_* to represent event allocation size
3750 // For now, tuck the original size away as HOVADDR
3751 dview
->setValue (PROP_HOVADDR
, i
, (uint64_t) hsize
);
3752 dview
->setValue (PROP_HSIZE
, i
, (uint64_t) 0);
3754 Size total_freed
= 0;
3757 long idx
= list
->val
;
3758 total_freed
+= list
->size
;
3759 Size leaked
= dview
->getLongValue (PROP_HLEAKED
, idx
);
3761 // Decrease heap size
3762 memoryUsage
-= list
->size
;
3763 dview
->setValue (PROP_HMEM_USAGE
, i
, memoryUsage
);
3765 Size leak_update
= leaked
- list
->size
;
3766 // update allocation
3767 dview
->setValue (PROP_HLEAKED
, idx
, leak_update
);
3768 // update allocation's list of frees
3770 UnmapChunk
*copy
= new UnmapChunk
;
3771 heapUnmapEvents
->append (copy
);
3772 copy
->val
= dview
->getIdByIdx (i
);
3773 copy
->size
= list
->size
;
3774 copy
->next
= (UnmapChunk
*) dview
->getObjValue (PROP_VOIDP_OBJ
, idx
);
3775 dview
->setObjValue (PROP_VOIDP_OBJ
, idx
, copy
);
3777 if (leak_update
<= 0)
3778 if (leak_update
== 0)
3779 dview
->setValue (PROP_TSTAMP2
, idx
, tstamp
);
3780 UnmapChunk
*t
= list
;
3784 // update this event
3786 // only need to write value if it is non-zero
3787 dview
->setValue (PROP_HFREED
, i
, total_freed
);
3790 // ignoring HEAPTYPE_LAST, which will never be recorded
3802 Experiment::get_heapsz_events ()
3804 DataDescriptor
*dDscr
= getDataDescriptor (DATA_HEAPSZ
);
3807 dDscr
= get_heap_events (); // derived from DATA_HEAP
3810 dDscr
= newDataDescriptor (DATA_HEAPSZ
, 0, dDscr
);
3815 update_heapsz_packet (std::set
<long> &pkt_id_set
, DataView
*dview
,
3816 long alloc_pkt_id
, int64_t net_alloc
, uint64_t leaks
)
3818 // pkt_id_set: set is updated to include packet
3819 // alloc_pkt_id: data descriptor id (NOT dview idx)
3820 // net_alloc: adjustment to net allocation for this packet (note: signed value)
3821 // leaks: leak bytes to attribute to alloc_pkt_id
3822 std::pair
< std::set
<long>::iterator
, bool> ret
;
3823 ret
= pkt_id_set
.insert (alloc_pkt_id
); // add to set
3824 bool new_to_set
= ret
.second
; // was not in set
3827 // Has been seen before, update values
3828 net_alloc
+= dview
->getDataDescriptorValue (PROP_HCUR_NET_ALLOC
, alloc_pkt_id
);
3831 uint64_t old
= dview
->getDataDescriptorValue (PROP_HCUR_LEAKS
, alloc_pkt_id
);
3836 dview
->setDataDescriptorValue (PROP_HCUR_NET_ALLOC
, alloc_pkt_id
, net_alloc
);
3837 dview
->setDataDescriptorValue (PROP_HCUR_LEAKS
, alloc_pkt_id
, leaks
);
3841 Experiment::create_heapsz_data_view (DataView
*heap_dview
)
3843 // heap_dview has DATA_HEAP _filtered_ packets.
3844 // This creates, populates, and returns DATA_HEAPSZ DataView
3845 DataDescriptor
*dDscr
= get_heapsz_events ();
3848 std::set
<long> pkt_id_set
;
3849 DataView
*dview
= heap_dview
;
3850 long sz
= dview
->getSize ();
3851 for (long i
= 0; i
< sz
; i
++)
3853 int64_t hsize
= (int64_t) dview
->getULongValue (PROP_HSIZE
, i
);
3854 uint64_t leaks
= dview
->getULongValue (PROP_HLEAKED
, i
);
3855 long alloc_pkt_id
= dview
->getIdByIdx (i
);
3856 update_heapsz_packet (pkt_id_set
, dview
, alloc_pkt_id
, hsize
, leaks
);
3859 UnmapChunk
*mmap_frees
= (UnmapChunk
*) dview
->getObjValue (PROP_VOIDP_OBJ
, i
); // mmap metadata
3862 // mmap: all frees associated with this packet
3865 long free_pkt_id
= mmap_frees
->val
;
3866 int64_t free_sz
= mmap_frees
->size
;
3867 update_heapsz_packet (pkt_id_set
, dview
, free_pkt_id
, -free_sz
, 0);
3868 mmap_frees
= mmap_frees
->next
;
3873 // malloc: check for associated free
3874 long free_pkt_id
= dview
->getLongValue (PROP_DDSCR_LNK
, i
) - 1;
3875 if (free_pkt_id
>= 0)
3876 update_heapsz_packet (pkt_id_set
, dview
, free_pkt_id
, -hsize
, 0);
3880 // create a new DataView based on the filtered-in and associated free events
3881 std::set
<long>::iterator it
;
3882 DataView
*heapsz_dview
= dDscr
->createExtManagedView ();
3883 for (it
= pkt_id_set
.begin (); it
!= pkt_id_set
.end (); ++it
)
3885 long ddscr_pkt_id
= *it
;
3886 heapsz_dview
->appendDataDescriptorId (ddscr_pkt_id
);
3888 compute_heapsz_data_view (heapsz_dview
);
3889 return heapsz_dview
;
3893 Experiment::compute_heapsz_data_view (DataView
*heapsz_dview
)
3895 DataView
*dview
= heapsz_dview
;
3897 // Keep track of memory usage
3898 int64_t currentAllocs
= 0;
3899 Size currentLeaks
= 0;
3900 dview
->sort (PROP_TSTAMP
);
3901 long sz
= dview
->getSize ();
3902 for (long i
= 0; i
< sz
; i
++)
3904 int64_t net_alloc
= dview
->getLongValue (PROP_HCUR_NET_ALLOC
, i
);
3905 currentAllocs
+= net_alloc
;
3906 dview
->setValue (PROP_HCUR_ALLOCS
, i
, currentAllocs
);
3908 Size leaks
= dview
->getULongValue (PROP_HCUR_LEAKS
, i
);
3909 currentLeaks
+= leaks
;
3910 dview
->setValue (PROP_HCUR_LEAKS
, i
, currentLeaks
);
3915 Experiment::DBG_memuse (Sample
* s
)
3917 DataDescriptor
*dDscr
= getDataDescriptor (DATA_HEAP
);
3918 if (dDscr
== NULL
|| dDscr
->getSize () == 0)
3921 DataView
*dview
= dDscr
->createView ();
3922 dview
->sort (PROP_TSTAMP
);
3923 hrtime_t ts1
= s
->get_start_time ();
3924 hrtime_t ts2
= s
->get_end_time ();
3926 HeapMap
*heapmap
= new HeapMap ();
3927 long sz
= dview
->getSize ();
3930 hrtime_t maxTime
= 0;
3931 for (long i
= 0; i
< sz
; i
++)
3933 hrtime_t tstamp
= dview
->getLongValue (PROP_TSTAMP
, i
);
3939 Heap_type mtype
= (Heap_type
) dview
->getIntValue (PROP_HTYPE
, i
);
3940 Vaddr vaddr
= dview
->getULongValue (PROP_HVADDR
, i
);
3941 Vaddr ovaddr
= dview
->getULongValue (PROP_HOVADDR
, i
);
3960 long idx
= heapmap
->deallocate (ovaddr
) - 1;
3962 curSize
-= dview
->getULongValue (PROP_HSIZE
, idx
);
3966 heapmap
->allocate (vaddr
, i
+ 1);
3967 curSize
+= dview
->getULongValue (PROP_HSIZE
, i
);
3968 if (curSize
> maxSize
)
3975 printf ("SAMPLE=%s (id=%d) MEMUSE=%lld TSTAMP=%lld\n", s
->get_start_label (),
3976 s
->get_number (), maxSize
, maxTime
- getStartTime ());
3982 Experiment::DBG_memuse (const char *sname
)
3984 for (int i
= 0; i
< samples
->size (); ++i
)
3986 Sample
*sample
= samples
->fetch (i
);
3987 if (streq (sname
, sample
->get_start_label ()))
3989 DBG_memuse (sample
);
3996 Experiment::get_race_events ()
3998 DataDescriptor
*dDscr
= getDataDescriptor (DATA_RACE
);
4001 if (dDscr
->getSize () == 0)
4003 char *base_name
= get_basename (expt_name
);
4004 char *msg
= dbe_sprintf (GTXT ("Loading Race Data: %s"), base_name
);
4005 read_data_file (SP_RACETRACE_FILE
, msg
);
4007 resolve_frame_info (dDscr
);
4013 Experiment::get_deadlock_events ()
4015 DataDescriptor
*dDscr
= getDataDescriptor (DATA_DLCK
);
4018 if (dDscr
->getSize () == 0)
4020 char *base_name
= get_basename (expt_name
);
4021 char *msg
= dbe_sprintf (GTXT ("Loading Deadlocks Data: %s"), base_name
);
4022 read_data_file (SP_DEADLOCK_FILE
, msg
);
4024 resolve_frame_info (dDscr
);
4030 Experiment::get_sample_events ()
4032 DataDescriptor
*dDscr
= getDataDescriptor (DATA_SAMPLE
);
4035 if (dDscr
->getSize () > 0)
4038 // read_overview_file(); //YXXX do this here at some point instead of:
4039 PropDescr
*tmp_propDscr
;
4040 tmp_propDscr
= new PropDescr (PROP_SMPLOBJ
, NTXT ("SMPLOBJ"));
4041 tmp_propDscr
->uname
= NULL
;
4042 tmp_propDscr
->vtype
= TYPE_OBJ
;
4043 dDscr
->addProperty (tmp_propDscr
);
4045 tmp_propDscr
= new PropDescr (PROP_TSTAMP
, NTXT ("TSTAMP"));
4046 tmp_propDscr
->uname
= dbe_strdup ("High resolution timestamp");
4047 tmp_propDscr
->vtype
= TYPE_UINT64
;
4048 dDscr
->addProperty (tmp_propDscr
);
4050 tmp_propDscr
= new PropDescr (PROP_SAMPLE
, NTXT ("SAMPLE"));
4051 tmp_propDscr
->uname
= dbe_strdup ("Sample number");
4052 tmp_propDscr
->vtype
= TYPE_UINT64
;
4053 dDscr
->addProperty (tmp_propDscr
);
4055 tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, NTXT ("EVT_TIME"));
4056 tmp_propDscr
->uname
= dbe_strdup ("Event duration");
4057 tmp_propDscr
->vtype
= TYPE_UINT64
;
4058 dDscr
->addProperty (tmp_propDscr
);
4060 long ssize
= samples
->size ();
4061 for (long ii
= 0; ii
< ssize
; ii
++)
4063 Sample
* sample
= samples
->fetch (ii
);
4064 long recn
= dDscr
->addRecord ();
4065 hrtime_t sduration
= sample
->get_end_time () - sample
->get_start_time ();
4066 dDscr
->setObjValue (PROP_SMPLOBJ
, recn
, sample
);
4067 dDscr
->setValue (PROP_SAMPLE
, recn
, sample
->get_number ());
4068 dDscr
->setValue (PROP_TSTAMP
, recn
, sample
->get_end_time ());
4069 dDscr
->setValue (PROP_EVT_TIME
, recn
, sduration
);
4075 Experiment::get_gc_events ()
4077 DataDescriptor
*dDscr
= getDataDescriptor (DATA_GCEVENT
);
4080 if (dDscr
->getSize () > 0)
4083 // read_overview_file(); //YXXX do this here at some point instead of:
4084 PropDescr
*tmp_propDscr
;
4085 tmp_propDscr
= new PropDescr (PROP_GCEVENTOBJ
, NTXT ("GCEVENTOBJ"));
4086 tmp_propDscr
->uname
= NULL
;
4087 tmp_propDscr
->vtype
= TYPE_OBJ
;
4088 dDscr
->addProperty (tmp_propDscr
);
4090 tmp_propDscr
= new PropDescr (PROP_TSTAMP
, NTXT ("TSTAMP"));
4091 tmp_propDscr
->uname
= dbe_strdup ("High resolution timestamp");
4092 tmp_propDscr
->vtype
= TYPE_UINT64
;
4093 dDscr
->addProperty (tmp_propDscr
);
4095 tmp_propDscr
= new PropDescr (PROP_GCEVENT
, NTXT ("GCEVENT"));
4096 tmp_propDscr
->uname
= dbe_strdup ("GCEvent number");
4097 tmp_propDscr
->vtype
= TYPE_UINT64
;
4098 dDscr
->addProperty (tmp_propDscr
);
4100 tmp_propDscr
= new PropDescr (PROP_EVT_TIME
, NTXT ("EVT_TIME"));
4101 tmp_propDscr
->uname
= dbe_strdup ("Event duration");
4102 tmp_propDscr
->vtype
= TYPE_UINT64
;
4103 dDscr
->addProperty (tmp_propDscr
);
4105 long ssize
= gcevents
->size ();
4106 for (long ii
= 0; ii
< ssize
; ii
++)
4108 GCEvent
* gcevent
= gcevents
->fetch (ii
);
4109 long recn
= dDscr
->addRecord ();
4110 hrtime_t sduration
= gcevent
->end
- gcevent
->start
;
4111 dDscr
->setObjValue (PROP_GCEVENTOBJ
, recn
, gcevent
);
4112 dDscr
->setValue (PROP_GCEVENT
, recn
, gcevent
->id
);
4113 dDscr
->setValue (PROP_TSTAMP
, recn
, gcevent
->end
);
4114 dDscr
->setValue (PROP_EVT_TIME
, recn
, sduration
);
4120 Experiment::update_last_event (hrtime_t ts
/*wall_ts*/)
4122 if (last_event
== ZERO_TIME
)
4124 // not yet initialized
4127 if (last_event
- exp_start_time
< ts
- exp_start_time
)
4128 // compare deltas to avoid hrtime_t wrap
4133 Experiment::write_header ()
4137 // write commentary to the experiment, describing the parameters
4138 if (dbeSession
->ipc_mode
|| dbeSession
->rdt_mode
)
4140 // In GUI: print start time at the beginning
4141 time_t t
= (time_t) start_sec
;
4142 char *start_time
= ctime (&t
);
4143 if (start_time
!= NULL
)
4146 sb
.sprintf (GTXT ("Experiment started %s"), start_time
);
4147 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4150 // write message with target arglist
4151 if (uarglist
!= NULL
)
4154 sb
.sprintf (GTXT ("\nTarget command (%s): '%s'"),
4155 (wsize
== W32
? "32-bit" : "64-bit"), uarglist
);
4156 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4160 sb
.sprintf (GTXT ("Process pid %d, ppid %d, pgrp %d, sid %d"),
4161 pid
, ppid
, pgrp
, sid
);
4162 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4164 // add comment for user name, if set
4165 if (username
!= NULL
)
4168 sb
.sprintf (GTXT ("User: `%s'"), username
);
4169 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4172 // add comment for current working directory
4176 sb
.sprintf (GTXT ("Current working directory: %s"), ucwd
);
4177 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4180 // add comment for collector version string
4181 if (cversion
!= NULL
)
4187 wstring
= NTXT ("?");
4190 wstring
= GTXT ("32-bit");
4193 wstring
= GTXT ("64-bit");
4196 wstring
= NTXT ("??");
4200 sb
.sprintf (GTXT ("Collector version: `%s'; experiment version %d.%d (%s)"),
4201 cversion
, exp_maj_version
, exp_min_version
, wstring
);
4202 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4205 // add comment for driver version string (er_kernel)
4206 if (dversion
!= NULL
)
4209 sb
.sprintf (GTXT ("Kernel driver version: `%s'"), dversion
);
4210 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4213 if (jversion
!= NULL
)
4216 sb
.sprintf (GTXT ("JVM version: `%s'"), jversion
);
4217 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4220 // add comment for hostname, parameters
4221 if (hostname
== NULL
)
4222 hostname
= dbe_strdup (GTXT ("unknown"));
4223 if (os_version
== NULL
)
4224 os_version
= dbe_strdup (GTXT ("unknown"));
4225 if (architecture
== NULL
)
4226 architecture
= dbe_strdup (GTXT ("unknown"));
4228 sb
.sprintf (GTXT ("Host `%s', OS `%s', page size %d, architecture `%s'"),
4229 hostname
, os_version
, page_size
, architecture
);
4230 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4233 if (maxclock
!= minclock
)
4237 GTXT (" %d CPUs, with clocks ranging from %d to %d MHz.; max of %d MHz. assumed"),
4238 ncpus
, minclock
, maxclock
, clock
);
4241 sb
.sprintf (GTXT (" %d CPU%s, clock speed %d MHz."),
4242 ncpus
, (ncpus
== 1 ? NTXT ("") : "s"), clock
);
4243 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4245 // add comment for machine memory size
4246 if (page_size
> 0 && npages
> 0)
4248 long long memsize
= ((long long) npages
* page_size
) / (1024 * 1024);
4250 sb
.sprintf (GTXT (" Memory: %d pages @ %d = %lld MB."),
4251 npages
, page_size
, memsize
);
4252 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4255 // add comment for machine memory size
4256 if (machinemodel
!= NULL
)
4259 sb
.sprintf (GTXT (" Machine model: %s"), machinemodel
);
4260 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4263 // add comment for start time
4264 time_t t
= (time_t) start_sec
;
4265 char *p
= ctime (&t
);
4268 sb
.sprintf (GTXT ("Experiment started %s"), p
);
4270 sb
.sprintf (GTXT ("\nExperiment start not recorded"));
4271 write_coll_params ();
4272 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4273 commentq
->appendqueue (runlogq
);
4274 runlogq
->mark_clear ();
4278 Experiment::write_coll_params ()
4282 // now write the various collection parameters as comments
4284 sb
.append (GTXT ("Data collection parameters:"));
4285 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4286 if (coll_params
.profile_mode
== 1)
4289 sb
.sprintf (GTXT (" Clock-profiling, interval = %d microsecs."),
4290 (int) (coll_params
.ptimer_usec
));
4291 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4293 if (coll_params
.sync_mode
== 1)
4296 char *scope_str
= NTXT ("");
4297 switch (coll_params
.sync_scope
)
4300 scope_str
= GTXT ("Native- and Java-APIs");
4302 case SYNCSCOPE_JAVA
:
4303 scope_str
= GTXT ("JAVA-APIs");
4305 case SYNCSCOPE_NATIVE
:
4306 scope_str
= GTXT ("Native-APIs");
4308 case SYNCSCOPE_JAVA
| SYNCSCOPE_NATIVE
:
4309 scope_str
= GTXT ("Native- and Java-APIs");
4312 if (coll_params
.sync_threshold
< 0)
4313 sb
.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs. (calibrated); %s"),
4314 -coll_params
.sync_threshold
, scope_str
);
4316 sb
.sprintf (GTXT (" Synchronization tracing, threshold = %d microsecs.; %s"),
4317 coll_params
.sync_threshold
, scope_str
);
4318 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4320 if (coll_params
.heap_mode
== 1)
4323 sb
.append (GTXT (" Heap tracing"));
4324 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4326 if (coll_params
.io_mode
== 1)
4329 sb
.append (GTXT (" IO tracing"));
4330 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4332 if (coll_params
.race_mode
== 1)
4335 char *race_stack_name
;
4336 switch (coll_params
.race_stack
)
4339 race_stack_name
= GTXT ("dual-stack");
4342 race_stack_name
= GTXT ("single-stack");
4345 race_stack_name
= GTXT ("leaf");
4350 sb
.sprintf (GTXT (" Datarace detection, %s"), race_stack_name
);
4351 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4353 if (coll_params
.deadlock_mode
== 1)
4356 sb
.append (GTXT (" Deadlock detection"));
4357 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4359 if (coll_params
.hw_mode
== 1)
4362 if (hwc_default
== true)
4363 sb
.append (GTXT (" HW counter-profiling (default); counters:"));
4365 sb
.append (GTXT (" HW counter-profiling; counters:"));
4366 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4367 for (int i
= 0; i
< MAX_HWCOUNT
; i
++)
4369 if (!coll_params
.hw_aux_name
[i
])
4372 sb
.sprintf (GTXT (" %s, tag %d, interval %d, memop %d"),
4373 coll_params
.hw_aux_name
[i
], i
,
4374 coll_params
.hw_interval
[i
], coll_params
.hw_tpc
[i
]);
4375 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4378 if (coll_params
.sample_periodic
== 1)
4381 sb
.sprintf (GTXT (" Periodic sampling, %d secs."),
4382 coll_params
.sample_timer
);
4383 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4385 if (coll_params
.limit
!= 0)
4388 sb
.sprintf (GTXT (" Experiment size limit, %d"),
4390 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4392 if (coll_params
.linetrace
!= NULL
)
4395 sb
.sprintf (GTXT (" Follow descendant processes from: %s"),
4396 coll_params
.linetrace
);
4397 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4399 if (coll_params
.pause_sig
!= NULL
)
4402 sb
.sprintf (GTXT (" Pause signal %s"), coll_params
.pause_sig
);
4403 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4405 if (coll_params
.sample_sig
!= NULL
)
4408 sb
.sprintf (GTXT (" Sample signal %s"), coll_params
.sample_sig
);
4409 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4411 if (coll_params
.start_delay
!= NULL
)
4414 sb
.sprintf (GTXT (" Data collection delay start %s seconds"), coll_params
.start_delay
);
4415 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4417 if (coll_params
.terminate
!= NULL
)
4420 sb
.sprintf (GTXT (" Data collection termination after %s seconds"), coll_params
.terminate
);
4421 commentq
->append (new Emsg (CMSG_COMMENT
, sb
));
4423 // add a blank line after data description
4424 commentq
->append (new Emsg (CMSG_COMMENT
, NTXT ("")));
4429 * Raw packet processing
4432 check_mstate (char *ptr
, PacketDescriptor
*pDscr
, int arg
)
4450 Vector
<FieldDescr
*> *fields
= pDscr
->getFields ();
4451 for (int i
= 0, sz
= fields
->size (); i
< sz
; i
++)
4453 FieldDescr
*fDscr
= fields
->fetch (i
);
4454 if (fDscr
->propID
== arg
)
4455 return *((int*) (ptr
+ fDscr
->offset
));
4460 #define PACKET_ALIGNMENT 4
4463 Experiment::readPacket (Data_window
*dwin
, Data_window::Span
*span
)
4465 Common_packet
*rcp
= (Common_packet
*) dwin
->bind (span
,
4466 sizeof (CommonHead_packet
));
4471 if ((((long) rcp
) % PACKET_ALIGNMENT
) != 0)
4474 size
= PROFILE_BUFFER_CHUNK
- span
->offset
% PROFILE_BUFFER_CHUNK
;
4477 v16
= (uint16_t) rcp
->tsize
;
4478 size
= dwin
->decode (v16
);
4481 size
= PROFILE_BUFFER_CHUNK
- span
->offset
% PROFILE_BUFFER_CHUNK
;
4484 rcp
= (Common_packet
*) dwin
->bind (span
, size
);
4489 if ((((long) rcp
) % PACKET_ALIGNMENT
) != 0)
4492 size
= PROFILE_BUFFER_CHUNK
- span
->offset
% PROFILE_BUFFER_CHUNK
;
4495 v16
= (uint16_t) rcp
->type
;
4496 uint32_t rcptype
= dwin
->decode (v16
);
4497 if (rcptype
== EMPTY_PCKT
)
4499 if (rcptype
== FRAME_PCKT
)
4501 RawFramePacket
*fp
= new RawFramePacket
;
4502 fp
->uid
= dwin
->decode (((Frame_packet
*) rcp
)->uid
);
4507 char *ptr
= (char*) rcp
+ dwin
->decode (((Frame_packet
*) rcp
)->hsize
);
4508 if ((((long) ptr
) % PACKET_ALIGNMENT
) != 0)
4514 v16
= (uint16_t) ((Frame_packet
*) rcp
)->tsize
;
4515 char *end
= (char*) rcp
+ dwin
->decode (v16
);
4518 Common_info
*cinfo
= (Common_info
*) ptr
;
4519 uint32_t hsize
= dwin
->decode (cinfo
->hsize
);
4520 if (hsize
== 0 || ptr
+ hsize
> end
)
4522 int kind
= dwin
->decode (cinfo
->kind
);
4523 bool compressed
= false;
4524 if (kind
& COMPRESSED_INFO
)
4527 kind
&= ~COMPRESSED_INFO
;
4533 char *stack
= ptr
+ sizeof (Stack_info
);
4534 size_t stack_size
= hsize
- sizeof (Stack_info
);
4535 uint64_t uidn
= dwin
->decode (((Stack_info
*) cinfo
)->uid
);
4536 if (stack_size
<= 0)
4538 fp
->uidn
= get_uid_node (uidn
);
4541 uint64_t link_uid
= (uint64_t) 0;
4544 stack_size
-= sizeof (uint64_t);
4545 unsigned char *s
= (unsigned char*) (stack
+ stack_size
);
4547 for (size_t i
= 0; i
<sizeof (link_uid
); i
++)
4549 link_uid
|= (uint64_t) * s
++ << shift
;
4554 fp
->uidn
= add_uid (dwin
, uidn
,
4555 (int) (stack_size
/ sizeof (uint32_t)),
4556 (uint32_t*) stack
, link_uid
);
4558 fp
->uidn
= add_uid (dwin
, uidn
,
4559 (int) (stack_size
/ sizeof (uint64_t)),
4560 (uint64_t*) stack
, link_uid
);
4565 char *stack
= ptr
+ sizeof (Java_info
);
4566 size_t stack_size
= hsize
- sizeof (Java_info
);
4567 uint64_t uidj
= dwin
->decode (((Java_info
*) cinfo
)->uid
);
4568 if (stack_size
<= 0)
4570 fp
->uidj
= get_uid_node (uidj
);
4574 uint64_t link_uid
= (uint64_t) 0;
4577 stack_size
-= sizeof (uint64_t);
4578 unsigned char *s
= (unsigned char*) (stack
+ stack_size
);
4580 for (size_t i
= 0; i
<sizeof (link_uid
); i
++)
4582 link_uid
|= (uint64_t) * s
++ << shift
;
4587 fp
->uidj
= add_uid (dwin
, uidj
,
4588 (int) (stack_size
/ sizeof (uint32_t)),
4589 (uint32_t*) stack
, link_uid
);
4592 // bug 6909545: garbage in 64-bit JAVA_INFO
4593 char *nstack
= (char*) malloc (stack_size
);
4595 char *srcmax
= stack
+ stack_size
- sizeof (uint64_t);
4596 for (char *src
= stack
; src
<= srcmax
;)
4598 int64_t val
= dwin
->decode (*(int32_t*) src
);
4599 *(uint64_t*) dst
= dwin
->decode (val
);
4600 src
+= sizeof (uint64_t);
4601 dst
+= sizeof (uint64_t);
4604 fprintf (stderr
, "er_print: Experiment::readPacket: Error in data: src=%llx greater than %llx\n",
4605 (long long) src
, (long long) srcmax
);
4608 *(uint64_t*) dst
= *(uint64_t*) src
;
4609 src
+= sizeof (uint64_t);
4610 dst
+= sizeof (uint64_t);
4612 fp
->uidj
= add_uid (dwin
, uidj
,
4613 (int) (stack_size
/ sizeof (uint64_t)),
4614 (uint64_t*) nstack
, link_uid
);
4620 fp
->omp_state
= dwin
->decode (((OMP_info
*) ptr
)->omp_state
);
4624 uint64_t omp_uid
= dwin
->decode (((OMP2_info
*) ptr
)->uid
);
4625 fp
->omp_uid
= get_uid_node (omp_uid
);
4626 fp
->omp_state
= dwin
->decode (((OMP2_info
*) ptr
)->omp_state
);
4634 frmpckts
->append (fp
);
4637 else if (rcptype
== UID_PCKT
)
4639 Uid_packet
*uidp
= (Uid_packet
*) rcp
;
4640 uint64_t uid
= dwin
->decode (uidp
->uid
);
4641 char *arr_bytes
= (char*) (uidp
+ 1);
4642 v16
= (uint16_t) rcp
->tsize
;
4643 size_t arr_length
= dwin
->decode (v16
) - sizeof (Uid_packet
);
4644 if (arr_length
<= 0)
4646 uint64_t link_uid
= (uint64_t) 0;
4647 if (dwin
->decode (uidp
->flags
) & COMPRESSED_INFO
)
4649 arr_length
-= sizeof (uint64_t);
4650 unsigned char *s
= (unsigned char*) (arr_bytes
+ arr_length
);
4652 for (size_t i
= 0; i
<sizeof (link_uid
); i
++)
4654 link_uid
|= (uint64_t) * s
++ << shift
;
4659 add_uid (dwin
, uid
, (int) (arr_length
/ sizeof (uint32_t)),
4660 (uint32_t*) arr_bytes
, link_uid
);
4662 add_uid (dwin
, uid
, (int) (arr_length
/ sizeof (uint64_t)),
4663 (uint64_t*) arr_bytes
, link_uid
);
4667 PacketDescriptor
*pcktDescr
= getPacketDescriptor (rcptype
);
4668 if (pcktDescr
== NULL
)
4670 DataDescriptor
*dataDescr
= pcktDescr
->getDataDescriptor ();
4671 if (dataDescr
== NULL
)
4674 /* omazur: TBR START -- old experiment */
4675 if (rcptype
== PROF_PCKT
)
4677 // For backward compatibility with older SS12 experiments
4678 int numstates
= get_params ()->lms_magic_id
; // ugly, for old experiments
4679 if (numstates
> LMS_NUM_SOLARIS_MSTATES
)
4680 numstates
= LMS_NUM_SOLARIS_MSTATES
;
4681 for (int i
= 0; i
< numstates
; i
++)
4682 if (check_mstate ((char*) rcp
, pcktDescr
, PROP_UCPU
+ i
))
4683 readPacket (dwin
, (char*) rcp
, pcktDescr
, dataDescr
, PROP_UCPU
+ i
,
4687 readPacket (dwin
, (char*) rcp
, pcktDescr
, dataDescr
, 0, size
);
4692 Experiment::readPacket (Data_window
*dwin
, char *ptr
, PacketDescriptor
*pDscr
,
4693 DataDescriptor
*dDscr
, int arg
, uint64_t pktsz
)
4701 long recn
= dDscr
->addRecord ();
4702 Vector
<FieldDescr
*> *fields
= pDscr
->getFields ();
4703 int sz
= fields
->size ();
4704 for (int i
= 0; i
< sz
; i
++)
4706 FieldDescr
*field
= fields
->fetch (i
);
4707 v
= (Value
*) (ptr
+ field
->offset
);
4708 if (field
->propID
== arg
)
4710 dDscr
->setValue (PROP_NTICK
, recn
, dwin
->decode (v
->val32
));
4711 dDscr
->setValue (PROP_MSTATE
, recn
, (uint32_t) (field
->propID
- PROP_UCPU
));
4713 if (field
->propID
== PROP_THRID
|| field
->propID
== PROP_LWPID
4714 || field
->propID
== PROP_CPUID
)
4717 switch (field
->vtype
)
4721 tmp64
= dwin
->decode (v
->val32
);
4725 tmp64
= dwin
->decode (v
->val64
);
4737 uint32_t tag
= mapTagValue ((Prop_type
) field
->propID
, tmp64
);
4738 dDscr
->setValue (field
->propID
, recn
, tag
);
4742 switch (field
->vtype
)
4746 dDscr
->setValue (field
->propID
, recn
, dwin
->decode (v
->val32
));
4750 dDscr
->setValue (field
->propID
, recn
, dwin
->decode (v
->val64
));
4754 int len
= (int) (pktsz
- field
->offset
);
4755 if ((len
> 0) && (ptr
[field
->offset
] != 0))
4757 StringBuilder
*sb
= new StringBuilder ();
4758 sb
->append (ptr
+ field
->offset
, 0, len
);
4759 dDscr
->setObjValue (field
->propID
, recn
, sb
);
4763 // ignoring the following cases (why?)
4777 #define PROG_BYTE 102400 // update progress bar every PROG_BYTE bytes
4780 Experiment::read_data_file (const char *fname
, const char *msg
)
4782 Data_window::Span span
;
4783 off64_t total_len
, remain_len
;
4784 char *progress_bar_msg
;
4785 int progress_bar_percent
= -1;
4787 char *data_file_name
= dbe_sprintf (NTXT ("%s/%s"), expt_name
, fname
);
4788 Data_window
*dwin
= new Data_window (data_file_name
);
4789 // Here we can call stat(data_file_name) to get file size,
4790 // and call a function to reallocate vectors for clock profiling data
4791 free (data_file_name
);
4792 if (dwin
->not_opened ())
4797 dwin
->need_swap_endian
= need_swap_endian
;
4800 span
.length
= dwin
->get_fsize ();
4801 total_len
= remain_len
= span
.length
;
4802 progress_bar_msg
= dbe_sprintf (NTXT ("%s %s"), NTXT (" "), msg
);
4806 uint64_t pcktsz
= readPacket (dwin
, &span
);
4809 // Update progress bar
4810 if ((span
.length
<= remain_len
) && (remain_len
> 0))
4812 int percent
= (int) (100 * (total_len
- remain_len
) / total_len
);
4813 if (percent
> progress_bar_percent
)
4815 progress_bar_percent
+= 10;
4816 theApplication
->set_progress (percent
, progress_bar_msg
);
4818 remain_len
-= PROG_BYTE
;
4820 span
.length
-= pcktsz
;
4821 span
.offset
+= pcktsz
;
4828 sb
.sprintf (GTXT ("WARNING: There are %d invalid packet(s) in the %s file"),
4829 invalid_packet
, fname
);
4830 Emsg
*m
= new Emsg (CMSG_WARN
, sb
);
4834 theApplication
->set_progress (0, NTXT (""));
4835 free (progress_bar_msg
);
4839 Experiment::read_overview_file ()
4841 char *data_file_name
= dbe_sprintf ("%s/%s", expt_name
, SP_OVERVIEW_FILE
);
4842 Data_window
*dwin
= new Data_window (data_file_name
);
4843 free (data_file_name
);
4844 if (dwin
->not_opened ())
4849 dwin
->need_swap_endian
= need_swap_endian
;
4850 newDataDescriptor (DATA_SAMPLE
);
4852 Data_window::Span span
;
4854 span
.length
= dwin
->get_fsize ();
4856 PrUsage
*data
= NULL
, *data_prev
= NULL
;
4858 int sample_number
= 1;
4862 prDataSize
= PrUsage::bind32Size ();
4864 prDataSize
= PrUsage::bind64Size ();
4866 while (span
.length
> 0)
4869 data
= new PrUsage ();
4871 void *dw
= dwin
->bind (&span
, prDataSize
);
4872 if ((dw
== NULL
) || (prDataSize
> span
.length
))
4874 Emsg
*m
= new Emsg (CMSG_ERROR
, GTXT ("Warning: overview data file can't be read"));
4882 data
->bind32 (dw
, need_swap_endian
);
4884 data
->bind64 (dw
, need_swap_endian
);
4885 span
.length
-= prDataSize
;
4886 span
.offset
+= prDataSize
;
4888 // Skip the first packet
4889 if (data_prev
== NULL
)
4891 if (sample_number
> samples
->size ())
4892 { // inconsistent log/overview
4893 sample
= new Sample (sample_number
);
4894 char * label
= GTXT ("<unknown>");
4895 sample
->start_label
= dbe_strdup (label
);
4896 sample
->end_label
= dbe_strdup (label
);
4897 samples
->append (sample
);
4900 sample
= samples
->fetch (sample_number
- 1);
4902 sample
->start_time
= data_prev
->pr_tstamp
+ 1;
4903 sample
->end_time
= data
->pr_tstamp
;
4904 sample
->prusage
= data_prev
;
4906 data_prev
->pr_rtime
= data
->pr_rtime
- data_prev
->pr_rtime
;
4907 data_prev
->pr_utime
= data
->pr_utime
- data_prev
->pr_utime
;
4908 data_prev
->pr_stime
= data
->pr_stime
- data_prev
->pr_stime
;
4909 data_prev
->pr_ttime
= data
->pr_ttime
- data_prev
->pr_ttime
;
4910 data_prev
->pr_tftime
= data
->pr_tftime
- data_prev
->pr_tftime
;
4911 data_prev
->pr_dftime
= data
->pr_dftime
- data_prev
->pr_dftime
;
4912 data_prev
->pr_kftime
= data
->pr_kftime
- data_prev
->pr_kftime
;
4913 data_prev
->pr_ltime
= data
->pr_ltime
- data_prev
->pr_ltime
;
4914 data_prev
->pr_slptime
= data
->pr_slptime
- data_prev
->pr_slptime
;
4915 data_prev
->pr_wtime
= data
->pr_wtime
- data_prev
->pr_wtime
;
4916 data_prev
->pr_stoptime
= data
->pr_stoptime
- data_prev
->pr_stoptime
;
4917 data_prev
->pr_minf
= data
->pr_minf
- data_prev
->pr_minf
;
4918 data_prev
->pr_majf
= data
->pr_majf
- data_prev
->pr_majf
;
4919 data_prev
->pr_nswap
= data
->pr_nswap
- data_prev
->pr_nswap
;
4920 data_prev
->pr_inblk
= data
->pr_inblk
- data_prev
->pr_inblk
;
4921 data_prev
->pr_oublk
= data
->pr_oublk
- data_prev
->pr_oublk
;
4922 data_prev
->pr_msnd
= data
->pr_msnd
- data_prev
->pr_msnd
;
4923 data_prev
->pr_mrcv
= data
->pr_mrcv
- data_prev
->pr_mrcv
;
4924 data_prev
->pr_sigs
= data
->pr_sigs
- data_prev
->pr_sigs
;
4925 data_prev
->pr_vctx
= data
->pr_vctx
- data_prev
->pr_vctx
;
4926 data_prev
->pr_ictx
= data
->pr_ictx
- data_prev
->pr_ictx
;
4927 data_prev
->pr_sysc
= data
->pr_sysc
- data_prev
->pr_sysc
;
4928 data_prev
->pr_ioch
= data
->pr_ioch
- data_prev
->pr_ioch
;
4929 sample
->get_usage (); // force validation
4932 for (long smpNum
= samples
->size (); smpNum
>= sample_number
; smpNum
--)
4934 // overview file was truncated
4935 sample
= samples
->remove (smpNum
- 1);
4941 // Update last_event so that getEndTime() covers
4942 // all loadobjects, too.
4943 update_last_event (data
->pr_tstamp
);
4951 Experiment::uidNodeCmp (const void *a
, const void *b
)
4953 UIDnode
*nd1
= *(UIDnode
**) a
;
4954 UIDnode
*nd2
= *(UIDnode
**) b
;
4955 if (nd1
->uid
== nd2
->uid
)
4957 return nd1
->uid
< nd2
->uid
? -1 : 1;
4961 funcAddr (uint32_t val
)
4963 if (val
== (uint32_t) SP_LEAF_CHECK_MARKER
)
4964 return (uint64_t) SP_LEAF_CHECK_MARKER
;
4965 if (val
== (uint32_t) SP_TRUNC_STACK_MARKER
)
4966 return (uint64_t) SP_TRUNC_STACK_MARKER
;
4967 if (val
== (uint32_t) SP_FAILED_UNWIND_MARKER
)
4968 return (uint64_t) SP_FAILED_UNWIND_MARKER
;
4972 Experiment::UIDnode
*
4973 Experiment::add_uid (Data_window
*dwin
, uint64_t uid
, int size
,
4974 uint32_t *array
, uint64_t link_uid
)
4976 if (uid
== (uint64_t) 0)
4978 uint64_t val
= funcAddr (dwin
->decode (array
[0]));
4979 UIDnode
*node
= NULL
;
4980 UIDnode
*res
= get_uid_node (uid
, val
);
4981 UIDnode
*next
= res
;
4982 for (int i
= 0; i
< size
; i
++)
4984 val
= funcAddr (dwin
->decode (array
[i
]));
4987 next
= get_uid_node ((uint64_t) 0, val
);
4995 else if (node
->val
!= val
) // Algorithmic error (should never happen)
4996 node
->val
= (uint64_t) SP_LEAF_CHECK_MARKER
;
4998 if (next
== NULL
&& link_uid
!= (uint64_t) 0 && node
!= NULL
)
4999 node
->next
= get_uid_node (link_uid
);
5003 Experiment::UIDnode
*
5004 Experiment::add_uid (Data_window
*dwin
, uint64_t uid
, int size
, uint64_t *array
, uint64_t link_uid
)
5006 if (uid
== (uint64_t) 0)
5008 UIDnode
*node
= NULL
;
5009 uint64_t val
= dwin
->decode (array
[0]);
5010 UIDnode
*res
= get_uid_node (uid
, val
);
5011 UIDnode
*next
= res
;
5012 for (int i
= 0; i
< size
; i
++)
5014 val
= dwin
->decode (array
[i
]);
5017 next
= get_uid_node ((uint64_t) 0, val
);
5023 if (node
->val
== (uint64_t) 0)
5025 else if (node
->val
!= val
) // Algorithmic error (should never happen)
5026 node
->val
= (uint64_t) - 1;
5028 if (next
== NULL
&& link_uid
!= (uint64_t) 0 && node
!= NULL
)
5029 node
->next
= get_uid_node (link_uid
);
5033 Experiment::UIDnode
*
5034 Experiment::new_uid_node (uint64_t uid
, uint64_t val
)
5036 #define NCHUNKSTEP 1024
5037 if (nnodes
>= nchunks
* CHUNKSZ
)
5039 // Reallocate Node chunk array
5040 UIDnode
** old_chunks
= chunks
;
5041 chunks
= new UIDnode
*[nchunks
+ NCHUNKSTEP
];
5042 memcpy (chunks
, old_chunks
, nchunks
* sizeof (UIDnode
*));
5043 nchunks
+= NCHUNKSTEP
;
5044 delete[] old_chunks
;
5045 // Clean future pointers
5046 memset (&chunks
[nchunks
- NCHUNKSTEP
], 0, NCHUNKSTEP
* sizeof (UIDnode
*));
5049 if (NULL
== chunks
[nnodes
/ CHUNKSZ
]) // Allocate new chunk for nodes.
5050 chunks
[nnodes
/ CHUNKSZ
] = new UIDnode
[CHUNKSZ
];
5051 UIDnode
*node
= &chunks
[nnodes
/ CHUNKSZ
][nnodes
% CHUNKSZ
];
5059 Experiment::UIDnode
*
5060 Experiment::get_uid_node (uint64_t uid
, uint64_t val
)
5062 int hash
= (((int) uid
) >> 4) & (HTableSize
- 1);
5063 if (uid
!= (uint64_t) 0)
5065 UIDnode
*node
= uidHTable
[hash
];
5066 if (node
&& node
->uid
== uid
)
5069 UIDnode
*node
= new_uid_node (uid
, val
);
5070 if (uid
!= (uint64_t) 0)
5072 uidHTable
[hash
] = node
;
5073 uidnodes
->append (node
);
5078 Experiment::UIDnode
*
5079 Experiment::get_uid_node (uint64_t uid
)
5081 if (uid
== (uint64_t) 0)
5083 int hash
= (((int) uid
) >> 4) & (HTableSize
- 1);
5084 UIDnode
*node
= uidHTable
[hash
];
5085 if (node
&& node
->uid
== uid
)
5087 node
= new_uid_node (uid
, (uint64_t) 0);
5092 Experiment::UIDnode
*
5093 Experiment::find_uid_node (uint64_t uid
)
5095 int hash
= (((int) uid
) >> 4) & (HTableSize
- 1);
5096 UIDnode
*node
= uidHTable
[hash
];
5097 if (node
&& node
->uid
== uid
)
5100 int rt
= uidnodes
->size () - 1;
5103 int md
= (lt
+ rt
) / 2;
5104 node
= uidnodes
->fetch (md
);
5105 if (node
->uid
< uid
)
5107 else if (node
->uid
> uid
)
5111 uidHTable
[hash
] = node
;
5119 Experiment::frUidCmp (const void *a
, const void *b
)
5121 RawFramePacket
*fp1
= *(RawFramePacket
**) a
;
5122 RawFramePacket
*fp2
= *(RawFramePacket
**) b
;
5123 if (fp1
->uid
== fp2
->uid
)
5125 return fp1
->uid
< fp2
->uid
? -1 : 1;
5128 Experiment::RawFramePacket
*
5129 Experiment::find_frame_packet (uint64_t uid
)
5132 int rt
= frmpckts
->size () - 1;
5135 int md
= (lt
+ rt
) / 2;
5136 RawFramePacket
*fp
= frmpckts
->fetch (md
);
5139 else if (fp
->uid
> uid
)
5148 #define FRINFO_CACHEOPT_SIZE_LIMIT 4000000
5149 #define FRINFO_PIPELINE_SIZE_LIMIT 500000
5150 #define FRINFO_PIPELINE_NUM_STAGES 3
5152 // Pipelined execution of resolve_frame_info() and add_stack().
5153 // Since this is the largest time consuming part of loading an experiment (especially
5154 // so for large java experiments) - executing this part as a 3 stage pipeline can
5155 // give significant performance gain - and this concept can be aggressively applied
5156 // to enhance the gain further in future. The three stages are:
5157 // Phase 1: resolve_frame_info()
5158 // Phase 2: first part of add_stack() where the native stack is built
5159 // Phase 3: second part og add_stack() where the java stack is built
5160 // Phase 4: insert the native and java stacks into the stack map
5161 // The main thread operates in the first Phase and the other stages are
5162 // operated by a ssplib sequential queue - The threads working on the queues run concurrently
5163 // with each other and with the main thread. But within a particular queue, jobs are
5164 // executed sequentially
5167 // This is the second phase of the pipeline of resolve_frame_info and add_stack
5168 // It works on a chunk of iterations (size CSTCTX_CHUNK_SZ) and invokes add_stack()
5169 // for each one of them
5172 Experiment::resolve_frame_info (DataDescriptor
*dDscr
)
5174 if (!resolveFrameInfo
)
5178 dDscr
->setResolveFrInfoDone ();
5181 int propID
= dbeSession
->getPropIdByName (NTXT ("TSTAMP"));
5182 Data
*dataTStamp
= dDscr
->getData (propID
);
5183 if (dataTStamp
== NULL
)
5186 propID
= dbeSession
->getPropIdByName (NTXT ("FRINFO"));
5187 Data
*dataFrinfo
= dDscr
->getData (propID
);
5189 propID
= dbeSession
->getPropIdByName (NTXT ("THRID"));
5190 Data
*dataThrId
= dDscr
->getData (propID
);
5192 // We can get frame info either by FRINFO or by [THRID,STKIDX]
5193 if (dataFrinfo
== NULL
)
5196 char *propName
= NTXT ("MSTACK");
5197 propID
= dbeSession
->getPropIdByName (propName
);
5198 PropDescr
*prMStack
= new PropDescr (propID
, propName
);
5199 prMStack
->uname
= dbe_strdup (GTXT ("Machine Call Stack"));
5200 prMStack
->vtype
= TYPE_OBJ
;
5201 dDscr
->addProperty (prMStack
);
5203 propName
= NTXT ("USTACK");
5204 propID
= dbeSession
->getPropIdByName (propName
);
5205 PropDescr
*prUStack
= new PropDescr (propID
, propName
);
5206 prUStack
->uname
= dbe_strdup (GTXT ("User Call Stack"));
5207 prUStack
->vtype
= TYPE_OBJ
;
5208 dDscr
->addProperty (prUStack
);
5210 propName
= NTXT ("XSTACK");
5211 propID
= dbeSession
->getPropIdByName (propName
);
5212 PropDescr
*prXStack
= new PropDescr (propID
, propName
);
5213 prXStack
->uname
= dbe_strdup (GTXT ("Expert Call Stack"));
5214 prXStack
->vtype
= TYPE_OBJ
;
5215 dDscr
->addProperty (prXStack
);
5217 propName
= NTXT ("HSTACK");
5218 propID
= dbeSession
->getPropIdByName (propName
);
5219 PropDescr
*prHStack
= new PropDescr (propID
, propName
);
5220 prHStack
->uname
= dbe_strdup (GTXT ("ShowHide Call Stack"));
5221 prHStack
->vtype
= TYPE_OBJ
;
5222 dDscr
->addProperty (prHStack
);
5226 propName
= NTXT ("JTHREAD");
5227 propID
= dbeSession
->getPropIdByName (propName
);
5228 PropDescr
*prJThread
= new PropDescr (propID
, propName
);
5229 prJThread
->uname
= dbe_strdup (GTXT ("Java Thread"));
5230 prJThread
->vtype
= TYPE_OBJ
;
5231 dDscr
->addProperty (prJThread
);
5236 PropDescr
*prop
= new PropDescr (PROP_OMPSTATE
, NTXT ("OMPSTATE"));
5237 prop
->uname
= dbe_strdup (GTXT ("OpenMP state"));
5238 prop
->vtype
= TYPE_UINT32
;
5239 char * stateNames
[OMP_LAST_STATE
] = OMP_THR_STATE_STRINGS
;
5240 char * stateUNames
[OMP_LAST_STATE
] = OMP_THR_STATE_USTRINGS
;
5241 for (int ii
= 0; ii
< OMP_LAST_STATE
; ii
++)
5242 prop
->addState (ii
, stateNames
[ii
], stateUNames
[ii
]);
5243 dDscr
->addProperty (prop
);
5245 // add PROP_CPRID to profiling data (not same as omptrace's PROP_CPRID)
5246 prop
= dDscr
->getProp (PROP_CPRID
);
5249 VType_type type
= prop
->vtype
;
5250 assert (type
== TYPE_OBJ
); //see 7040526
5252 prop
= new PropDescr (PROP_CPRID
, NTXT ("CPRID")); //profiling PROP_CPRID
5253 prop
->uname
= dbe_strdup (GTXT ("OpenMP parallel region"));
5254 prop
->vtype
= TYPE_OBJ
;
5255 dDscr
->addProperty (prop
);
5257 // add PROP_TSKID to profiling data (not same as omptrace's PROP_TSKID)
5258 prop
= dDscr
->getProp (PROP_TSKID
);
5261 VType_type type
= prop
->vtype
;
5262 assert (type
== TYPE_OBJ
); //see 7040526
5264 prop
= new PropDescr (PROP_TSKID
, NTXT ("TSKID")); //profiling PROP_TSKID
5265 prop
->uname
= dbe_strdup (GTXT ("OpenMP task"));
5266 prop
->vtype
= TYPE_OBJ
;
5267 dDscr
->addProperty (prop
);
5269 char *progress_bar_msg
= dbe_sprintf (NTXT ("%s %s: %s"), NTXT (" "),
5270 GTXT ("Processing CallStack Data"),
5271 get_basename (expt_name
));
5272 int progress_bar_percent
= -1;
5273 long deltaReport
= 5000;
5274 long nextReport
= 0;
5276 long size
= dDscr
->getSize ();
5277 // bool resolve_frinfo_pipelined = size > FRINFO_PIPELINE_SIZE_LIMIT && !ompavail;
5278 bool resolve_frinfo_pipelined
= false;
5280 Map
<uint64_t, uint64_t> *nodeCache
= NULL
;
5281 Map
<uint64_t, uint64_t> *frameInfoCache
= NULL
;
5282 if (size
> FRINFO_CACHEOPT_SIZE_LIMIT
&& dversion
== NULL
)
5284 frameInfoCache
= new CacheMap
<uint64_t, uint64_t>;
5285 nodeCache
= new CacheMap
<uint64_t, uint64_t>;
5288 pushCnt
= popCnt
= pushCnt3
= popCnt3
= 0;
5291 FramePacket
*fp
= NULL
;
5292 // DbeThreadPool * threadPool = new DbeThreadPool(5);
5293 fp
= new FramePacket
;
5294 fp
->stack
= new Vector
<Vaddr
>;
5295 fp
->jstack
= new Vector
<Vaddr
>;
5296 fp
->ompstack
= new Vector
<Vaddr
>;
5300 // piggyback on post-processing to calculate exp->last_event
5301 const hrtime_t _exp_start_time
= getStartTime (); // wall clock time
5302 hrtime_t exp_duration
= getLastEvent () == ZERO_TIME
? 0
5303 : getLastEvent () - _exp_start_time
; // zero-based
5308 for (long i
= 0; i
< size
; i
++)
5310 if (i
== nextReport
)
5312 int percent
= (int) (i
* 100 / size
);
5313 if (percent
> progress_bar_percent
)
5315 progress_bar_percent
+= 10;
5316 theApplication
->set_progress (percent
, progress_bar_msg
);
5318 nextReport
+= deltaReport
;
5321 uint32_t thrid
= (uint32_t) dataThrId
->fetchInt (i
);
5322 hrtime_t tstamp
= (hrtime_t
) dataTStamp
->fetchLong (i
);
5324 // piggyback on post-processing to calculate exp->last_event
5326 hrtime_t relative_timestamp
= tstamp
- _exp_start_time
;
5327 if (exp_duration
< relative_timestamp
)
5328 exp_duration
= relative_timestamp
;
5330 uint64_t frinfo
= (uint64_t) dataFrinfo
->fetchLong (i
);
5332 RawFramePacket
*rfp
= NULL
;
5335 // CacheMap does not work with NULL key
5336 if (frameInfoCache
!= NULL
)
5337 rfp
= (RawFramePacket
*) frameInfoCache
->get (frinfo
);
5341 rfp
= find_frame_packet (frinfo
);
5344 if (frameInfoCache
!= NULL
)
5345 frameInfoCache
->put (frinfo
, (uint64_t) rfp
);
5352 // Process OpenMP properties
5355 fp
->omp_state
= rfp
? rfp
->omp_state
: 0;
5356 dDscr
->setValue (PROP_OMPSTATE
, i
, fp
->omp_state
);
5358 fp
->omp_cprid
= mapPRid
->get (thrid
, tstamp
, mapPRid
->REL_EQLE
);
5359 void *omp_preg
= mapPReg
->get (thrid
, tstamp
, mapPReg
->REL_EQLE
);
5362 char *idxname
= NTXT ("OMP_preg");
5363 int idxtype
= dbeSession
->findIndexSpaceByName (idxname
);
5366 Histable
*preg0
= dbeSession
->findObjectById (Histable::INDEXOBJ
, idxtype
, (int64_t) 0);
5369 Vector
<Histable
*> pregs
;
5370 pregs
.append (preg0
);
5371 omp_preg
= cstack
->add_stack (&pregs
);
5372 mapPReg
->put (thrid
, tstamp
, omp_preg
);
5376 dDscr
->setObjValue (PROP_CPRID
, i
, omp_preg
); //profiling PROP_CPRID
5377 void *omp_task
= mapTask
->get (thrid
, tstamp
, mapTask
->REL_EQLE
);
5380 char *idxname
= NTXT ("OMP_task");
5381 int idxtype
= dbeSession
->findIndexSpaceByName (idxname
);
5384 Histable
*task0
= dbeSession
->findObjectById (Histable::INDEXOBJ
, idxtype
, (int64_t) 0);
5387 Vector
<Histable
*> tasks
;
5388 tasks
.append (task0
);
5389 omp_task
= cstack
->add_stack (&tasks
);
5390 mapTask
->put (thrid
, tstamp
, omp_task
);
5394 dDscr
->setObjValue (PROP_TSKID
, i
, omp_task
); //profiling PROP_TSKID
5402 // Construct the native stack
5403 fp
->stack
->reset ();
5404 Vaddr leafpc
= dDscr
->getULongValue (PROP_LEAFPC
, i
);
5406 fp
->stack
->append (leafpc
);
5407 UIDnode
*node
= rfp
? rfp
->uidn
: NULL
;
5410 if (node
->next
== node
)
5411 // this node contains link_uid
5412 node
= find_uid_node (node
->uid
);
5415 fp
->stack
->append (node
->val
);
5420 int last
= fp
->stack
->size () - 1;
5423 switch (fp
->stack
->fetch (last
))
5425 case SP_TRUNC_STACK_MARKER
:
5426 fp
->truncated
= (Vaddr
) SP_TRUNC_STACK_MARKER
;
5427 fp
->stack
->remove (last
);
5429 case SP_FAILED_UNWIND_MARKER
:
5430 fp
->truncated
= (Vaddr
) SP_FAILED_UNWIND_MARKER
;
5431 fp
->stack
->remove (last
);
5436 // Construct the Java stack
5437 fp
->jstack
->reset ();
5438 node
= rfp
? rfp
->uidj
: NULL
;
5441 if (node
->next
== node
)
5443 // this node contains link_uid
5447 // CacheMap does not work with NULL key
5448 if (nodeCache
!= NULL
)
5449 n
= (UIDnode
*) nodeCache
->get (node
->uid
);
5453 n
= find_uid_node (node
->uid
);
5456 if (nodeCache
!= NULL
)
5457 nodeCache
->put (node
->uid
, (uint64_t) n
);
5464 fp
->jstack
->append (node
->val
);
5468 fp
->jtruncated
= false;
5469 last
= fp
->jstack
->size () - 1;
5470 if (last
>= 1 && fp
->jstack
->fetch (last
) == SP_TRUNC_STACK_MARKER
)
5472 fp
->jtruncated
= true;
5473 fp
->jstack
->remove (last
);
5474 fp
->jstack
->remove (last
- 1);
5477 // Construct the OpenMP stack
5480 fp
->ompstack
->reset ();
5481 if (rfp
&& rfp
->omp_uid
)
5484 fp
->ompstack
->append (leafpc
);
5485 node
= rfp
->omp_uid
;
5488 if (node
->next
== node
)
5489 // this node contains link_uid
5490 node
= find_uid_node (node
->uid
);
5493 fp
->ompstack
->append (node
->val
);
5497 fp
->omptruncated
= false;
5498 last
= fp
->ompstack
->size () - 1;
5501 switch (fp
->ompstack
->fetch (last
))
5503 case SP_TRUNC_STACK_MARKER
:
5504 fp
->omptruncated
= (Vaddr
) SP_TRUNC_STACK_MARKER
;
5505 fp
->ompstack
->remove (last
);
5507 case SP_FAILED_UNWIND_MARKER
:
5508 fp
->omptruncated
= (Vaddr
) SP_FAILED_UNWIND_MARKER
;
5509 fp
->ompstack
->remove (last
);
5515 cstack
->add_stack (dDscr
, i
, fp
, NULL
);
5518 // piggyback on post-processing to calculate exp->last_event
5520 hrtime_t exp_end_time
= _exp_start_time
+ exp_duration
;
5521 update_last_event (exp_end_time
);
5528 GTXT ("*** Warning: %d frameinfo packets are missing from total of %d when resolving %s."),
5529 missed_fi
, total_fi
, dDscr
->getName ());
5530 warnq
->append (new Emsg (CMSG_WARN
, sb
));
5533 // threadPool->wait_group();
5534 // delete threadPool;
5535 theApplication
->set_progress (0, NTXT (""));
5536 free (progress_bar_msg
);
5537 if (!resolve_frinfo_pipelined
&& fp
!= NULL
)
5539 delete fp
->ompstack
;
5544 delete frameInfoCache
;
5545 frameInfoCache
= NULL
;
5551 Experiment::post_process ()
5553 // update non_paused_time after final update to "last_event"
5554 if (resume_ts
!= MAX_TIME
&& last_event
)
5556 hrtime_t ts
= last_event
- exp_start_time
;
5557 hrtime_t delta
= ts
- resume_ts
;
5558 non_paused_time
+= delta
;
5559 resume_ts
= MAX_TIME
; // collection is paused
5562 // GC: prune events outside of experiment duration, calculate GC duration, update indices
5565 gc_duration
= ZERO_TIME
;
5566 if (gcevents
!= NULL
)
5568 // delete events that finish before exp_start_time or start after last_event
5569 for (int ii
= 0; ii
< gcevents
->size ();)
5571 gcevent
= gcevents
->fetch (ii
);
5572 if (gcevent
->end
- exp_start_time
< 0
5573 || last_event
- gcevent
->start
< 0)
5574 delete gcevents
->remove (ii
);
5579 Vec_loop (GCEvent
*, gcevents
, index
, gcevent
)
5581 gcevent
->id
= index
+ 1; // renumber to account for any deleted events
5582 if (gcevent
->start
- exp_start_time
< 0 || gcevent
->start
== ZERO_TIME
)
5583 // truncate events that start before experiment start
5584 gcevent
->start
= exp_start_time
;
5585 if (last_event
- gcevent
->end
< 0)
5586 // truncate events that end after experiment end
5587 gcevent
->end
= last_event
;
5588 gc_duration
+= gcevent
->end
- gcevent
->start
;
5592 Experiment::Exp_status
5593 Experiment::find_expdir (char *path
)
5595 // This function checks that the experiment directory
5596 // is of the proper form, and accessible
5600 expt_name
= dbe_strdup (path
);
5602 // Check that the name ends in .er
5603 size_t i
= strlen (path
);
5604 if (i
> 0 && path
[i
- 1] == '/')
5607 if (i
< 4 || strcmp (&path
[i
- 3], NTXT (".er")) != 0)
5609 Emsg
*m
= new Emsg (CMSG_FATAL
,
5610 GTXT ("*** Error: not a valid experiment name"));
5616 // Check if new directory structure (i.e., no pointer file)
5617 if (dbe_stat (path
, &sbuf
))
5619 Emsg
*m
= new Emsg (CMSG_FATAL
, GTXT ("*** Error: experiment not found"));
5624 if (S_ISDIR (sbuf
.st_mode
) == 0)
5626 // ignore pointer-file experiments
5627 Emsg
*m
= new Emsg (CMSG_FATAL
,
5628 GTXT ("*** Error: experiment was recorded with an earlier version, and can not be read"));
5638 Experiment::purge ()
5640 // This routine will purge all of the caches of releasable storage.
5641 for (int i
= 0; i
< dataDscrs
->size (); ++i
)
5643 DataDescriptor
*dataDscr
= dataDscrs
->fetch (i
);
5644 if (dataDscr
== NULL
)
5649 delete cstackShowHide
;
5650 cstack
= CallStack::getInstance (this);
5651 cstackShowHide
= CallStack::getInstance (this);
5655 Experiment::resetShowHideStack ()
5657 delete cstackShowHide
;
5658 cstackShowHide
= CallStack::getInstance (this);
5661 #define GET_INT_VAL(v, s, len) \
5662 for (v = len = 0; isdigit(*s); s++, len++) { v = v * 10 + (*s -'0'); }
5665 dir_name_cmp (const void *a
, const void *b
)
5667 char *s1
= *((char **) a
);
5668 char *s2
= *((char **) b
);
5671 if (isdigit (*s1
) && isdigit (*s2
))
5673 int v1
, v2
, len1
, len2
;
5674 GET_INT_VAL (v1
, s1
, len1
);
5675 GET_INT_VAL (v2
, s2
, len2
);
5691 Experiment::get_descendants_names ()
5693 char *dir_name
= get_expt_name ();
5694 if (dir_name
== NULL
)
5696 DIR *exp_dir
= opendir (dir_name
);
5697 if (exp_dir
== NULL
)
5699 Vector
<char*> *exp_names
= new Vector
<char*>();
5700 for (struct dirent
*entry
= readdir (exp_dir
); entry
;
5701 entry
= readdir (exp_dir
))
5703 if (entry
->d_name
[0] == '_' || strncmp (entry
->d_name
, "M_r", 3) == 0)
5705 char *dpath
= dbe_sprintf (NTXT ("%s/%s"), dir_name
, entry
->d_name
);
5707 if (dbe_stat (dpath
, &sbuf
) == 0 && S_ISDIR (sbuf
.st_mode
))
5708 exp_names
->append (dpath
);
5714 if (exp_names
->size () == 0)
5719 exp_names
->sort (dir_name_cmp
);
5724 Experiment::create_dir (char *dname
)
5726 if (mkdir (dname
, S_IRWXU
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
) == 0)
5731 if (dbe_stat (dname
, &sbuf
) != 0 || S_ISDIR (sbuf
.st_mode
) == 0)
5733 char *buf
= dbe_sprintf (GTXT ("Unable to create directory `%s'\n"),
5735 errorq
->append (new Emsg (CMSG_ERROR
, buf
));
5743 Experiment::get_arch_name ()
5745 if (arch_name
== NULL
)
5747 // Determine the master experiment directory.
5748 // omazur: should do it in a less hacky way. XXXX
5749 char *ptr
= strstr_r (expt_name
, DESCENDANT_EXPT_KEY
);
5750 ptr
= ptr
? ptr
+ 3 : expt_name
+ strlen (expt_name
);
5751 arch_name
= dbe_sprintf (NTXT ("%.*s/%s"), (int) (ptr
- expt_name
),
5752 expt_name
, SP_ARCHIVES_DIR
);
5758 Experiment::get_fndr_arch_name ()
5760 if (fndr_arch_name
== NULL
)
5761 // Determine the founder experiment directory.
5762 fndr_arch_name
= dbe_strdup (get_arch_name ());
5763 return fndr_arch_name
;
5768 HASH_NAME_LEN
= 11 // (64 / 6 + 1) = 11
5772 get_hash_string (char buf
[HASH_NAME_LEN
+ 1], uint64_t hash
)
5774 static const char *har
=
5775 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
5776 for (int i
= 0; i
< HASH_NAME_LEN
; i
++)
5778 buf
[i
] = har
[hash
& 0x3f];
5781 buf
[HASH_NAME_LEN
] = 0;
5786 Experiment::getNameInArchive (const char *fname
, bool archiveFile
)
5788 char *aname
= get_archived_name (fname
, archiveFile
);
5789 char *ret
= dbe_sprintf (NTXT ("%s/%s"), get_arch_name (), aname
);
5794 #define MAX_ARCHIVE_FILENAME_LEN (256 - HASH_NAME_LEN - 2)
5797 Experiment::get_archived_name (const char *fname
, bool archiveFile
)
5799 char *bname
= get_basename (fname
);
5802 char dirnameHash
[HASH_NAME_LEN
+ 1];
5803 // Treat "a.out" and "./a.out" equally
5804 uint64_t hash
= bname
!= fname
? crc64 (fname
, bname
- fname
)
5805 : crc64 (NTXT ("./"), 2);
5806 get_hash_string (dirnameHash
, hash
);
5809 long bname_len
= dbe_sstrlen (bname
);
5810 if (bname_len
> MAX_ARCHIVE_FILENAME_LEN
)
5812 char basenameHash
[HASH_NAME_LEN
+ 1];
5813 hash
= crc64 (bname
, bname_len
);
5814 get_hash_string (basenameHash
, hash
);
5815 ret
= dbe_sprintf ("%.*s%c%s_%s",
5816 MAX_ARCHIVE_FILENAME_LEN
- HASH_NAME_LEN
- 1,
5817 bname
, archiveFile
? '.' : '_',
5818 dirnameHash
, basenameHash
);
5821 ret
= dbe_sprintf ("%s%c%s", bname
, archiveFile
? '.' : '_', dirnameHash
);
5826 Experiment::checkFileInArchive (const char *fname
, bool archiveFile
)
5830 char *aname
= get_archived_name (fname
, archiveFile
);
5831 DbeFile
*df
= archiveMap
->get (aname
);
5834 return strdup (df
->get_location ());
5838 return founder_exp
->checkFileInArchive (fname
, archiveFile
);
5846 SegMemCmp (const void *a
, const void *b
)
5848 SegMem
*item1
= *((SegMem
**) a
);
5849 SegMem
*item2
= *((SegMem
**) b
);
5850 return item1
->unload_time
> item2
->unload_time
? 1 :
5851 item1
->unload_time
== item2
->unload_time
? 0 : -1;
5855 Experiment::update_ts_in_maps (Vaddr addr
, hrtime_t ts
)
5857 Vector
<SegMem
*> *segMems
= (Vector
<SegMem
*> *) maps
->values ();
5858 if (!segMems
->is_sorted ())
5860 Dprintf (DEBUG_MAPS
, NTXT ("update_ts_in_maps: segMems.size=%lld\n"), (long long) segMems
->size ());
5861 segMems
->sort (SegMemCmp
);
5863 for (int i
= 0, sz
= segMems
? segMems
->size () : 0; i
< sz
; i
++)
5865 SegMem
*sm
= segMems
->fetch (i
);
5866 if (ts
< sm
->unload_time
)
5870 sm
= segMems
->fetch (i
);
5871 if ((addr
>= sm
->base
) && (addr
< sm
->base
+ sm
->size
))
5873 Dprintf (DEBUG_MAPS
,
5874 "update_ts_in_maps: old:%u.%09u -> %u.%09u addr=0x%08llx size=%lld\n",
5875 (unsigned) (sm
->load_time
/ NANOSEC
),
5876 (unsigned) (sm
->load_time
% NANOSEC
),
5877 (unsigned) (ts
/ NANOSEC
), (unsigned) (ts
% NANOSEC
),
5878 (unsigned long long) sm
->base
, (long long) sm
->size
);
5879 maps
->remove (sm
->base
, sm
->load_time
);
5881 maps
->insert (sm
->base
, ts
, sm
);
5887 Dprintf (DEBUG_MAPS
, "update_ts_in_maps: NOT FOUND %u.%09u addr=0x%08llx\n",
5888 (unsigned) (ts
/ NANOSEC
), (unsigned) (ts
% NANOSEC
),
5889 (unsigned long long) addr
);
5894 Experiment::map_Vaddr_to_PC (Vaddr addr
, hrtime_t ts
)
5896 // Look up in the hash table first
5897 int hash
= (((int) addr
) >> 8) & (HTableSize
- 1);
5898 SegMem
*si
= smemHTable
[hash
];
5899 if (si
== NULL
|| addr
< si
->base
|| addr
>= si
->base
+ si
->size
5900 || ts
< si
->load_time
|| ts
>= si
->unload_time
)
5902 // Not in the hash table
5903 si
= (SegMem
*) maps
->locate (addr
, ts
);
5904 if (si
== NULL
|| addr
< si
->base
|| addr
>= si
->base
+ si
->size
5905 || ts
< si
->load_time
|| ts
>= si
->unload_time
)
5907 si
= update_ts_in_maps (addr
, ts
);
5909 return dbeSession
->get_Unknown_Function ()->find_dbeinstr (PCInvlFlag
, addr
);
5911 smemHTable
[hash
] = si
;
5914 // Calculate the file offset of 'addr'
5915 uint64_t f_offset
= si
->get_file_offset () + (addr
- si
->base
);
5918 if (si
->obj
->get_type () == Histable::LOADOBJECT
)
5920 LoadObject
*lo
= (LoadObject
*) si
->obj
;
5921 lo
->sync_read_stabs ();
5922 instr
= lo
->find_dbeinstr (f_offset
);
5926 int hash2
= ((((int) addr
) & 0xFFFC00) | (((int) f_offset
) >> 2))
5928 instr
= instHTable
[hash2
];
5929 if (instr
== NULL
|| instr
->func
!= si
->obj
|| instr
->addr
!= f_offset
)
5931 // Not in the hash table
5932 Function
*fp
= (Function
*) si
->obj
;
5933 instr
= fp
->find_dbeinstr (0, f_offset
);
5934 instHTable
[hash2
] = instr
;
5937 if (!instr
->func
->isUsed
)
5939 instr
->func
->isUsed
= true;
5940 instr
->func
->module
->isUsed
= true;
5941 instr
->func
->module
->loadobject
->isUsed
= true;
5947 Experiment::map_event_to_Sample (hrtime_t ts
)
5952 // Check if the last used sample is the right one,
5953 // if not then find it.
5954 if (sample_last_used
&& ts
>= sample_last_used
->start_time
5955 && ts
<= sample_last_used
->end_time
)
5956 return sample_last_used
;
5958 Vec_loop (Sample
*, samples
, index
, sample
)
5960 if ((ts
>= sample
->start_time
) &&
5961 (ts
<= sample
->end_time
))
5963 sample_last_used
= sample
;
5967 return (Sample
*) NULL
;
5971 Experiment::map_event_to_GCEvent (hrtime_t ts
)
5976 // Check if the last used sample is the right one,
5977 // if not then find it.
5978 if (gcevent_last_used
&& ts
>= gcevent_last_used
->start
5979 && ts
<= gcevent_last_used
->end
)
5980 return gcevent_last_used
;
5981 Vec_loop (GCEvent
*, gcevents
, index
, gcevent
)
5983 if ((ts
>= gcevent
->start
) &&
5984 (ts
<= gcevent
->end
))
5986 gcevent_last_used
= gcevent
;
5990 return (GCEvent
*) NULL
;
5994 Experiment::map_jmid_to_PC (Vaddr mid
, int bci
, hrtime_t ts
)
5996 if (mid
== 0 || jmaps
== NULL
)
5997 // special case: no Java stack was recorded, bci - error code
5998 return dbeSession
->get_JUnknown_Function ()->find_dbeinstr (0, bci
);
6000 JMethod
*jmthd
= jmidHTable
->get (mid
);
6003 jmthd
= (JMethod
*) jmaps
->locate_exact_match (mid
, ts
);
6005 jmidHTable
->put (mid
, jmthd
);
6007 if (jmthd
== NULL
|| jmthd
->get_type () != Histable::FUNCTION
)
6008 return dbeSession
->get_JUnknown_Function ()->find_dbeinstr (0, (uint64_t) mid
);
6009 return jmthd
->find_dbeinstr (0, bci
);
6013 Experiment::fetch_comments ()
6015 return commentq
->fetch ();
6019 Experiment::fetch_runlogq ()
6021 return runlogq
->fetch ();
6025 Experiment::fetch_errors ()
6027 return errorq
->fetch ();
6031 Experiment::fetch_warnings ()
6033 return warnq
->fetch ();
6037 Experiment::fetch_notes ()
6039 return notesq
->fetch ();
6043 Experiment::fetch_ifreq ()
6045 return ifreqq
->fetch ();
6049 Experiment::fetch_pprocq ()
6051 return pprocq
->fetch ();
6055 Experiment::read_dyntext_file ()
6057 dyntext_name
= dbe_sprintf ("%s/%s", expt_name
, SP_DYNTEXT_FILE
);
6058 Data_window
*dwin
= new Data_window (dyntext_name
);
6059 if (dwin
->not_opened ())
6064 dwin
->need_swap_endian
= need_swap_endian
;
6066 Function
*fp
= NULL
;
6067 char *progress_msg
= NULL
; // Message for the progress bar
6068 for (int64_t offset
= 0;;)
6070 DT_common
*cpckt
= (DT_common
*) dwin
->bind (offset
, sizeof (DT_common
));
6073 size_t cpcktsize
= dwin
->decode (cpckt
->size
);
6074 cpckt
= (DT_common
*) dwin
->bind (offset
, cpcktsize
);
6077 switch (dwin
->decode (cpckt
->type
))
6081 DT_header
*hdr
= (DT_header
*) cpckt
;
6082 hrtime_t ts
= dwin
->decode (hdr
->time
) + exp_start_time
;
6083 SegMem
*si
= (SegMem
*) maps
->locate (dwin
->decode (hdr
->vaddr
), ts
);
6084 fp
= si
? (Function
*) si
->obj
: NULL
;
6085 if (fp
&& (fp
->get_type () != Histable::FUNCTION
6086 || !(fp
->flags
& FUNC_FLAG_DYNAMIC
)))
6093 fp
->img_fname
= dyntext_name
;
6094 fp
->img_offset
= offset
+ sizeof (DT_common
);
6095 if ((platform
!= Intel
) && (platform
!= Amd64
))
6097 // Find out 'save' instruction address for SPARC
6098 char *ptr
= ((char*) cpckt
) + sizeof (DT_common
);
6099 size_t img_size
= cpcktsize
- sizeof (DT_common
);
6100 for (size_t i
= 0; i
< img_size
; i
+= 4)
6101 if (ptr
[i
] == (char) 0x9d && ptr
[i
+ 1] == (char) 0xe3)
6112 char *srcname
= dbe_strndup (((char*) cpckt
) + sizeof (DT_common
),
6113 cpcktsize
- sizeof (DT_common
));
6114 LoadObject
*ds
= fp
->module
? fp
->module
->loadobject
: NULL
;
6115 assert (ds
!= NULL
);
6116 Module
*mod
= dbeSession
->createModule (ds
, NULL
);
6117 mod
->set_file_name (srcname
);
6121 // It's most likely (unknown). Remove fp from it.
6122 long idx
= fp
->module
->functions
->find (fp
);
6124 fp
->module
->functions
->remove (idx
);
6127 mod
->functions
->append (fp
);
6133 DT_lineno
*ltab
= (DT_lineno
*) ((char*) cpckt
+ sizeof (DT_common
));
6134 size_t sz
= (cpcktsize
- sizeof (DT_common
)) / sizeof (DT_lineno
);
6137 // Take care of the progress bar
6138 static int percent
= 0;
6139 static long deltaReport
= sz
/ 100; // 1000;
6140 static long nextReport
= 0;
6141 static long progress_count
= 0;
6142 fp
->pushSrcFile (fp
->getDefSrc (), 0);
6143 for (size_t i
= 0; i
< sz
; i
++)
6145 int lineno
= dwin
->decode (ltab
[i
].lineno
);
6146 if (fp
->usrfunc
!= NULL
)
6148 // Update progress bar
6149 if (dbeSession
->is_interactive ())
6151 if (progress_count
== nextReport
)
6156 if (NULL
== progress_msg
)
6158 progress_msg
= dbe_sprintf (GTXT ("Processing Dynamic Text: %s"),
6159 get_basename (expt_name
));
6161 theApplication
->set_progress (percent
, progress_msg
);
6162 nextReport
+= deltaReport
;
6167 DbeLine
*dbeline
= fp
->usrfunc
->mapPCtoLine (lineno
, NULL
);
6168 lineno
= dbeline
!= NULL
? dbeline
->lineno
: -1;
6170 fp
->add_PC_info (dwin
->decode (ltab
[i
].offset
), lineno
);
6176 // skip unknown records
6179 offset
+= cpcktsize
;
6181 free (progress_msg
);
6187 Experiment::mapTagValue (Prop_type prop
, uint64_t value
)
6189 Vector
<Histable
*> *objs
= tagObjs
->fetch (prop
);
6191 int rt
= objs
->size () - 1;
6194 int md
= (lt
+ rt
) / 2;
6195 Other
*obj
= (Other
*) objs
->fetch (md
);
6196 if (obj
->value64
< value
)
6198 else if (obj
->value64
> value
)
6205 if (sparse_threads
&& (prop
== PROP_THRID
|| prop
== PROP_LWPID
))
6206 tag
= objs
->size () + 1; // "+ 1" related to 7038295
6208 tag
= (int) value
; // truncation; See 6788767
6210 Other
*obj
= new Other ();
6211 obj
->value64
= value
;
6213 if (lt
== objs
->size ())
6216 objs
->insert (lt
, obj
);
6218 // Update min and max tags
6219 if (prop
== PROP_LWPID
)
6221 if ((uint64_t) tag
< min_lwp
)
6222 min_lwp
= (uint64_t) tag
;
6223 if ((uint64_t) tag
> max_lwp
)
6224 max_lwp
= (uint64_t) tag
;
6227 else if (prop
== PROP_THRID
)
6229 if ((uint64_t) tag
< min_thread
)
6230 min_thread
= (uint64_t) tag
;
6231 if ((uint64_t) tag
> max_thread
)
6232 max_thread
= (uint64_t) tag
;
6235 else if (prop
== PROP_CPUID
)
6237 // On Solaris 8, we don't get CPU id -- don't change
6238 if (value
!= (uint64_t) - 1)
6239 {//YXXX is this related only to solaris 8?
6240 if ((uint64_t) tag
< min_cpu
)
6241 min_cpu
= (uint64_t) tag
;
6242 if ((uint64_t) tag
> max_cpu
)
6243 max_cpu
= (uint64_t) tag
;
6251 Experiment::getTagObjs (Prop_type prop
)
6253 return tagObjs
->fetch (prop
);
6257 Experiment::getTagObj (Prop_type prop
, uint32_t tag
)
6259 Vector
<Histable
*> *objs
= tagObjs
->fetch (prop
);
6262 for (int i
= 0; i
< objs
->size (); i
++)
6264 Other
*obj
= (Other
*) objs
->fetch (i
);
6265 if (obj
->tag
== tag
)
6272 Experiment::map_pckt_to_Jthread (uint32_t tid
, hrtime_t tstamp
)
6275 return JTHREAD_DEFAULT
;
6277 int rt
= jthreads_idx
->size () - 1;
6280 int md
= (lt
+ rt
) / 2;
6281 JThread
*jthread
= jthreads_idx
->fetch (md
);
6282 if (jthread
->tid
< tid
)
6284 else if (jthread
->tid
> tid
)
6288 for (; jthread
; jthread
= jthread
->next
)
6289 if (tstamp
>= jthread
->start
&& tstamp
< jthread
->end
)
6295 return JTHREAD_NONE
;
6299 Experiment::get_jthread (uint32_t tid
)
6302 return JTHREAD_DEFAULT
;
6304 int rt
= jthreads_idx
->size () - 1;
6307 int md
= (lt
+ rt
) / 2;
6308 JThread
*jthread
= jthreads_idx
->fetch (md
);
6309 if (jthread
->tid
< tid
)
6311 else if (jthread
->tid
> tid
)
6315 JThread
*jthread_first
= jthread
;
6316 while ((jthread
= jthread
->next
) != NULL
)
6317 if (!jthread
->is_system () &&
6318 jthread
->jthr_id
< jthread_first
->jthr_id
)
6319 jthread_first
= jthread
;
6320 return jthread_first
;
6324 return JTHREAD_NONE
;
6329 Experiment::newDataDescriptor (int data_id
, int flags
,
6330 DataDescriptor
*master_dDscr
)
6332 DataDescriptor
*dataDscr
= NULL
;
6333 if (data_id
>= 0 && data_id
< dataDscrs
->size ())
6335 dataDscr
= dataDscrs
->fetch (data_id
);
6336 if (dataDscr
!= NULL
)
6340 assert (data_id
>= 0 && data_id
< DATA_LAST
);
6341 const char *nm
= get_prof_data_type_name (data_id
);
6342 const char *uname
= get_prof_data_type_uname (data_id
);
6345 dataDscr
= new DataDescriptor (data_id
, nm
, uname
, master_dDscr
);
6347 dataDscr
= new DataDescriptor (data_id
, nm
, uname
, flags
);
6348 dataDscrs
->store (data_id
, dataDscr
);
6352 Vector
<DataDescriptor
*> *
6353 Experiment::getDataDescriptors ()
6355 Vector
<DataDescriptor
*> *result
= new Vector
<DataDescriptor
*>;
6356 for (int i
= 0; i
< dataDscrs
->size (); ++i
)
6359 dd
= get_raw_events (i
); // force data fetch
6361 result
->append (dd
);
6367 Experiment::getDataDescriptor (int data_id
)
6369 if (data_id
< 0 || data_id
>= dataDscrs
->size ())
6371 return dataDscrs
->fetch (data_id
);
6375 Experiment::newPacketDescriptor (int kind
, DataDescriptor
*dDscr
)
6377 PacketDescriptor
*pDscr
= new PacketDescriptor (dDscr
);
6378 pcktDscrs
->store (kind
, pDscr
);
6383 Experiment::getPacketDescriptor (int kind
)
6385 if (kind
< 0 || kind
>= pcktDscrs
->size ())
6387 return pcktDscrs
->fetch (kind
);
6391 Experiment::set_clock (int clk
)
6400 if (minclock
== 0 || minclock
> clk
)
6406 JThread::is_system ()
6408 if (group_name
== NULL
)
6410 return strcmp (group_name
, NTXT ("system")) == 0;
6414 Experiment::dump_stacks (FILE *outfile
)
6416 cstack
->print (outfile
);
6420 Experiment::dump_map (FILE *outfile
)
6424 fprintf (outfile
, GTXT ("Experiment %s\n"), get_expt_name ());
6425 fprintf (outfile
, GTXT ("Address Size (hex) Load time Unload time Checksum Name\n"));
6426 Vec_loop (SegMem
*, seg_items
, index
, s
)
6430 hr2timestruc (&load
, (s
->load_time
- exp_start_time
));
6431 if (load
.tv_nsec
< 0)
6434 load
.tv_nsec
+= NANOSEC
;
6436 if (s
->unload_time
== MAX_TIME
)
6442 hr2timestruc (&unload
, (s
->unload_time
- exp_start_time
));
6443 if (load
.tv_nsec
< 0)
6446 load
.tv_nsec
+= NANOSEC
;
6449 "0x%08llx %8lld (0x%08llx) %5lld.%09lld %5lld.%09lld \"%s\"\n",
6450 (long long) s
->base
, (long long) s
->size
, (long long) s
->size
,
6451 (long long) load
.tv_sec
, (long long) load
.tv_nsec
,
6452 (long long) unload
.tv_sec
, (long long) unload
.tv_nsec
,
6453 s
->obj
->get_name ());
6455 fprintf (outfile
, NTXT ("\n"));
6459 * Copy file to archive
6463 * @return 0 - success, 1 - error
6466 Experiment::copy_file_to_archive (const char *name
, const char *aname
, int hide_msg
)
6469 int fd_w
= ::open64 (aname
, O_WRONLY
| O_CREAT
| O_EXCL
, 0644);
6472 if (errno
== EEXIST
)
6474 fprintf (stderr
, GTXT ("gp-archive: unable to copy `%s': %s\n"),
6475 name
, STR (strerror (errno
)));
6479 if (dbe_stat_file (name
, NULL
) != 0)
6481 fprintf (stderr
, GTXT ("gp-archive: cannot access file `%s': %s\n"),
6482 name
, STR (strerror (errno
)));
6487 int fd_r
= ::open64 (name
, O_RDONLY
);
6490 fprintf (stderr
, GTXT ("gp-archive: unable to open `%s': %s\n"),
6491 name
, strerror (errno
));
6498 fprintf (stderr
, GTXT ("Copying `%s' to `%s'\n"), name
, aname
);
6499 bool do_unlink
= false;
6502 unsigned char buf
[65536];
6504 n
= (int) read (fd_r
, (void *) buf
, sizeof (buf
));
6507 n1
= (int) write (fd_w
, buf
, n
);
6510 fprintf (stderr
, GTXT ("gp-archive: unable to write %d bytes to `%s': %s\n"),
6511 n
, aname
, STR (strerror (errno
)));
6519 if (fstat64 (fd_r
, &s_buf
) == 0)
6521 struct utimbuf u_buf
;
6522 u_buf
.actime
= s_buf
.st_atime
;
6523 u_buf
.modtime
= s_buf
.st_mtime
;
6524 utime (aname
, &u_buf
);
6530 fprintf (stderr
, GTXT ("gp-archive: remove %s\n"), aname
);
6538 * Copy file to common archive
6540 * Calculate checksum
6541 * Generate file name to be created in common archive
6542 * Check if it is not in common archive yet
6543 * Copy file to the common archive directory if it is not there yet
6544 * Create symbolic link: "aname" -> "caname", where "caname" is the name in common archive
6545 * @param name - original file name
6546 * @param aname - file name in experiment archive
6547 * @param common_archive - common archive directory
6548 * @return 0 - success, 1 - error
6551 Experiment::copy_file_to_common_archive (const char *name
, const char *aname
,
6553 const char *common_archive
,
6556 if (!name
|| !aname
|| !common_archive
)
6559 fprintf (stderr
, GTXT ("gp-archive: Internal error: file name is NULL\n"));
6561 fprintf (stderr
, GTXT ("gp-archive: Internal error: file name in archive is NULL\n"));
6562 if (!common_archive
)
6563 fprintf (stderr
, GTXT ("gp-archive: Internal error: path to common archive is NULL\n"));
6566 // Check if file is already archived
6567 if (dbe_stat (aname
, NULL
) == 0)
6568 return 0; // File is already archived
6569 // Generate full path to common archive directory
6571 char *abs_aname
= NULL
;
6572 if ((common_archive
[0] != '/') || (aname
[0] != '/'))
6574 long size
= pathconf (NTXT ("."), _PC_PATH_MAX
);
6577 fprintf (stderr
, GTXT ("gp-archive: Fatal error: pathconf(\".\", _PC_PATH_MAX) failed\n"));
6580 char *buf
= (char *) malloc ((size_t) size
);
6583 fprintf (stderr
, GTXT ("gp-archive: Fatal error: unable to allocate memory\n"));
6586 char *ptr
= getcwd (buf
, (size_t) size
);
6589 fprintf (stderr
, GTXT ("gp-archive: Fatal error: cannot determine current directory\n"));
6593 if (common_archive
[0] != '/')
6594 cad
= dbe_sprintf (NTXT ("%s/%s"), ptr
, common_archive
);
6596 cad
= dbe_strdup (common_archive
);
6597 if (aname
[0] != '/')
6598 abs_aname
= dbe_sprintf (NTXT ("%s/%s"), ptr
, aname
);
6600 abs_aname
= dbe_strdup (aname
);
6605 cad
= dbe_strdup (common_archive
);
6606 abs_aname
= dbe_strdup (aname
);
6608 // Calculate checksum
6609 char * errmsg
= NULL
;
6610 uint32_t crcval
= get_cksum (name
, &errmsg
);
6617 fprintf (stderr
, GTXT ("gp-archive: Fatal error: %s\n"), errmsg
);
6622 GTXT ("gp-archive: Fatal error: get_cksum(%s) returned %d\n"),
6626 // Generate file name to be created in common archive
6627 char *fname
= get_basename (name
);
6628 char *abs_caname
= dbe_sprintf (NTXT ("%s/%u_%s"), cad
, crcval
, fname
);
6629 if (abs_caname
== NULL
)
6634 GTXT ("gp-archive: Fatal error: unable to allocate memory\n"));
6637 // Check if full name is not too long
6638 long len
= dbe_sstrlen (abs_caname
);
6639 long max
= pathconf (cad
, _PC_PATH_MAX
);
6640 if ((max
< 0) || (len
<= 0))
6642 fprintf (stderr
, GTXT ("gp-archive: Fatal error: pathconf(%s, _PC_PATH_MAX) failed\n"),
6651 // Try to truncate the name
6652 if ((len
- max
) <= dbe_sstrlen (fname
))
6654 // Yes, we can do it
6655 abs_caname
[max
- 1] = 0;
6657 fprintf (stderr
, GTXT ("gp-gp-archive: file path is too long - truncated:%s\n"),
6661 // Check if file name is not too long
6662 char *cafname
= get_basename (abs_caname
);
6663 len
= dbe_sstrlen (cafname
);
6664 max
= pathconf (cad
, _PC_NAME_MAX
);
6665 if ((max
< 0) || (len
<= 0))
6667 fprintf (stderr
, GTXT ("gp-archive: Fatal error: pathconf(%s, _PC_NAME_MAX) failed\n"),
6676 // Try to truncate the name
6677 if ((len
- max
) <= dbe_sstrlen (fname
))
6679 // Yes, we can do it
6680 cafname
[max
- 1] = 0;
6682 fprintf (stderr
, GTXT ("gp-archive: file name is too long - truncated:%s\n"),
6686 // Copy file to the common archive directory if it is not there yet
6688 if (dbe_stat_file (abs_caname
, NULL
) != 0)
6690 // Use temporary file to avoid synchronization problems
6691 char *t
= dbe_sprintf ("%s/archive_%llx", cad
, (unsigned long long) gethrtime());
6693 // Copy file to temporary file
6694 res
= copy_file_to_archive (name
, t
, hide_msg
); // hide messages
6697 fprintf (stderr
, GTXT ("gp-archive: Fatal error: cannot copy file %s to temporary file: %s\n"),
6705 // Set read-only permissions
6707 if (0 == dbe_stat_file (name
, &statbuf
))
6709 mode_t mask
= S_IRUSR
| S_IXUSR
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH
;
6710 mode_t mode
= statbuf
.st_mode
& mask
;
6713 // Try to rename temporary file "t" to "abs_caname"
6714 // res = link(t, abs_caname); // link() fails on some f/s - use rename()
6715 res
= rename (t
, abs_caname
);
6718 if (errno
!= EEXIST
)
6720 fprintf (stderr
, GTXT ("gp-archive: Fatal error: rename(%s, %s) returned error: %d\n"),
6721 t
, abs_caname
, res
);
6728 // File "abs_caname" is already there - continue
6738 if (common_archive
[0] != '/' && aname
[0] != '/')
6740 // compare one relative path to another and find common beginning
6741 char *rel_caname
= dbe_sprintf ("%s/%s", common_archive
, cafname
);
6742 if (rel_caname
== NULL
)
6744 fprintf (stderr
, GTXT ("gp-archive: Fatal error: unable to allocate memory\n"));
6747 lname
= get_relative_link (rel_caname
, aname
);
6752 if (abs_aname
== NULL
)
6754 fprintf (stderr
, GTXT ("gp-archive: Fatal error: unable to allocate memory\n"));
6757 lname
= get_relative_link (abs_caname
, abs_aname
);
6760 else // absolute path
6761 lname
= dbe_strdup (abs_caname
);
6765 fprintf (stderr
, GTXT ("gp-archive: Fatal error: unable to allocate memory\n"));
6768 // Create symbolic link: aname -> lname
6769 if (dbe_stat_file (abs_caname
, NULL
) == 0)
6771 res
= symlink (lname
, aname
);
6774 fprintf (stderr
, GTXT ("gp-archive: Fatal error: symlink(%s, %s) returned error: %d (errno=%s)\n"),
6775 lname
, aname
, res
, strerror (errno
));
6781 fprintf (stderr
, GTXT ("Created symbolic link %s to file in common archive: %s\n"),
6786 fprintf (stderr
, GTXT ("gp-archive: Internal error: file does not exist in common archive: %s\n"),
6796 * Copy file to archive
6800 * @param common_archive
6801 * @return 0 - success
6804 Experiment::copy_file (char *name
, char *aname
, int hide_msg
, char *common_archive
, int relative_path
)
6808 if (0 == copy_file_to_common_archive (name
, aname
, hide_msg
,
6809 common_archive
, relative_path
))
6811 // Error. For now - fatal error. Message is already printed.
6812 fprintf (stderr
, GTXT ("gp-archive: Fatal error: cannot copy file %s to common archive %s\n"),
6813 name
, common_archive
);
6816 return (copy_file_to_archive (name
, aname
, hide_msg
));
6820 Experiment::createLoadObject (const char *path
, uint64_t chksum
)
6822 LoadObject
*lo
= dbeSession
->createLoadObject (path
, chksum
);
6823 if (lo
->firstExp
== NULL
)
6824 lo
->firstExp
= this;
6829 Experiment::createLoadObject (const char *path
, const char *runTimePath
)
6831 DbeFile
*df
= findFileInArchive (path
, runTimePath
);
6832 if (df
&& (df
->get_stat () == NULL
))
6833 df
= NULL
; // No access to file
6834 LoadObject
*lo
= dbeSession
->createLoadObject (path
, runTimePath
, df
);
6835 if (df
&& (lo
->dbeFile
->get_location (false) == NULL
))
6837 lo
->dbeFile
->set_location (df
->get_location ());
6838 lo
->dbeFile
->inArchive
= df
->inArchive
;
6839 lo
->dbeFile
->sbuf
= df
->sbuf
;
6840 lo
->dbeFile
->experiment
= df
->experiment
;
6841 lo
->firstExp
= df
->experiment
;
6843 if (lo
->firstExp
== NULL
)
6845 lo
->firstExp
= this;
6846 lo
->dbeFile
->experiment
= this;
6852 Experiment::get_source (const char *path
)
6854 if (founder_exp
&& (founder_exp
!= this))
6855 return founder_exp
->get_source (path
);
6856 if (sourcesMap
== NULL
)
6857 sourcesMap
= new StringMap
<SourceFile
*>(1024, 1024);
6858 if (strncmp (path
, NTXT ("./"), 2) == 0)
6860 SourceFile
*sf
= sourcesMap
->get (path
);
6863 char *fnm
= checkFileInArchive (path
, false);
6866 sf
= new SourceFile (path
);
6867 dbeSession
->append (sf
);
6868 DbeFile
*df
= sf
->dbeFile
;
6869 df
->set_location (fnm
);
6870 df
->inArchive
= true;
6871 df
->check_access (fnm
); // init 'sbuf'
6872 df
->sbuf
.st_mtime
= 0; // Don't check timestamps
6876 sf
= dbeSession
->createSourceFile (path
);
6877 sourcesMap
->put (path
, sf
);
6882 Experiment::get_comparable_objs ()
6884 update_comparable_objs ();
6885 if (comparable_objs
|| dbeSession
->expGroups
->size () <= 1)
6886 return comparable_objs
;
6887 comparable_objs
= new Vector
<Histable
*>(dbeSession
->expGroups
->size ());
6888 for (long i
= 0, sz
= dbeSession
->expGroups
->size (); i
< sz
; i
++)
6890 ExpGroup
*gr
= dbeSession
->expGroups
->get (i
);
6891 if (groupId
== gr
->groupId
)
6893 comparable_objs
->append (this);
6897 for (long i1
= 0, sz1
= gr
->exps
? gr
->exps
->size () : 0; i1
< sz1
; i1
++)
6899 Experiment
*exp
= gr
->exps
->get (i1
);
6900 if ((exp
->comparable_objs
== NULL
) && (dbe_strcmp (utargname
, exp
->utargname
) == 0))
6902 exp
->phaseCompareIdx
= phaseCompareIdx
;
6904 h
->comparable_objs
= comparable_objs
;
6908 comparable_objs
->append (h
);
6910 dump_comparable_objs ();
6911 return comparable_objs
;
6915 Experiment::findFileInArchive (const char *fname
)
6919 char *aname
= get_archived_name (fname
);
6920 DbeFile
*df
= archiveMap
->get (aname
);
6925 return founder_exp
->findFileInArchive (fname
);
6930 Experiment::findFileInArchive (const char *className
, const char *runTimePath
)
6935 const char *fnm
= NULL
;
6936 if (strncmp (runTimePath
, NTXT ("zip:"), 4) == 0)
6937 fnm
= runTimePath
+ 4;
6938 else if (strncmp (runTimePath
, NTXT ("jar:file:"), 9) == 0)
6939 fnm
= runTimePath
+ 9;
6942 const char *s
= strchr (fnm
, '!');
6945 char *s1
= dbe_strndup (fnm
, s
- fnm
);
6946 df
= findFileInArchive (s1
);
6950 df
= findFileInArchive (fnm
);
6952 df
->filetype
|= DbeFile::F_JAR_FILE
;
6954 else if (strncmp (runTimePath
, NTXT ("file:"), 5) == 0)
6956 fnm
= runTimePath
+ 5;
6957 df
= findFileInArchive (fnm
);
6960 df
= findFileInArchive (runTimePath
);
6963 df
= findFileInArchive (className
);