[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 ------------------------------------------------------------------------------