[PATCH 2/2 RFC] Add time stamp collection to operf and opreport

"Carl E. Love" <[email protected]>
Newsgroups gmane.linux.oprofile
Message-ID <1443803981.6530.57.camel@oc3328482554>
OProfile Time stamp processing support

This patch adds two scripts for processing and plotting the time stamp
data collected by operf.  The primary script is in utils/plot_time_stamps.sh
This script calls the perl script utils/processs_time_stamps.prl that does
the majority of the data processing.

Signed-off-by: Carl Love <[email protected]>
---
 configure.ac                  |    1 +
 doc/Makefile.am               |    3 +-
 doc/plot_time_stamps.1.in     |   85 +++++
 utils/Makefile.am             |    2 +
 utils/plot_time_stamps.sh     |  222 ++++++++++++
 utils/process_time_stamps.prl |  739 +++++++++++++++++++++++++++++++++++++++++
 6 files changed, 1051 insertions(+), 1 deletions(-)
 create mode 100644 doc/plot_time_stamps.1.in
 create mode 100755 utils/plot_time_stamps.sh
 create mode 100755 utils/process_time_stamps.prl

diff --git a/configure.ac b/configure.ac
index 72b1515..201a535 100644
--- a/configure.ac
+++ b/configure.ac
@@ -426,6 +426,7 @@ AC_OUTPUT(Makefile \
 	doc/opimport.1 \
 	doc/operf.1 \
 	doc/ocount.1 \
+	doc/plot_time_stamps.1 \
 	doc/srcdoc/Doxyfile \
 	libpp/Makefile \
 	opjitconv/Makefile \
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 43a7781..9a87835 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -20,7 +20,8 @@ man_MANS = \
 
 if BUILD_FOR_PERF_EVENT
 man_MANS += operf.1 \
-			ocount.1
+	ocount.1 \
+	plot_time_stamps.1
 endif
 
 htmldir = $(prefix)/share/doc/oprofile
diff --git a/doc/plot_time_stamps.1.in b/doc/plot_time_stamps.1.in
new file mode 100644
index 0000000..8243593
--- /dev/null
+++ b/doc/plot_time_stamps.1.in
@@ -0,0 +1,85 @@
+.\" Manpage for operf
+.\" Author: Carl Love   <[email protected]>
+.\" Modifications:
+.TH OPERF 1 "@DATE@" "timestamp processing @VERSION@"
+.SH NAME
+plot_time_stamps.sh \- Script to process and plot time stamp data.
+
+.SH SYNOPSIS
+.B process_time_stamps.sh
+[
+.I options
+]
+[ -f | -l | -b | -s | -e | -m | -S | -p | --xml_file | --line_graph | --bar_graph | --start_time | --stop_time | --max_bins | --max_symbols | --ps_file | --help]
+
+
+.SH DESCRIPTION
+OProfile can produce an XML output file that contains the time stamp for each sample.  This script
+is used to process the time stamp data and display it in a bar or line graph format.  The graph can show
+all of the symbols combined or show the top N symbols individually. The value of N can be specified by a 
+command line argument.  Each point (bar) on the graph is for a given period of time, referred to as
+a bin.  The width of the bin and the number of bins can be set as command line options.  The user
+may specify the name of the output postscript file containing the graph.  
+
+This is a shell script which calls an additional script and applications to generate and display the
+graph.  The bulk of the data processing is done by a perl script process_time_stamps.prl which is part
+of the OProfile package.  This script calls gnuplot and xdg-open.  Both applications are assumed to
+be installed. 
+.P
+
+.TP
+.BI "-f / --xml_file  " XML_file_name
+This option allows the user to specify the OProfile XML input file con the time stamp data.  This is a
+required entry.
+
+.TP
+.BI "-p / --ps_file  "  ps_file_name
+This option allows the user to specify the name of the postscript file containing the graph.  By default
+the graph is put into file workload_tm_data.ps.
+
+.TP
+.BI " -l / --line_graph"
+This option specifies the data is to be plotted as a line graph.  This is the default for plotting the data.
+The user can specify either line graph or bar graph but not both.
+.TP
+.BI " -b / --bar_graph"
+This option specifies the data is to be plotted as a bar graph.
+The user can specify either line graph or bar graph but not both.
+.TP
+
+.BI " -s / --start_time  "  start_time
+This option allows the user to plot a portion of the time stamps starting at the specified time.
+
+.TP
+.BI " -e / --stop_time  "   stop_time
+This option allows the user to plot a portion of the time stamps stopping at the specified time.
+
+.TP
+.BI " -m / --max_bins  "     number_of_bins
+This option allows the user to adjust the number of bins in the graph. The default is 200 bins.
+
+.TP
+.BI " -S / --max_symbols  "  max_number_symbols
+This option allows the user to adjust the number of symbols displayed or plot all symbols combined.
+An input value of zero specifies combine all symbols into a single plot.  A positive nonzero value,
+N, will plot the N symbols with the most time stamps.  All other symbols are combined into symbol
+"other".
+
+.TP
+.BI "--help / -h"
+Display brief usage help message.
+.br
+.RE
+
+.TP
+
+.SH EXAMPLE
+Typical OProfile data collection and processing to create the input XML data file.
+
+   operf -T -e CPU_CLK_UNHALTED:100000 <your workload>                                               
+   opreport -T -X   > opreport-out               
+
+Process and display the time stamp data.
+
+   plot_time_stamps.sh -f opreport-out
+
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 408dc54..65d8c45 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -9,6 +9,8 @@ LIBS=@POPT_LIBS@ @LIBERTY_LIBS@
 
 bin_PROGRAMS = ophelp op-check-perfevents
 
+bin_SCRIPTS = plot_time_stamps.sh process_time_stamps.prl
+
 op_check_perfevents_SOURCES = op_perf_events_checker.c
 op_check_perfevents_CPPFLAGS = ${AM_CFLAGS} @PERF_EVENT_FLAGS@
 
diff --git a/utils/plot_time_stamps.sh b/utils/plot_time_stamps.sh
new file mode 100755
index 0000000..a25686f
--- /dev/null
+++ b/utils/plot_time_stamps.sh
@@ -0,0 +1,222 @@
+#!/bin/sh
+
+# This script takes the name of the OProfile XML output file containing
+# the time stamp data as input.  This script calls the perl script
+# utils/process_time_stamps.prl to generate the data and command files
+# needed by gnu plot to plot the time stamp data.  This script then
+# invokes gnu plot to display the graph.  Finally, the script will invoke
+# xdg-open to display the graph.
+#
+# This script passes the needed options to utils/process_time_stamps.prl
+# if the user specifies any.
+#
+# The OProfile xml file is typically created by running operf and opreport
+# with the -T option.  The -T tells operf and opreport to collect and process
+# the time stamp data.  The call to opreport must also have the -X option
+# specified to generate the output in xml format.
+#
+#  example run:
+#
+#   operf -T -e CPU_CLK_UNHALTED:100000 <your workload>
+#   opreport -T -X   > opreport-out
+#   plot_time_stamps.sh -f opreport-out
+#
+#  Copyright 2015 OProfile authors                                                                    
+#  Read the file COPYING                                                                              
+#                                                                                                     
+#  Created on: Sept. 25, 2015                                                                         
+#  Author  Carl Love   [email protected]                                                               
+#  (C) Copyright IBM Corp. 2015        
+#
+#--------------------------------------------------------------
+
+# Check that the required applications are installed.
+#
+# Check to see if perl is installed                                             
+if  ! perl --version > /dev/null 2>&1 ; then
+    echo " "
+    echo " This utility requires perl to process the timestamps."
+    echo " Please install perl and try again. Exiting."
+    echo " "
+    exit
+fi
+
+# Check to see if gnuplot is installed
+if ! gnuplot --version > /dev/null 2>&1 ; then
+    echo " "
+    echo " This utility requires gnuplot to generate the timestamp plot."
+    echo " Please install gnuplot and try again. Exiting."
+    echo " "
+    exit
+fi
+
+# Check to see if xdg-open is installed
+   
+if  xdg-open --version > /dev/null 2>&1 ; then
+    have_xdg_open="1";
+else
+    have_xdg_open="";
+    echo " "
+    echo " This utility uses xdg-open to display the postscript plot of the data."
+    echo " The postscript file with the plot will be generated but you will"
+    echo " need to open it manually.  Install xdg-open if you would like "
+    echo " this utility to automatically display the graph for you."
+    echo " "
+fi
+
+
+# 
+function usage
+{
+echo "        -f | --xml_file    XML input file with the time stamps"
+echo "        -l | --line_graph  generate a line graph of the time stamps within each bin"
+echo "        -b | --bar_graph   generate a bar graph of the time stamps within each bin"
+echo "        -s | --start_time  start plot time, default first time stamp"
+echo "        -e | --stop_time   stop  plot time, default last time stamp"
+echo "        -m | --max_bins    number of intervals to be plotted"
+echo "        -S | --max_symbols maximum number of symbols to plot, default is "
+echo "        -p | --ps_file     Output file name for the generate postscript plot"
+echo "                           zero which prints all symbols combined.  A "
+echo "                           non-zero value will graph each of the top N "
+echo "                           symbols individually"
+echo "        -h | --help        print this help guide "
+    
+}
+
+xml_input_filename=
+ps_output_filename="plot.ps"
+
+while [ "$1" != "" ]; do
+    case $1 in
+        -f | --xml_file )      shift
+                               xml_input_filename=$1 ;;
+
+        -l | --line_graph )    line_graph=1 ;;
+
+        -b | --bar_graph )     bar_graph=1 ;;
+
+        -s | --start_time )    shift
+                               start_time=$1 ;;
+
+        -e | --stop_time )     shift
+                               stop_time=$1 ;;
+
+        -m | --max_bins )      shift
+                               max_bins=$1 ;;
+
+        -S | --print_symbols ) shift
+                               print_symbols=$1 ;;
+
+        -p | --ps_file )       shift
+                               ps_output_filename=$1 ;;
+
+        -h | --help )          usage
+                               exit
+                               ;;
+        * )                    echo "Command line argument $1 is not valid"
+                               usage
+                               exit 1
+    esac
+    shift
+done
+
+# Check the options, input file name is required
+if [ -z $xml_input_filename ]; then
+    echo " "
+    echo "Error: XML input file name not specified.  A file name is required.";
+    echo " "
+    exit;
+fi
+
+if [ ! -z $bar_graph ] && [ ! -z $line_graph ]; then
+    echo " "
+    echo "Error: specify line_graph or bar_graph but not both.";
+    echo " "
+    exit;
+fi
+
+# Setup command line for utils/process_time_stamps.prl
+#command=" -debug ";
+command="";
+
+if [ ! -z $line_graph ]; then
+    command="$command  -line_graph "
+fi
+
+if [ ! -z $bar_graph ]; then
+    command="$command  -bar_graph "
+fi
+
+if [ ! -z $start_time ]; then
+    command="$command  -start_time=$start_time "
+fi
+
+if [ ! -z $stop_time ]; then
+    command="$command  -stop_time=$stop_time "
+fi
+
+if [ ! -z $max_bins ]; then
+    command="$command  -max_bins=$max_bins "
+fi
+
+if [ ! -z $print_symbols ]; then
+    command="$command  -print_symbol_threshold=$print_symbols "
+fi
+
+if [ ! -z $ps_output_filename ]; then
+    command="$command  -ps_output_file=$ps_output_filename "
+fi
+
+# call the perl script to process the data.  Note, we will let the perl
+# script use the default gnu plot command and data files but pass it the
+# user's specified postscript file name if specified.
+
+echo " "
+echo " Processing XML time stamp data from file $xml_input_filename... "
+echo " "
+
+process_time_stamps.prl $command < $xml_input_filename > process_time_stamps.out 
+
+# Check that the perl script succeeded
+if [ ! $? ]; then
+   echo " "
+   echo  " ERROR: perl script failed.  Exiting...."
+   exit
+fi
+
+echo " Done processing XML time stamp data."
+echo " "
+
+# call gnuplot to generate the post script file containing the plot.
+echo " Calling gnuplot to create postscript file.  Output file is: " $ps_output_filename "."
+echo " "
+
+# command file default
+workload_tm_cmd="workload_tm_cmd.plt"
+gnuplot ./$workload_tm_cmd
+
+# Check that gnuplot succeeded
+if [ ! $? ]; then
+   echo " "
+   echo  " ERROR: call to gnuplot failed.  Exiting...."
+   exit
+fi
+
+if [  $have_xdg_open ]; then
+    echo " Calling xdg-open to open the postscript file " $ps_output_filename "."
+    echo " "
+
+    xdg-open $ps_output_filename
+
+# Check that the call to xdg-open succeeded
+    if [ ! $? ]; then
+	echo " "
+	echo  " ERROR: all to xdg-open failed.  Exiting...."
+	echo " "
+	exit
+    fi
+else
+    echo " The histogram plot was generated.  It is in file $ps_output_filename"
+    echo " Please open manually."
+    echo " "
+fi
\ No newline at end of file
diff --git a/utils/process_time_stamps.prl b/utils/process_time_stamps.prl
new file mode 100755
index 0000000..054624c
--- /dev/null
+++ b/utils/process_time_stamps.prl
@@ -0,0 +1,739 @@
+#!/usr/bin/perl
+#
+# process_time_stamps.prl
+#
+# This script reads an OProfile xml output file and generates a gnu-plot
+# command and data file.
+# 
+# The OProfile xml file is typically created by running operf and opreport
+# with the -T option.  The -T tells operf and opreport to collect and process
+# the time stamp data.  The call to opreport must also have the -X option 
+# specified to generate the output in xml format.
+#
+#  example run:
+#
+#   operf -T -e CPU_CLK_UNHALTED:100000 <your workload>
+#   opreport -T -X   > opreport-out
+#   plot_time_stamps.sh -f opreport-out
+#
+#  Copyright 2015 OProfile authors
+#  Read the file COPYING
+#
+#  Created on: Sept. 25, 2015
+#  Author  Carl Love   [email protected]
+#  (C) Copyright IBM Corp. 2015
+#
+use strict;
+use Getopt::Long qw(GetOptions);
+
+###########################
+#main
+my $DATA_SEPARATOR = "\t ";
+
+# Default name for the generated data file to pass to gnuplot
+my $GNU_PLOT_DEFAULT_OUTPUT_DATA_FILE = "workload_tm_data.gpi";
+
+# Default name for the gnuplot command file
+my $GNU_PLOT_DEFAULT_OUTPUT_COMMAND_FILE = "workload_tm_cmd.plt";
+
+#default name for the output postscript file containing the plot
+my $PS_DEFAULT_OUTPUT_FILE = "workload_tm_data.ps";
+
+#  Command line options
+#  -debug          enable debug prints
+
+#  -start_time         Beginning of time to display, default beginning of 
+#                      data.
+#  -stop_time          End of time to display, default end of data.
+#
+#  -gnu_plot_data_file  File name for the generated data file containing
+#                       the data to be plotted by gnu plot.
+#
+#  -gnu_plot_cmd_file   File name for the generated command file to input to
+#                       gnu plot.
+#
+#  -ps_output_file      Postscript output file name for the gnu plot
+#
+#  -print_symbol_threshold    0 - combine all symbol time stamps in a single data set.
+#                       if greater then zero, display the top N symbols where
+#                       N is the argument of symbol_threshold
+
+# Process the command line arguments
+#
+my $debug = 0;
+my $usr_start_time  = 0;
+my $usr_stop_time   = -1;
+my $line_graph = 0;
+my $bar_graph = 0;
+my $max_bins = 200;
+my $gnu_plot_data_file = $GNU_PLOT_DEFAULT_OUTPUT_DATA_FILE;
+my $gnu_plot_cmd_file  = $GNU_PLOT_DEFAULT_OUTPUT_COMMAND_FILE;
+my $ps_output_file = $PS_DEFAULT_OUTPUT_FILE;
+my $print_symbol_threshold = 0;
+
+GetOptions (
+    'debug!'         => \$debug,
+    'start_time=s'   => \$usr_start_time,
+    'stop_time=s'    => \$usr_stop_time,
+    'line_graph!'    => \$line_graph,
+    'bar_graph!'     => \$bar_graph,
+    'max_bins=s'     => \$max_bins,
+    'gnu_plot_data_file=s'  => \$gnu_plot_data_file,
+    'gnu_plot_cmd_file=s'   => \$gnu_plot_cmd_file,
+    'ps_output_file=s'      => \$ps_output_file,
+    'print_symbol_threshold=s'    => \$print_symbol_threshold,
+    ) or die "Unknown command line option\n";
+
+
+if ($debug) {
+    printf " Command line argument settings are: \n";
+    printf "    debug       = $debug \n";
+    printf "    start_time  = $usr_start_time \n";
+    printf "    stop_time   = $usr_stop_time \n";
+    printf "    line_graph  = $line_graph \n";
+    printf "    bar_graph   = $bar_graph \n";
+    printf "    max_bins    = $max_bins \n";
+    printf "    ps_output_file  = $ps_output_file \n";
+}
+
+## Check command line argument
+if ($line_graph && $bar_graph) {
+    die "Error, cannot specify both line and bar graph styles.\n";
+}
+if (!$line_graph && !$bar_graph) {
+    # must specify line_graph or bar_graph
+    $line_graph=1;
+}
+
+if ($max_bins < 0) {
+    die "The number of bins for the bar graph style must be positive.\n"
+}
+
+my $num_symbols = 0;
+my $found_count = 0;
+my $found_tm = 0;
+my $found_symbol = 0;
+my $min_tm = -1;
+my $max_tm = -1;
+
+my ($i, $j, $k, $n, $print_rank, $data_column, $bin_width);
+my ($end_time, $max_bin_count, $sum, $x_coordinate, $bin_time, $value);
+my ($all_symbols, $print_symbol, $name, $id_name, $rank, $delta);
+my ($symb_min_tm, $symb_max_tm, $top_index, $top_count, $slice_num);
+my ($offset, $start_time, $stop_time);
+my (@sym_name, @sym_rank, @bin_count, @tm_array, @fields, @count, @fields);
+my (@symbol_max_tm, @symbol_min_tm, @subfields);
+
+### Global data
+my $included_count = 0;
+my $excluded_count = 0;
+
+##############################
+### get data
+&read_xml_file($num_symbols, $min_tm, $max_tm, @count, @sym_name, @sym_rank, @tm_array, @symbol_min_tm, @symbol_max_tm);
+
+## Enable debuging the parsing of the data file
+if ($debug) {
+    &debug_print_extracted_data();
+}
+
+######################################
+
+### Display symbols
+# 0 - Collapse all symbol data into a single line
+# 3 - Show time stamps for symbols counts in the top N
+
+##############################################
+###  SET the graph start/stop time
+
+
+### Setup to display the time range.  The assumption is that the
+#   user is inputting an adjusted start/stop time based on a
+#   previously viewed graph.
+
+if ($usr_start_time <= 0) {
+    $start_time = $min_tm;
+} else {
+    $start_time = $usr_start_time + $min_tm;
+}
+
+print "USER start time = $usr_start_time\n";
+print "USER input stop time = $usr_stop_time\n";
+print "MAX TIME = $max_tm\n";
+
+if ($usr_stop_time == -1) {
+    $end_time = $max_tm;
+} elsif ($usr_stop_time < ($max_tm -$min_tm)) {
+    $end_time = $usr_stop_time + $min_tm;
+    printf "SET END_TIME TO UNNORMALIZED USR STOP TIME, $end_time\n";
+} else {
+    $end_time = $max_tm;
+}
+$bin_width = ($end_time - $start_time) / $max_bins;
+
+if ($debug) {
+    print "Display_window = 1, Initial, min_tm = $min_tm, max_tm = $max_tm\n";
+    print "Display_window = 1, start_time = $start_time, end_time = $end_time\n";
+    print "print_symbol_threshold = $print_symbol_threshold \n";
+    print "gnu_plot_data_file = $gnu_plot_data_file\n";
+    print "gnu_plot_cmd_file  = $gnu_plot_cmd_file\n";
+    print "ps_output_file = $ps_output_file\n";
+    print "line_graph = $line_graph\n";
+    print "bar_graph = $bar_graph\n";
+    print "user start time = $usr_start_time\n";
+    print "user stop time = $usr_stop_time\n";
+}
+print "user start time = $usr_start_time\n";
+print "user stop time = $usr_stop_time\n";
+print "start time = $start_time\n";
+print "end time   = $end_time\n";
+
+#################################################
+# currently not supporting the &print_dot_plot_script_file but
+# the routine is still included if desired to support again 
+# in the future.
+if ($line_graph == 1) {
+    &print_bin_line_plot_script_file();
+    &print_bin_data_file_for_plot();
+} elsif ($bar_graph == 1) {
+    &print_bin_hist_plot_script_file();
+    &print_bin_data_file_for_plot();
+} else {
+    print "ERROR, unknown value of graph style\n";
+}
+
+################################
+
+#print "Slice size = ", $slice_size, "\n";
+print "Start time = ", $start_time, "\n";
+print "bin width  = ", $bin_width, "\n";
+print "End time   = ", $end_time, "\n";
+
+
+&print_timestamp_range_for_symbols();
+
+######################  End of main
+
+
+#### subroutines  #############################################
+
+sub print_this_symbol {
+
+    my $index = $_[0];
+
+    $print_symbol = 0;
+
+    if ($print_symbol_threshold == 0) {
+	     $print_symbol = 1;
+    } elsif ($print_symbol_threshold > 0) {
+	if ($sym_rank[$index] != 0) {
+	     $print_symbol = 1;
+	}
+
+    } else {
+	print "ERROR, print_symbol_threshold setting is invalid\n";
+    }
+}
+
+sub generate_symbol_rank (@sym_rank) {
+    # go through the list of symbols and assign the rank of 1 to num_symbols
+    # where the symbol with the highest count is 1, the next highest is 2,...
+    $rank = 1;
+    for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+	$top_index = -1;
+	$top_count = 0;
+	for ($j = 0; $j < $num_symbols; $j = $j + 1) {
+	    if (($sym_rank[$j] == 0) && ($top_index == -1)) {
+		$top_index = $j;
+		$top_count = $count[$j];
+	    } elsif (($count[$j] > $top_count ) && ($sym_rank[$j] == 0)) {
+		$top_index = $j;
+		$top_count = $count[$j];
+	    }
+	}
+	$sym_rank[$top_index] = $rank;
+	$rank = $rank + 1;
+    }
+    for ($j = 0; $j < $num_symbols; $j = $j + 1) {
+	for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+	    if ($sym_rank[$i] == ($j + 1)) {
+		print "Symbol $sym_name[$i], index $i, is at rank $sym_rank[$i], count $count[$i].\n";
+	    }
+	}
+    }
+}
+
+sub read_xml_file ($num_symbols, $min_tm, $max_tm, @count, @sym_name, @sym_rank, @tm_array, @symbol_min_tm, @symbol_max_tm) {
+# read the input
+
+    while(<>)  {
+	# look for the symbol name
+	@fields = split(' ', $_);
+
+	if ($debug) {
+	    print "LINE: $_\n";
+	}
+
+	if ($fields[0] eq "<symbol") {
+	    @subfields = split('>', $fields[1]);
+# change " to ' otherwise it messes up my title string.
+	    $name = $subfields[0];
+	    $name=~ s/"/'/g;
+	    $sym_name[$num_symbols] = $name;
+	    $sym_rank[$num_symbols] = 0;    # initialize the ranking
+	    $found_symbol = 1;
+	    if ($debug) {
+		print "Found symbol number $num_symbols = $sym_name[$num_symbols] \n";
+	    }
+	}
+
+	if ($fields[0] eq "</symbol>") {
+	    $found_symbol = 0;
+	    $num_symbols = $num_symbols + 1;
+	    if ($debug) {
+		print "found </symbol>, num_symbols incremented to $num_symbols\n";
+	    }
+	}
+
+	if ($found_count == 1) {
+	    if ($found_symbol == 1) {
+		@subfields = split('<', $_);
+		$count[$num_symbols] = $subfields[0];
+		if ($debug) {
+		    print "symbol $sym_name[$num_symbols] count is ", $count[$num_symbols], "\n";
+		}
+	    }
+	    $found_count = 0;
+	}
+
+	if ((($found_tm == 1) && ($found_symbol == 1))) {
+	    # the entry may be <timestamp  0xfffff where the tag and data are 
+	    # the same line
+	    $found_tm = 0;
+	    if ($debug) {
+		print "Found time stamps, number TMs $count[$num_symbols] \n";
+	    }
+
+	    if ($fields[0] =~ /\<timestamp/) {
+		# time stamps start in field 1 in this case
+		$offset = 1;
+	    } else {
+		$offset = 0;
+	    }
+
+	    $symb_min_tm = -1;
+	    $symb_max_tm = -1;
+
+	    for ($i = 0; $i < $count[$num_symbols]; $i = $i + 1) {
+		$value = oct($fields[$i+$offset]);
+		if ($debug) {
+		    print "TM value = $value\n";
+		}
+
+		if ($min_tm == -1) {
+		    $min_tm = $value;
+		} elsif ($min_tm > $value) {
+		    $min_tm = $value;
+		}
+
+		if ($max_tm == -1) {
+		    $max_tm = $value;
+		} elsif ($max_tm < $value) {
+		    $max_tm = $value;
+		}
+
+		if ($symb_min_tm == -1) {
+		    $symb_min_tm = $value;
+		} elsif ($symb_min_tm > $value) {
+		    $symb_min_tm = $value;
+		}
+
+		if ($symb_max_tm == -1) {
+		    $symb_max_tm = $value;
+		} elsif ($symb_max_tm < $value) {
+		    $symb_max_tm = $value;
+		}
+	      
+		$tm_array[$num_symbols][$i] = $value;
+	    }
+	    $symbol_min_tm[$num_symbols] = $symb_min_tm;
+	    $symbol_max_tm[$num_symbols] = $symb_max_tm;
+	    if ($debug) {
+		print "symbol_min_tm[$num_symbols] = $symbol_min_tm[$num_symbols] \n";
+		print "symbol_max_tm[$num_symbols] = $symbol_max_tm[$num_symbols] \n";
+	    }
+	}
+
+	if ($fields[0] eq "<symboldata") {
+	    # Found a symbol table entry, update symbol id in sym_name
+	    # with the actual symbol name
+	    @subfields = split('"', $fields[2]);
+	    $name = $subfields[1];
+	    $id_name = $fields[1];
+	    $id_name=~ s/"/'/g;       # changed " to ' when storing id
+	    $id_name=~ s/id=/idref=/g;  
+      
+	    for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+		#search for id_name in $sym_name and update with actual name
+		if ($sym_name[$i] eq $id_name) {
+		    if ($debug) {
+			print "Replace name $sym_name[$i] at index $i with $name\n";
+		    }
+		    $sym_name[$i] = $name;
+		}
+	    }
+	}
+#check these last so they will set the flag for the next line
+
+	if ($fields[0] =~ /\<count/) {    # field has substring <count
+	    if ($debug) {
+		print "Found count entry \n";
+	    }
+	    $found_count = 1;
+	}     
+	
+	if ($fields[0] eq "<timestamp>") { # time stamps on next line
+	    if ($debug) {
+		print "Found time stamp entry \n";
+	    }
+	    $found_tm = 1;
+	}
+    }
+}
+
+sub debug_print_extracted_data {
+    print "\n\nEXTRACTED DATA \n\n";
+
+    print " Number of symbols found = $num_symbols\n";
+    print " Min time stamp = $min_tm\n";
+    print " Max time stamp = $max_tm\n\n";
+
+    for ($i = 0; $i <= $num_symbols; $i = $i + 1) {
+	print "Symbol = $sym_name[$i], count[$i] = $count[$i]\n";
+        print "symbol_min_tm = $symbol_min_tm[$i]\n";
+        print "symbol_max_tm = $symbol_max_tm[$i]\n\n";
+
+	for ($j = 0; $j < $count[$i]; $j = $j + 1) {
+	    print "tm_array[$i][$j] = $tm_array[$i][$j], ";
+	} 
+	print "\n\n";
+    }
+}
+
+
+# print selected symbols with time stamps
+sub print_timestamp_range_for_symbols {
+
+    print "Minimum raw time ", $min_tm, "\n";
+    print "Maximum raw time ", $max_tm, "\n\n";
+
+    print "Minimum adjusted time ", $min_tm - $min_tm, "\n";
+    print "Maximum adjusted time ", $max_tm- $min_tm, "\n\n";
+
+    for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+	print "Symbol: ", $sym_name[$i], "\n";
+	print "   Min time stamp = ", $symbol_min_tm[$i] - $min_tm, "\n";
+	print "   Max time stamp = ", $symbol_max_tm[$i] - $min_tm, "\n";
+	printf("\n");
+    }
+}
+
+sub print_bin_data_file_for_plot {
+# count samples within the bin size, plot counts within each bin
+    $all_symbols = 1;   # print all symbols in one line
+
+    $bin_width = ($end_time - $start_time) / $max_bins;
+
+    open FH_DATA_FILE, "> $gnu_plot_data_file";
+
+    $print_symbol = 0;
+
+    $bin_time = $start_time;
+
+    for ($k = 0; $k < $max_bins; $k = $k + 1) {
+	for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+	    $bin_count[$i][$k] = 0;
+
+	    for ($j = 0; $j < $count[$i]; $j = $j + 1) {
+		$value = $tm_array[$i][$j];
+		if ( $k < 3) {
+		    print "CARLL k = $k, j = $j, bin_time = $bin_time, value = $value\n";
+		}
+		if (($value >= $bin_time) &&
+		    ($value <= ($bin_time + $bin_width))) {
+		    $bin_count[$i][$k] = $bin_count[$i][$k] + 1;
+		}
+	    }
+	}
+	$bin_time = $bin_time + $bin_width;
+    }
+
+
+    if ($print_symbol_threshold == 0) {
+	for ($k = 0; $k < $max_bins; $k = $k + 1) {
+	    $x_coordinate = $k * $bin_width;
+	    print FH_DATA_FILE $x_coordinate, $DATA_SEPARATOR;
+	    $sum = 0;
+	    for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+		$sum = $sum + $bin_count[$i][$k];
+	    } 
+	    print FH_DATA_FILE "$sum \n";
+	}
+    } elsif ($print_symbol_threshold > 0) {
+	for ($k = 0; $k < $max_bins; $k = $k + 1) {
+	    $x_coordinate = $k * $bin_width;
+	    if ($debug) {
+		print FH_DATA_FILE $x_coordinate, "\t";
+	    } else {
+		print FH_DATA_FILE $x_coordinate, $DATA_SEPARATOR;
+	    }
+
+	    # print the N symbols
+	    for ($n = 0; $n < $print_symbol_threshold; $n = $n + 1) {
+		$print_rank = $n + 1;    # column 1 is X data
+		for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+		    if ($sym_rank[$i] == $print_rank) {
+			if ($debug) {
+			    print "print_rank = $print_rank, index = $i\n";
+			}
+			print FH_DATA_FILE $bin_count[$i][$k], $DATA_SEPARATOR;
+		    }
+		}
+	    }
+
+	    # Sum counts for all symbols whose rank is greater
+	    # then top N symbols and print them in the last
+	    # column for other
+	    $sum = 0;
+	    for ($n = $print_symbol_threshold; $n < $num_symbols; $n = $n + 1) {
+		$print_rank = $n + 1;
+		for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+		    if ($sym_rank[$i] >= $print_symbol_threshold) {
+			$sum = $sum + $bin_count[$i][$k];
+		    }
+		}
+	    }
+	    print FH_DATA_FILE "$sum\n";
+	}
+
+    } else {
+	print "ERROR, print_symbol_threshold value not valid in print_bin_data_file_for_plot\n";
+    }
+    close FH_DATA_FILE;
+}
+
+sub print_base_plot_script {
+# This routine opens the output script file and writes the 
+# gnuplot commands that are generic to the various plots 
+# being made.  It is called from the routine that is doing
+# a specific plot type.
+
+    open FH_GNU_SCRIPT, '>',  $gnu_plot_cmd_file;
+
+    print FH_GNU_SCRIPT "# Start time = ", $start_time, "\n";
+    print FH_GNU_SCRIPT "# End time   = ",   $end_time, "\n";
+    print FH_GNU_SCRIPT "set terminal postscript\n";
+    print FH_GNU_SCRIPT "set output \"$ps_output_file\"\n";
+
+    if ($line_graph == 1) {
+	## unfortunately gnuplot does not use the X-axis value for histograms
+	## and box graphs.  The x-axis is labeled by the bin number.
+	print FH_GNU_SCRIPT "set xlabel \"Time in ns, since data collection started.\" \n";
+	print FH_GNU_SCRIPT "set ylabel \"Counts in bin.  Bin size is $bin_width ns.\" \n";
+    } elsif ($bar_graph == 1) {
+	print FH_GNU_SCRIPT "set xlabel \"Time in ns is bin number times bin_width = $bin_width.\" \n";
+	print FH_GNU_SCRIPT "set ylabel \"Counts in bin.\" \n";
+
+    } else {
+	die "ERROR: neither line_graph or bar_graph was set\n";
+    }
+
+#    print FH_GNU_SCRIPT "set ytics 1\n";
+    print FH_GNU_SCRIPT "set xrange [0:*] \n";
+    print FH_GNU_SCRIPT "set yrange [0:*] \n";
+
+    print FH_GNU_SCRIPT "set mytics 0\n";
+}
+
+sub print_line_style_color {
+    print FH_GNU_SCRIPT "# black\n";
+    print FH_GNU_SCRIPT "set style line 99 lt rgbcolor \"#0000\"\n\n";
+
+    print FH_GNU_SCRIPT "# red\n";
+    print FH_GNU_SCRIPT "set style line 1 lt rgbcolor \"#FF0000\"\n\n";
+
+    print FH_GNU_SCRIPT "# aqua\n";
+    print FH_GNU_SCRIPT "set style line 2 lt rgbcolor \"#00FFFF\"\n\n";
+
+    print FH_GNU_SCRIPT "# bisque\n";
+    print FH_GNU_SCRIPT "set style line 3 lt rgbcolor \"#FFE4C4\"\n\n";
+
+    print FH_GNU_SCRIPT "# blue\n";
+    print FH_GNU_SCRIPT "set style line 4 lt rgbcolor \"#0000FF\"\n\n";
+
+    print FH_GNU_SCRIPT "# blueviolet\n";
+    print FH_GNU_SCRIPT "set style line 5 lt rgbcolor \"#8A2BE2\"\n\n";
+
+    print FH_GNU_SCRIPT "# brown\n";
+    print FH_GNU_SCRIPT "set style line 6 lt rgbcolor \"#A52A2A\"\n\n";
+
+    print FH_GNU_SCRIPT "# burlywood\n";
+    print FH_GNU_SCRIPT "set style line 7 lt rgbcolor \"#DEB887\"\n\n";
+
+    print FH_GNU_SCRIPT "# cadetblue\n";
+    print FH_GNU_SCRIPT "set style line 8 lt rgbcolor \"#5F9EA0\"\n\n";
+
+    print FH_GNU_SCRIPT "# cartreuse\n";
+    print FH_GNU_SCRIPT "set style line 9 lt rgbcolor \"#7FFF00\"\n\n";
+
+    print FH_GNU_SCRIPT "# chocolate\n";
+    print FH_GNU_SCRIPT "set style line 10 lt rgbcolor \"#D2691E\"\n\n";
+
+    print FH_GNU_SCRIPT "# coral\n";
+    print FH_GNU_SCRIPT "set style line 11 lt rgbcolor \"#FF7F50\"\n\n";
+
+    print FH_GNU_SCRIPT "# cornflowerblue\n";
+    print FH_GNU_SCRIPT "set style line 12 lt rgbcolor \"#6495ED\"\n\n";
+
+    print FH_GNU_SCRIPT "# crimson\n";
+    print FH_GNU_SCRIPT "set style line 13 lt rgbcolor \"#DC143C\"\n\n";
+
+    print FH_GNU_SCRIPT "# darkcyan\n";
+    print FH_GNU_SCRIPT "set style line 14 lt rgbcolor \"#008B8B\"\n\n";
+
+    print FH_GNU_SCRIPT "# darkgoldenrod\n";
+    print FH_GNU_SCRIPT "set style line 15 lt rgbcolor \"#B8860B\"\n\n";
+
+    print FH_GNU_SCRIPT "# green\n";
+    print FH_GNU_SCRIPT "set style line 16 lt rgbcolor \"#008000\"\n\n";
+
+    print FH_GNU_SCRIPT "# greenyellow\n";
+    print FH_GNU_SCRIPT "set style line 17 lt rgbcolor \"#ADFF2F\"\n\n";
+
+    print FH_GNU_SCRIPT "# hotpink\n";
+    print FH_GNU_SCRIPT "set style line 18 lt rgbcolor \"#FF69B4\"\n\n";
+
+    print FH_GNU_SCRIPT "# lawngreend\n";
+    print FH_GNU_SCRIPT "set style line 19 lt rgbcolor \"#7CFC00\"\n\n";
+
+    print FH_GNU_SCRIPT "# lightseagreen\n";
+    print FH_GNU_SCRIPT "set style line 20 lt rgbcolor \"#20B2AA\"\n\n";
+
+    print FH_GNU_SCRIPT "# lightskyblue\n";
+    print FH_GNU_SCRIPT "set style line 21 lt rgbcolor \"#87CEFA\"\n";
+
+    print FH_GNU_SCRIPT "# lightslategray\n";
+    print FH_GNU_SCRIPT "set style line 22 lt rgbcolor \"#778899\"\n\n";
+
+    print FH_GNU_SCRIPT "# limegreen\n";
+    print FH_GNU_SCRIPT "set style line 23 lt rgbcolor \"#32CD32\"\n\n";
+
+    print FH_GNU_SCRIPT "# indigo\n";
+    print FH_GNU_SCRIPT "set style line 24 lt rgbcolor \"#4B0082\"\n\n";
+
+    print FH_GNU_SCRIPT "# lime\n";
+    print FH_GNU_SCRIPT "set style line 25 lt rgbcolor \"#00FF00\"\n\n";
+
+    print FH_GNU_SCRIPT "# linen\n";
+    print FH_GNU_SCRIPT "set style line 26 lt rgbcolor \"#FAF0E6\"\n\n";
+
+    print FH_GNU_SCRIPT "# magenta\n";
+    print FH_GNU_SCRIPT "set style line 27 lt rgbcolor \"#FF00FF\"\n\n";
+
+    print FH_GNU_SCRIPT "# maroon\n";
+    print FH_GNU_SCRIPT "set style line 28 lt rgbcolor \"#800000\"\n\n";
+
+    print FH_GNU_SCRIPT "# mediumslateblue\n";
+    print FH_GNU_SCRIPT "set style line 29 lt rgbcolor \"#7B68EE\"\n\n";
+
+    print FH_GNU_SCRIPT "# mediumturquoise\n";
+    print FH_GNU_SCRIPT "set style line 30 lt rgbcolor \"#48D1CC\"\n\n";
+}
+
+sub print_bin_line_plot_script_file {
+# script for making a dot plot 
+    $bin_width = ($end_time - $start_time) / $max_bins;
+    if ($debug) {
+	print "print_bin_line_plot_script_file(), bin_width = $bin_width\n";
+    }
+
+    &print_base_plot_script();
+
+    if ($print_symbol_threshold == 0) {
+	print FH_GNU_SCRIPT "set title \"Line-Histogram\"\n";
+	# use blue #0000FF  color
+	print FH_GNU_SCRIPT "plot \"$gnu_plot_data_file\" using 1:2 with linespoints lc rgb \"#0000FF\" title 'all symbols'";
+    } elsif ($print_symbol_threshold > 0) {
+	# can't handle a negative number
+	&print_line_style_color();
+	&generate_symbol_rank(@sym_rank);   # also needed by the print
+	                                    # data routine
+	print FH_GNU_SCRIPT "plot ";
+
+	$data_column = 2;     # column 1 is X data
+
+	for ($n = 0; $n < $print_symbol_threshold; $n = $n + 1) {
+	    # Last column is sum of counts for all other symbols
+	    $print_rank = $n + 1;
+	    for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+		if ($sym_rank[$i] == $print_rank) {
+		    print FH_GNU_SCRIPT "\"$gnu_plot_data_file\" using 1:$data_column with lines ls $print_rank title '$sym_name[$i]', ";
+		    $data_column = $data_column + 1;
+		}
+	    }
+	}
+
+	# column 1 is X data, last column other y data
+	print FH_GNU_SCRIPT "\"$gnu_plot_data_file\" using 1:$data_column with lines ls 99 title 'Other'\n";
+
+    } else {
+	print "ERROR, unsupported value of print_symbol_threshold = $print_symbol_threshold in print_bin_line_plot_script_file\n";
+    }
+
+
+    close FH_GNU_SCRIPT;
+}
+
+sub print_bin_hist_plot_script_file {
+# script for making a histogram plot 
+    $bin_width = ($end_time - $start_time) / $max_bins;
+
+    &print_base_plot_script();
+    print FH_GNU_SCRIPT "set title \"Histogram\"\n";
+
+    print FH_GNU_SCRIPT "set key invert reverse Left outside\n";
+    print FH_GNU_SCRIPT "set style data histogram\n";
+    print FH_GNU_SCRIPT "set style histogram rowstacked\n";
+    print FH_GNU_SCRIPT "set style fill  solid  noborder\n";
+    print FH_GNU_SCRIPT "set boxwidth 0.5\n";
+
+    if ($print_symbol_threshold == 0) {
+
+	# use blue #0000FF  color
+	print FH_GNU_SCRIPT "plot \"$gnu_plot_data_file\" using 2  lc rgb \"#0000FF\" title 'all symbols'";
+    } elsif ($print_symbol_threshold > 0) {
+	&print_line_style_color();
+	&generate_symbol_rank(@sym_rank);   # also needed by the print
+	                                    # data routine
+	print FH_GNU_SCRIPT "plot ";
+	$data_column = 2;   # X data in column 1
+
+	for ($n = 0; $n < $print_symbol_threshold; $n = $n + 1) {
+	    # Last column is sum of counts for all other symbols
+	    $print_rank = $n + 1;  # column 0 is X data
+	    for ($i = 0; $i < $num_symbols; $i = $i + 1) {
+		if ($sym_rank[$i] == $print_rank) {
+		    print FH_GNU_SCRIPT "\"$gnu_plot_data_file\" using $data_column with boxes ls $print_rank title '$sym_name[$i]', ";
+		    $data_column = $data_column + 1;
+		}
+	    }
+	}
+
+	print FH_GNU_SCRIPT "\"$gnu_plot_data_file\" using  $data_column with boxes ls 99 title 'Other'\n";
+
+    } else {
+	print "ERROR, unsupported value of print_symbol_threshold = $print_symbol_threshold in print_bin_hist_plot_script_file\n";
+    }
+    close FH_GNU_SCRIPT;
+
+}
-- 
1.7.1




------------------------------------------------------------------------------
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.