summaryrefslogtreecommitdiff
path: root/gprofng/src/Experiment.h
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src/Experiment.h')
-rw-r--r--gprofng/src/Experiment.h689
1 files changed, 689 insertions, 0 deletions
diff --git a/gprofng/src/Experiment.h b/gprofng/src/Experiment.h
new file mode 100644
index 00000000000..41c44e4a08a
--- /dev/null
+++ b/gprofng/src/Experiment.h
@@ -0,0 +1,689 @@
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+ Contributed by Oracle.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#ifndef _EEXPERIMENT_H
+#define _EEXPERIMENT_H
+
+// The experiment class is responsible for managing all the data
+// for an individual experiment
+
+#include "Metric.h"
+#include "Histable.h"
+#include "Stats_data.h"
+#include "DefaultMap.h"
+#include "HeapMap.h"
+
+class Data_window;
+class DbeFile;
+class CallStack;
+class JMethod;
+class Sample;
+class SegMem;
+class LoadObject;
+class SourceFile;
+class UserLabel;
+class PRBTree;
+class Emsg;
+class Emsgqueue;
+struct JThread;
+struct GCEvent;
+class FileData;
+class Module;
+class Experiment;
+template <class ITEM> class Vector;
+
+#define JTHREAD_DEFAULT ((JThread*)0)
+#define JTHREAD_NONE ((JThread*)-1)
+
+// When we perform the pipelined optimization on resolve_frame_info() and add_stack()
+// this is the number of iterations one phase works on before passing on the work to
+// the next phase
+
+#define CSTCTX_CHUNK_SZ 10000
+#define PIPELINE_QUEUE_SZ_HI 8
+#define PIPELINE_QUEUE_SZ_LOW 2
+
+// the add_stack_ctx structure contains the intermediate state (context) after
+// CSTCTX_CHUNK_SZ number of iterations to pass on the work to another thread to
+// operate on the next stage
+typedef struct
+{
+ Vector<DbeInstr*> *natpcs;
+ Vector<Histable*> *jpcs;
+ long idx;
+ FramePacket *frp;
+ hrtime_t tstamp;
+ uint32_t thrid;
+ bool last_ctx;
+} cstk_ctx;
+
+// To minimize threadpool overhead, the granularity of a job submitted is made larger:
+// containing a chunk of iterations (of size CSTCTX_CHUNK_SZ)
+typedef struct
+{
+ cstk_ctx* cstCtxAr[CSTCTX_CHUNK_SZ];
+ int last_idx;
+ long idx_begin;
+ long idx_end;
+ DataDescriptor *dDscr;
+ Experiment *exp;
+ void *cstk;
+} cstk_ctx_chunk;
+
+class Experiment : public Histable, public DbeMessages
+{
+public:
+
+ enum Exp_status
+ {
+ SUCCESS,
+ INCOMPLETE,
+ FAILURE
+ };
+
+ Experiment ();
+ virtual ~Experiment ();
+
+ virtual Histable_type
+ get_type ()
+ {
+ return EXPERIMENT;
+ };
+ virtual Vector<Histable*> *get_comparable_objs ();
+
+ int groupId;
+ Experiment *founder_exp; // parent of this experiment
+ Vector<Experiment*> *children_exps; // children of this experiment
+
+ // Configuration Information
+ char *hostname; // Hosthame (e.g. mymachine)
+ long start_sec; // Starting timeval secs.
+ char *username; // name of person performing the test
+ char *architecture; // Architecture name ("sun4")
+ Platform_t platform; // Sparc,Sparcv9,Intel
+ WSize_t wsize; // word size: may be w32 or w64
+ int clock; // CPU clock frequency, Mhz
+ int varclock; // Set if CPU clock frequency can change: turbo-mode
+ int maxclock; // max. CPU clock frequency on MP machine
+ int minclock; // min. CPU clock frequency on MP machine
+ int ncpus; // count of CPUs where expt was recorded
+ int hw_cpuver; // CPU version from libcpc
+ char *machinemodel; // machine model of machine on which experiment was recorded
+ char *os_version; // Operating system name
+ int page_size; // Page size (bytes)
+ int npages; // Number of page size
+ int exp_maj_version; // major version number of current experiment
+ int exp_min_version; // minor version number of current experiment
+ int hex_field_width; // number of digits in hex form of address
+ // for current experiment, i.e. 8 for 32bit addresses
+ int broken; // If SP_JCMD_RUN line not seen
+ int obsolete; // If pointer file experiment detected
+ bool hwc_default; // True if HW counters were enabled by default
+ int hwc_bogus; // Count of bogus HWC packets
+ int hwc_lost_int; // Count of packets reflecting lost interrupt
+ int hwc_scanned; // If the HWC packets have been scanned
+ int invalid_packet; // Count of invalid packets
+ bool exec_started; // True if exec was called, and exec error not yet seen
+ bool dataspaceavail; // True if dataspace data is in the experiment
+ bool leaklistavail; // True if leaklist data is in the experiment
+ bool heapdataavail; // True if heap data is in the experiment
+ bool racelistavail; // true if there are race events in the experiment
+ bool iodataavail; // true if there are io events in the experiment
+ bool deadlocklistavail; // true if there are deadlock events in the experiment
+ bool timelineavail; // true if there are valid timestamps in the experiment
+ bool ifreqavail; // True if instruction-frequency data is in the experiment
+ bool ompavail; // true if there is OpenMP data in the experiment
+ bool has_java;
+ char *uarglist; // argv[] array, as a string
+ char *utargname; // basename of argv[0] extracted from uarglist
+ char *ucwd; // working directory
+ char *cversion; // collector version string
+ char *dversion; // driver version string (er_kernel)
+ char *jversion; // Java version string (java profiling)
+
+ // Open the named experiment record and process log file
+ Exp_status open (char *directory_name);
+
+ // Update experiment (read and process new data)
+ Exp_status update ();
+
+ // Returns collector parameters for the current sample selection
+ Collection_params *
+ get_params ()
+ {
+ return &coll_params;
+ }
+
+ Exp_status
+ get_status ()
+ {
+ return status;
+ }
+
+ // Returns the number of samples. For use by FilterNumeric
+ int
+ nsamples ()
+ {
+ return samples->size ();
+ }
+
+ // Release any releasable memory.
+ void purge ();
+
+ void resetShowHideStack ();
+ int save_notes (char*, bool);
+ int delete_notes (bool);
+ Experiment *getBaseFounder (); // returns topmost founder or this if no descendents
+
+ hrtime_t
+ getStartTime ()
+ {
+ return exp_start_time;
+ }
+ hrtime_t getRelativeStartTime (); // delta between start and founder's start
+
+ hrtime_t
+ getWallStartSec ()
+ {
+ return start_sec;
+ }
+
+ hrtime_t
+ getLastEvent ()
+ {
+ if (last_event != ZERO_TIME)
+ return last_event;
+ return exp_start_time;
+ }
+
+ hrtime_t
+ getGCDuration ()
+ {
+ return gc_duration;
+ }
+
+ int
+ getPID ()
+ {
+ return pid;
+ }
+
+ int
+ getUserExpId ()
+ {
+ return userExpId;
+ }
+
+ int
+ getExpIdx ()
+ {
+ return expIdx;
+ }
+
+ void
+ setExpIdx (int idx)
+ {
+ expIdx = idx;
+ }
+
+ void
+ setUserExpId (int idx)
+ {
+ userExpId = idx;
+ }
+
+ void
+ setTinyThreshold (int limit)
+ {
+ tiny_threshold = limit;
+ }
+
+ bool
+ isDiscardedTinyExperiment ()
+ {
+ return discardTiny;
+ }
+
+ Exp_status open_epilogue ();
+ void read_experiment_data (bool read_ahead);
+ static int copy_file_to_archive (const char *name, const char *aname, int hide_msg);
+ static int copy_file_to_common_archive (const char *name, const char *aname,
+ int hide_msg, const char *common_archive, int relative_path = 0);
+ static int copy_file (char *name, char *aname, int hide_msg,
+ char *common_archive = NULL, int relative_path = 0);
+
+ // get_raw_events()
+ // action: get unfiltered packets, loading them if required
+ // parameters: data_id (see ProfData_type)
+ DataDescriptor *get_raw_events (int data_id);
+ Vector<DataDescriptor*> *getDataDescriptors ();
+
+ // Some DATA_* types are derived from others, e.g. DATA_HEAPSZ is derived from DATA_HEAP
+ // The following hooks support derived DataViews
+ int base_data_id (int data_id); // returns base data_id type (ProfData_type DATA_*)
+ DataView *create_derived_data_view (int data_id, DataView *dview);
+
+ Vector<BaseMetric*>*
+ get_metric_list ()
+ {
+ return metrics;
+ }
+
+ char *
+ get_expt_name ()
+ {
+ return expt_name; // Return the pathname to the experiment
+ };
+
+ Vector<char*> *get_descendants_names ();
+ char *get_fndr_arch_name ();
+ char *get_arch_name ();
+ char *getNameInArchive (const char *fname, bool archiveFile = false);
+ char *checkFileInArchive (const char *fname, bool archiveFile = false);
+ DbeFile *findFileInArchive (const char *className, const char *runTimePath);
+ DbeFile *findFileInArchive (const char *fname);
+ bool create_dir (char *dname);
+
+ Vaddr
+ ret_stack_base ()
+ {
+ return stack_base;
+ };
+
+ // Map a virtual address to a PC pair
+ DbeInstr *map_Vaddr_to_PC (Vaddr addr, hrtime_t ts);
+ DbeInstr *map_jmid_to_PC (Vaddr mid, int lineno, hrtime_t ts);
+ Sample *map_event_to_Sample (hrtime_t ts);
+ GCEvent *map_event_to_GCEvent (hrtime_t ts);
+
+ DataView *
+ getOpenMPdata ()
+ {
+ return openMPdata;
+ }
+
+ time_t
+ get_mtime ()
+ {
+ return mtime;
+ }
+
+ Emsg *fetch_comments (void); // fetch the queue of comment messages
+ Emsg *fetch_runlogq (void); // fetch the queue of run log messages
+ Emsg *fetch_errors (void); // fetch the queue of error messages
+ Emsg *fetch_warnings (void); // fetch the queue of warning messages
+ Emsg *fetch_notes (void); // fetch the queue of notes messages
+ Emsg *fetch_ifreq (void); // fetch the queue of ifreq messages
+ Emsg *fetch_pprocq (void); // fetch the queue of post-processing messages
+
+ // message queues
+ Emsgqueue *commentq; // comments for the experiment header
+ Emsgqueue *runlogq; // used temporarily; after log file processing,
+ // messages are appended to the commentq
+ Emsgqueue *errorq; // error messages
+ Emsgqueue *warnq; // warning messages
+ Emsgqueue *notesq; // user-written notes messages
+ Emsgqueue *pprocq; // postprocessing messages
+ Emsgqueue *ifreqq; // Instruction frequency data, from count experiment
+ Map<const char*, LoadObject*> *loadObjMap;
+ Vector<LoadObject*> *loadObjs;
+ void append (LoadObject *lo);
+ LoadObject *createLoadObject (const char *path, uint64_t chksum = 0);
+ LoadObject *createLoadObject (const char *path, const char *runTimePath);
+ SourceFile *get_source (const char *path);
+ void set_clock (int clk);
+
+ CallStack *
+ callTree ()
+ {
+ return cstack;
+ }
+
+ CallStack *
+ callTreeShowHide ()
+ {
+ return cstackShowHide;
+ }
+
+ uint32_t mapTagValue (Prop_type, uint64_t value);
+ Histable *getTagObj (Prop_type, uint32_t idx);
+ Vector<Histable*> *getTagObjs (Prop_type);
+
+ JThread *map_pckt_to_Jthread (uint32_t tid, hrtime_t tstamp);
+ JThread *get_jthread (uint32_t tid);
+
+ Vector<JThread*> *
+ get_jthreads ()
+ {
+ return jthreads;
+ }
+
+ Vector<GCEvent*> *
+ get_gcevents ()
+ {
+ return gcevents;
+ }
+
+ bool need_swap_endian;
+ Collection_params coll_params; // Collection params
+
+ // Ranges for threads, lwps, cpu
+ uint64_t min_thread;
+ uint64_t max_thread;
+ uint64_t thread_cnt;
+ uint64_t min_lwp;
+ uint64_t max_lwp;
+ uint64_t lwp_cnt;
+ uint64_t min_cpu;
+ uint64_t max_cpu;
+ uint64_t cpu_cnt;
+ uint64_t dsevents; // count of dataspace events
+ uint64_t dsnoxhwcevents; /* count of ds events that could be be validated
+ * because of no branch target info */
+
+ PacketDescriptor *newPacketDescriptor (int kind, DataDescriptor *dDscr);
+ PacketDescriptor *getPacketDescriptor (int kind);
+
+ // debugging aids -- dump_stacks, dump_map
+ void dump_stacks (FILE *);
+ void dump_map (FILE *);
+
+ // These methods are used in nightly performance regression testing
+ void DBG_memuse (Sample *);
+ void DBG_memuse (const char *sname);
+ void init_cache ();
+
+ DefaultMap<int64_t, FileData*> *
+ getFDataMap ()
+ {
+ return fDataMap;
+ }
+ CallStack *cstack;
+
+protected:
+
+ Exp_status status; // Error status
+ Vector<SegMem*> *seg_items; // Master list of seg_items
+ CallStack *cstackShowHide;
+ PRBTree *maps; // All maps in (Vaddr,time)
+
+ hrtime_t gc_duration; // wall-clock hrtime of total GC intervals
+ hrtime_t exp_start_time; // wall-clock hrtime at exp start
+ hrtime_t last_event; // wall-clock hrtime of last known sample or log.xml entry
+ hrtime_t non_paused_time; // sum of periods where data collection is active (not paused)
+ hrtime_t resume_ts; // tracks log.xml start/resume times
+ void update_last_event (hrtime_t ts /*wall time (not 0-based)*/);
+
+ char *expt_name; // name of experiment
+ char *arch_name; // <experiment>/archive
+ char *fndr_arch_name; // <founder_experiment>/archive
+ //TBR? hrtime_t sample_time; // total of sample durations
+ int yyparse (); // Allow yyparse actions to access
+ Vaddr stack_base; // Stack base
+
+ // Write experiment header to comment queue
+ void write_header ();
+ void write_coll_params ();
+
+ Exp_status find_expdir (char *directory_name);
+
+ // Invoke the parser to process a file.
+ void read_data_file (const char*, const char*);
+ int read_log_file ();
+ void read_labels_file ();
+ void read_notes_file ();
+ void read_archives ();
+ int read_java_classes_file ();
+ void read_map_file ();
+ int read_overview_file ();
+ int read_dyntext_file ();
+ void read_omp_file ();
+ void read_omp_preg ();
+ void read_omp_task ();
+ void read_ifreq_file ();
+ void read_frameinfo_file ();
+
+ // Functions to process the log and loadobjects file entries
+ // They are deliberately made virtual to overload them
+ // in er_export.
+ virtual int process_arglist_cmd (char *, char *);
+ virtual int process_desc_start_cmd (char *, hrtime_t, char *, char *, int, char *);
+ virtual int process_desc_started_cmd (char *, hrtime_t, char *, char *, int, char *);
+ virtual int process_fn_load_cmd (Module *mod, char *fname, Vaddr vaddr, int fsize, hrtime_t ts);
+ virtual int process_fn_unload_cmd (char *, Vaddr, hrtime_t);
+ virtual int process_hwcounter_cmd (char *, int, char *, char *, int, int, int, char *);
+ virtual int process_hwsimctr_cmd (char *, int, char *, char *, char*, int, int, int, int, int);
+ virtual int process_jcm_load_cmd (char*, Vaddr, Vaddr, int, hrtime_t);
+ virtual int process_jcm_unload_cmd (char*, Vaddr, hrtime_t);
+ virtual int process_Linux_kernel_cmd (hrtime_t);
+ virtual int process_jthr_end_cmd (char *, uint64_t, Vaddr, Vaddr, hrtime_t);
+ virtual int process_jthr_start_cmd (char *, char *, char *, char *, uint64_t, Vaddr, Vaddr, hrtime_t);
+ virtual int process_gc_end_cmd (hrtime_t);
+ virtual int process_gc_start_cmd (hrtime_t);
+ virtual int process_sample_cmd (char *, hrtime_t, int id, char *lbl);
+ virtual int process_sample_sig_cmd (char *, int);
+ virtual int process_seg_map_cmd (char *, hrtime_t, Vaddr, int, int, int64_t, int64_t, int64_t, char *);
+ virtual int process_seg_unmap_cmd (char *, hrtime_t, Vaddr);
+
+ // creation time for experiment
+ time_t mtime;
+ hrtime_t exp_rel_start_time; // start of exp. relative to founder
+ bool exp_rel_start_time_set;
+ Vector<UserLabel*> *userLabels; // List of er_labels
+ int userExpId; // user value for EXPID
+ int expIdx; // DbeSession exp identifier
+ PRBTree *jmaps; // JAVA_CLASSES: (id,time)->Histable
+ Experiment* baseFounder; // outermost experiment (null until lazily computed)
+
+ // Represents a file in experiment
+ class ExperimentFile;
+
+ // XML handler to parse various experiment files
+ class ExperimentHandler;
+ class ExperimentLabelsHandler;
+
+ uint64_t readPacket (Data_window *dwin, Data_window::Span *span);
+ void readPacket (Data_window *dwin, char *ptr, PacketDescriptor *pDscr,
+ DataDescriptor *dDscr, int arg, uint64_t pktsz);
+
+ // read data
+ DataDescriptor *get_profile_events ();
+ DataDescriptor *get_sync_events ();
+ DataDescriptor *get_hwc_events ();
+ DataDescriptor *get_heap_events ();
+ DataDescriptor *get_heapsz_events ();
+ DataDescriptor *get_iotrace_events ();
+ DataDescriptor *get_race_events ();
+ DataDescriptor *get_deadlock_events ();
+ DataDescriptor *get_sample_events ();
+ DataDescriptor *get_gc_events ();
+ DataDescriptor *getDataDescriptor (int data_id);
+ DataDescriptor *newDataDescriptor (int data_id, int flags = 0,
+ DataDescriptor *master_dDscr = NULL);
+
+ // Frame info data structures and methods
+ struct UIDnode;
+ struct RawFramePacket;
+
+ Vector<RawFramePacket*>*frmpckts; // frame info data
+ static int frUidCmp (const void*, const void*);
+ RawFramePacket *find_frame_packet (uint64_t uid);
+
+ static const int CHUNKSZ = 16384;
+ long nnodes;
+ long nchunks;
+ UIDnode **chunks;
+ UIDnode **uidHTable;
+ Vector<UIDnode*> *uidnodes;
+ bool resolveFrameInfo;
+ bool discardTiny;
+ int tiny_threshold; /* optimize away tiny experiments which ran
+ * for less than specified time (ms): default 0 */
+
+ static int uidNodeCmp (const void *a, const void *b);
+ UIDnode *add_uid (Data_window *dwin, uint64_t uid, int size, uint32_t *array, uint64_t link_uid);
+ UIDnode *add_uid (Data_window *dwin, uint64_t uid, int size, uint64_t *array, uint64_t link_uid);
+ UIDnode *new_uid_node (uint64_t uid, uint64_t val);
+ UIDnode *get_uid_node (uint64_t uid, uint64_t val);
+ UIDnode *get_uid_node (uint64_t uid);
+ UIDnode *find_uid_node (uint64_t uid);
+
+ ExperimentFile *logFile;
+
+ // Data descriptors
+ Vector<DataDescriptor*> *dataDscrs;
+ Vector<PacketDescriptor*> *pcktDscrs;
+ long blksz; // binary data file block size
+
+ // Processed data packets
+ DataView *openMPdata; // OMP fork events
+
+ // Map events to OpenMP parallel regions and tasks
+ Map2D<uint32_t, hrtime_t, uint64_t> *mapPRid;
+ Map2D<uint32_t, hrtime_t, void*> *mapPReg;
+ Map2D<uint32_t, hrtime_t, void*> *mapTask;
+
+ // Archive content
+ Map<const char*, DbeFile *> *archiveMap;
+ Map<const char*, SourceFile*>*sourcesMap;
+
+ void init ();
+ void fini ();
+ void post_process ();
+ void constructJavaStack (FramePacket *, UIDnode *, Map<uint64_t, uint64_t> *);
+ void resolve_frame_info (DataDescriptor*);
+ void cleanup_cstk_ctx_chunk ();
+ void register_metric (Metric::Type type);
+ void register_metric (Hwcentry *ctr, const char* aux, const char* username);
+
+ Sample *sample_last_used;
+ GCEvent *gcevent_last_used;
+ char *first_sample_label;
+ Module *get_jclass (const char *className, const char *fileName);
+ LoadObject *get_j_lo (const char *className, const char *fileName);
+
+ Vector<BaseMetric*> *metrics;
+ Vector<JThread*> *jthreads; // master list of Java threads
+ Vector<JThread*> *jthreads_idx; // index in the master list
+ Vector<GCEvent*> *gcevents;
+ Vector<UnmapChunk*> *heapUnmapEvents;
+ Vector<Sample*> *samples; // Array of Sample pointers
+
+ DefaultMap<int64_t, FileData*> *fDataMap; // list of FileData objects using the virtual File descriptor as the key
+ DefaultMap<int, int64_t> *vFdMap; // list of virtual file descrptors using the file descriptor as the key
+
+ Vector<Vector<Histable*>*> *tagObjs; // tag objects
+ bool sparse_threads;
+
+ SegMem **smemHTable; // hash table for SegMem's
+ DbeInstr **instHTable; // hash table for DbeInstr
+ Map<unsigned long long, JMethod*> *jmidHTable; // hash table for jmid
+
+ // identity of target process
+ int pid;
+ int ppid;
+ int pgrp;
+ int sid;
+
+ // Map file processing related data
+ struct MapRecord
+ {
+
+ enum
+ {
+ LOAD, UNLOAD
+ } kind;
+ Histable *obj;
+ Vaddr base;
+ Size size;
+ hrtime_t ts;
+ uint64_t foff;
+ };
+
+ void mrec_insert (MapRecord *mrec);
+ SegMem *update_ts_in_maps (Vaddr addr, hrtime_t ts);
+ int read_warn_file ();
+ LoadObject *get_dynfunc_lo (const char *loName);
+ Function *create_dynfunc (Module *mod, char *fname, int64_t vaddr, int64_t fsize);
+ char *get_archived_name (const char *fname, bool archiveFile = false);
+
+ Vector<MapRecord*> *mrecs;
+
+private:
+ void add_evt_time_to_profile_events (DataDescriptor *dDscr);
+ DataView *create_heapsz_data_view (DataView *heap_dview);
+ void compute_heapsz_data_view (DataView *heapsz_dview);
+};
+
+struct JThread
+{
+ JThread *next;
+ char *name;
+ char *group_name;
+ char *parent_name;
+ uint32_t tid; // system thread id
+ Vaddr jthr; // recorded Java thread id
+ Vaddr jenv; // recorded JNIEnv id
+ uint32_t jthr_id; // internal JThread object id
+ hrtime_t start;
+ hrtime_t end;
+
+ JThread ()
+ {
+ name = NULL;
+ group_name = NULL;
+ parent_name = NULL;
+ }
+
+ ~JThread ()
+ {
+ free (name);
+ free (group_name);
+ free (parent_name);
+ }
+ bool is_system ();
+};
+
+struct GCEvent
+{
+
+ GCEvent ()
+ {
+ id = -1;
+ }
+
+ ~GCEvent () { }
+
+ hrtime_t start;
+ hrtime_t end;
+ int id;
+};
+
+class ExperimentLoadCancelException
+{
+public:
+
+ ExperimentLoadCancelException () { };
+
+ ~ExperimentLoadCancelException () { };
+};
+
+
+#endif /* _EEXPERIMENT_H */