mirror of
https://github.com/nasa/trick.git
synced 2025-06-17 14:48:19 +00:00
Frame Performance Tool- jperf (#1785)
Some checks failed
Linux Python 2 / build (clang-devel gcc gcc-c++ java-11-openjdk-devel libxml2-devel llvm-devel llvm-static ncurses-devel openmotif openmotif-devel perl perl-Digest-MD5 udunits2 udunits2-devel which zlib-devel python2-devel python3-devel, map[arch:rhel]) (push) Has been cancelled
Linux Python 2 / build (map[], echo package manager already configured, bison clang flex git llvm make maven cmake zip, install -y, echo gtest already installed) (push) Has been cancelled
Linux Python 2 / build (map[arch:debian arch_ver:12 os:ubuntu tag:22.04], 2) (push) Has been cancelled
Linux Python 2 / build (map[arch:rhel arch_ver:7], yum -y install epel-release
yum -y update
, libX11-devel libXt-devel swig3 gtest-devel, yum) (push) Has been cancelled
Linux Python 2 / build (map[arch:rhel arch_ver:8 os:oraclelinux tag:8], 2) (push) Has been cancelled
Linux Python 2 / build (map[arch:rhel arch_ver:8 os:rockylinux tag:8], 2) (push) Has been cancelled
Linux Python 2 / build (map[arch:rhel arch_ver:8], dnf -y install epel-release
dnf -y update
dnf install -y 'dnf-command(config-manager)'
, dnf config-manager --enable powertools
dnf install -y gtest-devel
, dnf, swig diffutils) (push) Has been cancelled
Linux Python 2 / build (map[os:oraclelinux], dnf config-manager --enable ol8_codeready_builder
dnf install -y gtest-devel
) (push) Has been cancelled
Linux Python 2 / build (swig curl g++ libx11-dev libxml2-dev libxt-dev libmotif-common libmotif-dev zlib1g-dev llvm-dev libclang-dev libudunits2-dev libgtest-dev default-jdk python2.7-dev python3-dev python3-pip python3-venv, map[arch:debian], apt-get update, apt-get i… (push) Has been cancelled
32-bit Oracle / trick_32bit_oracle (push) Has been cancelled
Test Docker Hub Images / latest (trick_ubuntu1804) (push) Has been cancelled
More Linux / build (clang-devel gcc gcc-c++ java-11-openjdk-devel libxml2-devel llvm-devel llvm-static ncurses-devel openmotif openmotif-devel perl perl-Digest-MD5 udunits2 udunits2-devel which zlib-devel python2-devel python3-devel, map[arch:rhel]) (push) Has been cancelled
More Linux / build (map[], echo package manager already configured, bison clang flex git llvm make maven cmake zip, install -y, echo gtest already installed) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:10 os:debian tag:10], 2) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:10 os:debian tag:10], 3) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:10], apt-get install -y libgtest-dev
cd /usr/src/gtest
cmake .
make
cp libgtest* /usr/lib/
) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11 os:debian tag:11], 2) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11 os:debian tag:11], 3) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11 os:ubuntu tag:20.04], 2) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11 os:ubuntu tag:20.04], 3) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11], export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y tzdata
) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:12 os:debian tag:bookworm], 2) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:12 os:debian tag:bookworm], 3) (push) Has been cancelled
More Linux / build (map[arch:debian], 2, python2.7-dev) (push) Has been cancelled
More Linux / build (map[arch:rhel arch_ver:8 os:almalinux tag:8], 2) (push) Has been cancelled
More Linux / build (map[arch:rhel arch_ver:8 os:almalinux tag:8], 3) (push) Has been cancelled
More Linux / build (map[arch:rhel arch_ver:8], dnf -y install epel-release
dnf -y update
dnf install -y 'dnf-command(config-manager)'
, dnf config-manager --enable powertools
dnf install -y gtest-devel
, dnf, swig diffutils) (push) Has been cancelled
More Linux / build (swig curl g++ libx11-dev libxml2-dev libxt-dev libmotif-common libmotif-dev zlib1g-dev llvm-dev libclang-dev libudunits2-dev libgtest-dev default-jdk python3-dev python3-pip python3-venv, map[arch:debian], apt-get update, apt-get install -y libg… (push) Has been cancelled
Some checks failed
Linux Python 2 / build (clang-devel gcc gcc-c++ java-11-openjdk-devel libxml2-devel llvm-devel llvm-static ncurses-devel openmotif openmotif-devel perl perl-Digest-MD5 udunits2 udunits2-devel which zlib-devel python2-devel python3-devel, map[arch:rhel]) (push) Has been cancelled
Linux Python 2 / build (map[], echo package manager already configured, bison clang flex git llvm make maven cmake zip, install -y, echo gtest already installed) (push) Has been cancelled
Linux Python 2 / build (map[arch:debian arch_ver:12 os:ubuntu tag:22.04], 2) (push) Has been cancelled
Linux Python 2 / build (map[arch:rhel arch_ver:7], yum -y install epel-release
yum -y update
, libX11-devel libXt-devel swig3 gtest-devel, yum) (push) Has been cancelled
Linux Python 2 / build (map[arch:rhel arch_ver:8 os:oraclelinux tag:8], 2) (push) Has been cancelled
Linux Python 2 / build (map[arch:rhel arch_ver:8 os:rockylinux tag:8], 2) (push) Has been cancelled
Linux Python 2 / build (map[arch:rhel arch_ver:8], dnf -y install epel-release
dnf -y update
dnf install -y 'dnf-command(config-manager)'
, dnf config-manager --enable powertools
dnf install -y gtest-devel
, dnf, swig diffutils) (push) Has been cancelled
Linux Python 2 / build (map[os:oraclelinux], dnf config-manager --enable ol8_codeready_builder
dnf install -y gtest-devel
) (push) Has been cancelled
Linux Python 2 / build (swig curl g++ libx11-dev libxml2-dev libxt-dev libmotif-common libmotif-dev zlib1g-dev llvm-dev libclang-dev libudunits2-dev libgtest-dev default-jdk python2.7-dev python3-dev python3-pip python3-venv, map[arch:debian], apt-get update, apt-get i… (push) Has been cancelled
32-bit Oracle / trick_32bit_oracle (push) Has been cancelled
Test Docker Hub Images / latest (trick_ubuntu1804) (push) Has been cancelled
More Linux / build (clang-devel gcc gcc-c++ java-11-openjdk-devel libxml2-devel llvm-devel llvm-static ncurses-devel openmotif openmotif-devel perl perl-Digest-MD5 udunits2 udunits2-devel which zlib-devel python2-devel python3-devel, map[arch:rhel]) (push) Has been cancelled
More Linux / build (map[], echo package manager already configured, bison clang flex git llvm make maven cmake zip, install -y, echo gtest already installed) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:10 os:debian tag:10], 2) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:10 os:debian tag:10], 3) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:10], apt-get install -y libgtest-dev
cd /usr/src/gtest
cmake .
make
cp libgtest* /usr/lib/
) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11 os:debian tag:11], 2) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11 os:debian tag:11], 3) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11 os:ubuntu tag:20.04], 2) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11 os:ubuntu tag:20.04], 3) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:11], export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y tzdata
) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:12 os:debian tag:bookworm], 2) (push) Has been cancelled
More Linux / build (map[arch:debian arch_ver:12 os:debian tag:bookworm], 3) (push) Has been cancelled
More Linux / build (map[arch:debian], 2, python2.7-dev) (push) Has been cancelled
More Linux / build (map[arch:rhel arch_ver:8 os:almalinux tag:8], 2) (push) Has been cancelled
More Linux / build (map[arch:rhel arch_ver:8 os:almalinux tag:8], 3) (push) Has been cancelled
More Linux / build (map[arch:rhel arch_ver:8], dnf -y install epel-release
dnf -y update
dnf install -y 'dnf-command(config-manager)'
, dnf config-manager --enable powertools
dnf install -y gtest-devel
, dnf, swig diffutils) (push) Has been cancelled
More Linux / build (swig curl g++ libx11-dev libxml2-dev libxt-dev libmotif-common libmotif-dev zlib1g-dev llvm-dev libclang-dev libudunits2-dev libgtest-dev default-jdk python3-dev python3-pip python3-venv, map[arch:debian], apt-get update, apt-get install -y libg… (push) Has been cancelled
* Initial Commit of Frame Performance - jperf * Fix KeyStroke.getKeyStroke call. * Separate reading of file from processing it. * Refactor JobPerf.java to clean up names and organization. * Add statistics reporting to jperf. * Fix min/max issue, and rename types and variables for clarity. * Break up and document the classes that compose JobPerf. * Frame range selection and speed improvements. * Indicate selected frame * Added Jobs-stats and, Frame-details windows, job names,classes, contained jobs and so forth. * Refactor timeline log and improve frame boundary determination. * Fix check of whether one job executes within the bounds of another. * Handle case where and id in the timeline is not found in the S-job_execution file. * Add Trick Logo and Buttons that will be activated in the near future. * Add functionality for advance retreat buttons. * Fix replacement of minIndex with 0.
This commit is contained in:
8
bin/trick-jperf
Executable file
8
bin/trick-jperf
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib ("$RealBin/../libexec/trick/pm", "$RealBin/../lib/trick/pm") ;
|
||||||
|
use launch_java ;
|
||||||
|
|
||||||
|
launch_java("JPERF", "JPerf") ;
|
||||||
|
|
@ -20,6 +20,8 @@ namespace Trick {
|
|||||||
/** Data to save for each timeline sample.\n */
|
/** Data to save for each timeline sample.\n */
|
||||||
struct timeline_t {
|
struct timeline_t {
|
||||||
bool trick_job;
|
bool trick_job;
|
||||||
|
bool isEndOfFrame;
|
||||||
|
bool isTopOfFrame;
|
||||||
double id;
|
double id;
|
||||||
long long start;
|
long long start;
|
||||||
long long stop;
|
long long stop;
|
||||||
|
@ -47,6 +47,12 @@ namespace Trick {
|
|||||||
/** Indicates if a scheduler is handling this job */
|
/** Indicates if a scheduler is handling this job */
|
||||||
bool handled; /**< trick_units(--) */
|
bool handled; /**< trick_units(--) */
|
||||||
|
|
||||||
|
/** Indicates whether this is an "top_of_frame" job. */
|
||||||
|
bool isTopOfFrame; /**< trick_units(--) */
|
||||||
|
|
||||||
|
/** Indicates whether this is an "end_of_frame" job. */
|
||||||
|
bool isEndOfFrame; /**< trick_units(--) */
|
||||||
|
|
||||||
/** The cycle time */
|
/** The cycle time */
|
||||||
double cycle; /**< trick_units(s) */
|
double cycle; /**< trick_units(s) */
|
||||||
|
|
||||||
|
@ -282,6 +282,22 @@
|
|||||||
<finalName>MM</finalName>
|
<finalName>MM</finalName>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
|
<execution>
|
||||||
|
|
||||||
|
<id>jobperf</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>trick.jobperf.JobPerf</mainClass>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
<finalName>JPerf</finalName>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CompareByDuration compares two JobExecutionEvent's by their duration.
|
||||||
|
*/
|
||||||
|
class CompareByDuration implements Comparator<JobExecutionEvent> {
|
||||||
|
public int compare(JobExecutionEvent a, JobExecutionEvent b) {
|
||||||
|
Double dur_a = a.stop - a.start;
|
||||||
|
Double dur_b = b.stop - b.start;
|
||||||
|
if ( dur_a > dur_b) return -1;
|
||||||
|
if ( dur_a < dur_b) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CompareByDuration compares two JobExecutionEvent's by their start time.
|
||||||
|
*/
|
||||||
|
class CompareByStartTime implements Comparator<JobExecutionEvent> {
|
||||||
|
public int compare(JobExecutionEvent a, JobExecutionEvent b) {
|
||||||
|
if ( a.start < b.start) return -1;
|
||||||
|
if ( a.start > a.start) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FrameRecord represents the set of jobs that have been executed during a
|
||||||
|
* frame.
|
||||||
|
*/
|
||||||
|
public class FrameRecord {
|
||||||
|
public ArrayList<JobExecutionEvent> jobEvents;
|
||||||
|
public double start;
|
||||||
|
public double stop;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public FrameRecord() {
|
||||||
|
start = 0.0;
|
||||||
|
stop = 0.0;
|
||||||
|
jobEvents = new ArrayList<JobExecutionEvent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the stop time minus the start time.
|
||||||
|
*/
|
||||||
|
public double getDuration() {
|
||||||
|
return stop - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SortByJobEventDuration() {
|
||||||
|
Collections.sort( jobEvents, new CompareByDuration());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SortByStartTime() {
|
||||||
|
Collections.sort( jobEvents, new CompareByStartTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each jobEvent in the frame, record the number of times
|
||||||
|
* its start time is contained within
|
||||||
|
* another jobs stop/stop range.
|
||||||
|
*/
|
||||||
|
public void CalculateJobContainment() {
|
||||||
|
SortByJobEventDuration();
|
||||||
|
int N = jobEvents.size();
|
||||||
|
for (int i = 0 ; i < (N-1); i++) {
|
||||||
|
for (int j = i+1 ; j < N; j++) {
|
||||||
|
if ( jobEvents.get(i).contains( jobEvents.get(j) )) {
|
||||||
|
jobEvents.get(j).contained ++ ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
public class FrameViewCanvas extends JPanel {
|
||||||
|
private FrameRecord frame;
|
||||||
|
private TraceViewCanvas tvc;
|
||||||
|
private Font headingsFont;
|
||||||
|
private Font dataFont;
|
||||||
|
|
||||||
|
public FrameViewCanvas( TraceViewCanvas tvc, FrameRecord frame ) {
|
||||||
|
this.tvc = tvc;
|
||||||
|
this.frame = frame;
|
||||||
|
dataFont = new Font("Arial", Font.PLAIN, 18);
|
||||||
|
headingsFont = new Font("Arial", Font.BOLD, 18);
|
||||||
|
|
||||||
|
setPreferredSize(new Dimension(800, neededPanelHeight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDrawing(Graphics g) {
|
||||||
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
|
|
||||||
|
RenderingHints rh = new RenderingHints(
|
||||||
|
RenderingHints.KEY_ANTIALIASING,
|
||||||
|
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
rh.put(RenderingHints.KEY_RENDERING,
|
||||||
|
RenderingHints.VALUE_RENDER_QUALITY);
|
||||||
|
|
||||||
|
// Panel Background Color Fill
|
||||||
|
g2d.setPaint(Color.WHITE);
|
||||||
|
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
|
||||||
|
// TITLE
|
||||||
|
g2d.setFont(headingsFont);
|
||||||
|
g2d.setPaint( Color.RED );
|
||||||
|
g2d.drawString("Frame Details", 100, 50);
|
||||||
|
|
||||||
|
// Column Headings
|
||||||
|
g2d.setFont(headingsFont);
|
||||||
|
g2d.setPaint( Color.BLUE );
|
||||||
|
g2d.drawString("Job-ID", 100, 80);
|
||||||
|
g2d.drawString("Job-Class", 180, 80);
|
||||||
|
g2d.drawString("Start-Time", 420, 80);
|
||||||
|
g2d.drawString("Stop-Time", 520, 80);
|
||||||
|
g2d.drawString("Duration", 620, 80);
|
||||||
|
g2d.drawString("Job-Name", 740, 80);
|
||||||
|
|
||||||
|
frame.SortByStartTime();
|
||||||
|
|
||||||
|
// For each job in the frame.
|
||||||
|
int jobY = 100;
|
||||||
|
for (JobExecutionEvent jobExec : frame.jobEvents) {
|
||||||
|
g2d.setPaint( tvc.idToColorMap.getColor( jobExec.id ) );
|
||||||
|
g2d.fillRect(50, jobY, 20, 20);
|
||||||
|
g2d.setPaint( Color.BLACK );
|
||||||
|
jobY += 20;
|
||||||
|
double duration = jobExec.stop - jobExec.start;
|
||||||
|
|
||||||
|
g2d.setFont(dataFont);
|
||||||
|
g2d.drawString(jobExec.id, 100, jobY);
|
||||||
|
g2d.drawString( String.format("%12.6f", jobExec.start), 420, jobY);
|
||||||
|
g2d.drawString( String.format("%12.6f", jobExec.stop), 520, jobY);
|
||||||
|
g2d.drawString( String.format("%12.6f", duration), 620, jobY);
|
||||||
|
|
||||||
|
JobSpecification jobSpec = tvc.jobSpecificationMap.getJobSpecification(jobExec.id);
|
||||||
|
if ( jobSpec == null) {
|
||||||
|
g2d.setPaint( Color.RED );
|
||||||
|
g2d.drawString("UNKNOWN", 180, jobY);
|
||||||
|
g2d.drawString("UNKNOWN", 740, jobY);
|
||||||
|
} else {
|
||||||
|
g2d.drawString(jobSpec.jobClass, 180, jobY);
|
||||||
|
g2d.drawString(jobSpec.name, 740, jobY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame.SortByJobEventDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the height of the FrameViewCanvas (JPanel) needed to render the
|
||||||
|
* jobs in the frame.
|
||||||
|
*/
|
||||||
|
private int neededPanelHeight() {
|
||||||
|
return 20 * frame.jobEvents.size() + 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function paints the FrameViewCanvas (i.e, JPanel) when required.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
doDrawing(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
public class FrameViewWindow extends JFrame {
|
||||||
|
public FrameViewWindow( TraceViewCanvas tvc, FrameRecord frame, int frameNumber ) {
|
||||||
|
|
||||||
|
FrameViewCanvas frameViewCanvas = new FrameViewCanvas(tvc, frame);
|
||||||
|
|
||||||
|
JScrollPane scrollPane = new JScrollPane( frameViewCanvas );
|
||||||
|
scrollPane.getVerticalScrollBar().setUnitIncrement( 20 );
|
||||||
|
|
||||||
|
JPanel scrollingFrameViewCanvas = new JPanel();
|
||||||
|
scrollingFrameViewCanvas.add(scrollPane);
|
||||||
|
scrollingFrameViewCanvas.setLayout(new BoxLayout(scrollingFrameViewCanvas, BoxLayout.X_AXIS));
|
||||||
|
|
||||||
|
setTitle("Frame " + frameNumber);
|
||||||
|
setPreferredSize(new Dimension(1200, 400));
|
||||||
|
add(scrollingFrameViewCanvas);
|
||||||
|
pack();
|
||||||
|
setVisible(true);
|
||||||
|
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||||
|
setFocusable(true);
|
||||||
|
setVisible(true);
|
||||||
|
|
||||||
|
frameViewCanvas.repaint();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class InvalidFrameBoundsExpection is an exception indicating
|
||||||
|
* that the user has specified an illegal range for the frames
|
||||||
|
* to be rendered.
|
||||||
|
*/
|
||||||
|
class InvalidFrameBoundsExpection extends Exception {
|
||||||
|
public InvalidFrameBoundsExpection(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.Math;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class JobExecutionEvent represents one execution/run of a Trick job.
|
||||||
|
* <id> identifies the job. <start> and <stop> specify the
|
||||||
|
* clock times at which the job started and finished.
|
||||||
|
* <isTOF> indicates whether the job was run as
|
||||||
|
* an "top-of-frame" job.
|
||||||
|
*/
|
||||||
|
class JobExecutionEvent {
|
||||||
|
public String id;
|
||||||
|
public boolean isTOF;
|
||||||
|
public boolean isEOF;
|
||||||
|
public double start;
|
||||||
|
public double stop;
|
||||||
|
public int contained;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param identifier identifies the relavant Trick job.
|
||||||
|
* @param isTopOfFrame true if the job is a "top-of-frame" job, otherwise false.
|
||||||
|
* @param isEndOfFrame true if the job is a "end-of-frame" job, otherwise false.
|
||||||
|
* @param start_time the start time (seconds) of the identified job.
|
||||||
|
* @param stop_time the stop time (seconds) of the identified job.
|
||||||
|
*/
|
||||||
|
public JobExecutionEvent(String id, boolean isTOF, boolean isEOF, double start, double stop) {
|
||||||
|
this.id = id;
|
||||||
|
this.isTOF = isTOF;
|
||||||
|
this.isEOF = isEOF;
|
||||||
|
this.start = start;
|
||||||
|
this.stop = stop;
|
||||||
|
contained = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a job's start time is contained
|
||||||
|
* within another jobs stop/stop range.
|
||||||
|
*/
|
||||||
|
public boolean contains( JobExecutionEvent other ) {
|
||||||
|
if ((other.start > this.start) &&
|
||||||
|
(other.start < this.stop)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a String representation of an object of this class.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return ( "JobExecutionEvent: " + id + "," + start + "," + stop );
|
||||||
|
}
|
||||||
|
}
|
202
trick_source/java/src/main/java/trick/jobperf/JobPerf.java
Normal file
202
trick_source/java/src/main/java/trick/jobperf/JobPerf.java
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
/**
|
||||||
|
* Class JobPerf is an application that renders time-line data from a Trick based
|
||||||
|
simulation. It also generates run-time statistics reports for the simulation
|
||||||
|
jobs. It can be run with or without a GUI.
|
||||||
|
*/
|
||||||
|
public class JobPerf {
|
||||||
|
ArrayList<JobExecutionEvent> jobExecEvtList;
|
||||||
|
JobStats jobStats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param args the command line arguments.
|
||||||
|
*/
|
||||||
|
public JobPerf( String[] args ) {
|
||||||
|
TraceViewWindow traceViewWindow;
|
||||||
|
boolean interactive = true;
|
||||||
|
boolean printReport = false;
|
||||||
|
JobStats.SortCriterion sortOrder = JobStats.SortCriterion.MEAN;
|
||||||
|
String timeLineFileName = "in.csv";
|
||||||
|
|
||||||
|
int ii = 0;
|
||||||
|
while (ii < args.length) {
|
||||||
|
switch (args[ii]) {
|
||||||
|
case "-h" :
|
||||||
|
case "--help" : {
|
||||||
|
printHelpText();
|
||||||
|
System.exit(0);
|
||||||
|
} break;
|
||||||
|
case "-x" :
|
||||||
|
case "--nogui" : {
|
||||||
|
interactive = false;
|
||||||
|
} break;
|
||||||
|
case "-p" :
|
||||||
|
case "--report" : {
|
||||||
|
printReport = true;
|
||||||
|
} break;
|
||||||
|
case "-s0" :
|
||||||
|
case "--sort=id" : {
|
||||||
|
sortOrder = JobStats.SortCriterion.ID;
|
||||||
|
} break;
|
||||||
|
case "-s1" :
|
||||||
|
case "--sort=mean" : {
|
||||||
|
sortOrder = JobStats.SortCriterion.MEAN;
|
||||||
|
} break;
|
||||||
|
case "-s2" :
|
||||||
|
case "--sort=stddev" : {
|
||||||
|
sortOrder = JobStats.SortCriterion.STDDEV;
|
||||||
|
} break;
|
||||||
|
case "-s3" :
|
||||||
|
case "--sort=max" : {
|
||||||
|
sortOrder = JobStats.SortCriterion.MAX;
|
||||||
|
} break;
|
||||||
|
case "-s4" :
|
||||||
|
case "--sort=min" : {
|
||||||
|
sortOrder = JobStats.SortCriterion.MIN;
|
||||||
|
} break;
|
||||||
|
default : {
|
||||||
|
timeLineFileName = args[ii];
|
||||||
|
} break;
|
||||||
|
} //switch
|
||||||
|
++ii;
|
||||||
|
} // while
|
||||||
|
|
||||||
|
// All files shall be in the same directory as the timeline file.
|
||||||
|
String filesDir = Paths.get(timeLineFileName).toAbsolutePath().getParent().toString();
|
||||||
|
System.out.println( "\n\nFilesDir = " + filesDir + "\n\n");
|
||||||
|
|
||||||
|
// Generate the JobSpecificationMap from information extracted from the S_job_execution
|
||||||
|
// file, that should be in the same directory as the time-line file.
|
||||||
|
File s_job_execution_file = new File( filesDir + "/S_job_execution" );
|
||||||
|
JobSpecificationMap jobSpecificationMap = null;
|
||||||
|
try {
|
||||||
|
jobSpecificationMap = new JobSpecificationMap( s_job_execution_file );
|
||||||
|
} catch ( java.io.FileNotFoundException e ) {
|
||||||
|
System.out.println("File \"" + s_job_execution_file.toString() + "\" not found.\n");
|
||||||
|
System.exit(0);
|
||||||
|
} catch ( java.io.IOException e ) {
|
||||||
|
System.out.println("IO Exception while attempting to read " + s_job_execution_file.toString() + ".\n");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Color Map
|
||||||
|
KeyedColorMap idToColorMap = null;
|
||||||
|
File colorMapFile = null;
|
||||||
|
try {
|
||||||
|
colorMapFile = new File(filesDir + "/IdToColors.txt");
|
||||||
|
idToColorMap = new KeyedColorMap( colorMapFile.toString());
|
||||||
|
if ( colorMapFile.exists()) {
|
||||||
|
idToColorMap.readFile();
|
||||||
|
}
|
||||||
|
} catch ( java.io.IOException e ) {
|
||||||
|
System.out.println("IO Exception while attempting to read " + colorMapFile.toString() + ".\n");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
jobExecEvtList = getJobExecutionEventList(timeLineFileName, jobSpecificationMap);
|
||||||
|
|
||||||
|
if (printReport) {
|
||||||
|
jobStats = new JobStats(jobExecEvtList);
|
||||||
|
if (sortOrder == JobStats.SortCriterion.ID ) jobStats.SortByID();
|
||||||
|
if (sortOrder == JobStats.SortCriterion.MEAN ) jobStats.SortByMeanValue();
|
||||||
|
if (sortOrder == JobStats.SortCriterion.STDDEV ) jobStats.SortByStdDev();
|
||||||
|
if (sortOrder == JobStats.SortCriterion.MAX ) jobStats.SortByMaxValue();
|
||||||
|
if (sortOrder == JobStats.SortCriterion.MIN ) jobStats.SortByMinValue();
|
||||||
|
jobStats.write( jobSpecificationMap);
|
||||||
|
}
|
||||||
|
if (interactive) {
|
||||||
|
traceViewWindow = new TraceViewWindow(jobExecEvtList, idToColorMap, jobSpecificationMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the usage instructions to the terminal.
|
||||||
|
*/
|
||||||
|
private static void printHelpText() {
|
||||||
|
System.out.println(
|
||||||
|
"----------------------------------------------------------------------\n"
|
||||||
|
+ "usage: trick-jperf [options] <file-name>\n\n"
|
||||||
|
+ "options: \n"
|
||||||
|
+ "-h, --help\n"
|
||||||
|
+ " Print this help text and exit.\n"
|
||||||
|
+ "-x, --nogui\n"
|
||||||
|
+ " Don't run as a GUI application. Command line only.\n"
|
||||||
|
+ "-p, --report\n"
|
||||||
|
+ " Write sorted job statics report to the terminal.\n"
|
||||||
|
+ "-s0, --sort=id\n"
|
||||||
|
+ " Sort job statistics by identifier.\n"
|
||||||
|
+ "-s1, --sort=mean [default]\n"
|
||||||
|
+ " Sort job statistics by mean duration.\n"
|
||||||
|
+ "-s2, --sort=stddev\n"
|
||||||
|
+ " Sort job statistics by standard deviation of duration.\n"
|
||||||
|
+ "-s3, --sort=min\n"
|
||||||
|
+ " Sort job statistics by minimum duration.\n"
|
||||||
|
+ "-s4, --sort=max\n"
|
||||||
|
+ " Sort job statistics by maximum duration.\n"
|
||||||
|
+ "----------------------------------------------------------------------\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the timeline file, resulting in a ArrayList<JobExecutionEvent>.
|
||||||
|
*/
|
||||||
|
private ArrayList<JobExecutionEvent> getJobExecutionEventList( String fileName,
|
||||||
|
JobSpecificationMap jobSpecificationMap ) {
|
||||||
|
String line;
|
||||||
|
String field[];
|
||||||
|
|
||||||
|
ArrayList<JobExecutionEvent> jobExecEvtList = new ArrayList<JobExecutionEvent>();
|
||||||
|
try {
|
||||||
|
BufferedReader in = new BufferedReader( new FileReader(fileName) );
|
||||||
|
|
||||||
|
// Strip the header line off the CSV file.
|
||||||
|
line = in.readLine();
|
||||||
|
|
||||||
|
// Iterate through and process each of the data lines.
|
||||||
|
while( (line = in.readLine()) !=null) {
|
||||||
|
boolean isTOF = false;
|
||||||
|
boolean isEOF = false;
|
||||||
|
field = line.split(",");
|
||||||
|
|
||||||
|
String id = field[0].trim();
|
||||||
|
JobSpecification jobSpec = jobSpecificationMap.getJobSpecification(id);
|
||||||
|
if (jobSpec != null) {
|
||||||
|
if (jobSpec.jobClass.equals("top_of_frame")) {
|
||||||
|
isTOF = true;
|
||||||
|
} else if (jobSpec.jobClass.equals("end_of_frame")) {
|
||||||
|
isEOF = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double start = Double.parseDouble( field[1]);
|
||||||
|
double stop = Double.parseDouble( field[2]);
|
||||||
|
if (start < stop) {
|
||||||
|
JobExecutionEvent evt = new JobExecutionEvent(id, isTOF, isEOF, start, stop);
|
||||||
|
jobExecEvtList.add( evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch ( java.io.FileNotFoundException e ) {
|
||||||
|
System.out.println("File \"" + fileName + "\" not found.\n");
|
||||||
|
System.exit(0);
|
||||||
|
} catch ( java.io.IOException e ) {
|
||||||
|
System.out.println("IO Exception.\n");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
return jobExecEvtList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point for the Java application.
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
JobPerf jobPerf = new JobPerf( args );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class JobSpecification represents ...
|
||||||
|
*/
|
||||||
|
class JobSpecification {
|
||||||
|
public String name;
|
||||||
|
public String jobClass;
|
||||||
|
public int phase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name identifies the relevant Trick job.
|
||||||
|
* @param jobClass the Trick job class.
|
||||||
|
* @param phase the Trick phase number of the Trick job.
|
||||||
|
*/
|
||||||
|
public JobSpecification(String name, String jobClass, int phase) {
|
||||||
|
this.name = name;
|
||||||
|
this.jobClass = jobClass;
|
||||||
|
this.phase = phase;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Create a String representation of an object of this jobClass.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return ( "JobSpecification: " + name + "," + jobClass + "," + phase );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.nio.file.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class JobSpecificationMap associates identifiers with unique RGB colors.
|
||||||
|
*/
|
||||||
|
public class JobSpecificationMap {
|
||||||
|
private Map<String, JobSpecification> jobSpecMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public JobSpecificationMap( File file ) throws IOException, FileNotFoundException {
|
||||||
|
jobSpecMap = new HashMap<String, JobSpecification>();
|
||||||
|
System.out.println( "INSTANCIATING JobSpecificationMap("+ file.toString() +").");
|
||||||
|
BufferedReader in = new BufferedReader( new FileReader( file.toString()) );
|
||||||
|
String line;
|
||||||
|
String field[];
|
||||||
|
|
||||||
|
while( (line = in.readLine()) != null) {
|
||||||
|
if ( line.matches("\\s+1 [|].*$") ) {
|
||||||
|
field = line.split("[|]");
|
||||||
|
if (field.length == 9) {
|
||||||
|
String jobclass = field[2].trim();
|
||||||
|
int phase = Integer.parseInt( field[3].trim());
|
||||||
|
String id = String.format("%.2f", Double.parseDouble( field[7].trim()));
|
||||||
|
String name = field[8].trim();
|
||||||
|
jobSpecMap.put(id, new JobSpecification(name, jobclass, phase));
|
||||||
|
//System.out.println("JobSpec = " + id + "," + jobclass + "," + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO:
|
||||||
|
// Sometimes job specifications, and therefore their IDs are not recorded in the S_job_execution file.
|
||||||
|
// So, when we attempt to find one of these unrecorded Job specs by ID, we get null.
|
||||||
|
//
|
||||||
|
// Job IDs are of the form XX.YY (e.g., 12.03). The XX part is associated with
|
||||||
|
// a particular component sim object. The YY part identifies a specific job from that
|
||||||
|
// sim object.
|
||||||
|
// If an unknown ID shares the XX part of the ID, then perhaps we could at least report which
|
||||||
|
// simobject the job came from.
|
||||||
|
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an identifier, and a JobSpecification to the JobSpecificationMap.
|
||||||
|
* @ param identifier Specifies the key.
|
||||||
|
*/
|
||||||
|
public void addKey( String identifier, JobSpecification jobSpec) {
|
||||||
|
if (!jobSpecMap.containsKey(identifier)) {
|
||||||
|
jobSpecMap.put(identifier, jobSpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an identifier, return the corresponding JobSpecification.
|
||||||
|
* @param identifier the key.
|
||||||
|
* @return the JobSpecification associated with the key.
|
||||||
|
*/
|
||||||
|
public JobSpecification getJobSpecification(String identifier) {
|
||||||
|
return jobSpecMap.get(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // class JobSpecificationMap
|
198
trick_source/java/src/main/java/trick/jobperf/JobStats.java
Normal file
198
trick_source/java/src/main/java/trick/jobperf/JobStats.java
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CompareByID compares two StatisticsRecord's by id.
|
||||||
|
*/
|
||||||
|
class CompareByID implements Comparator<StatisticsRecord> {
|
||||||
|
public int compare(StatisticsRecord a, StatisticsRecord b) {
|
||||||
|
return a.id.compareTo(b.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Class CompareByMeanValue compares two StatisticsRecord's by meanValue.
|
||||||
|
*/
|
||||||
|
class CompareByMeanValue implements Comparator<StatisticsRecord> {
|
||||||
|
public int compare(StatisticsRecord a, StatisticsRecord b) {
|
||||||
|
if ( a.meanValue < b.meanValue) return -1;
|
||||||
|
if ( a.meanValue > b.meanValue) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Class CompareByStdDev compares two StatisticsRecord's by stddev.
|
||||||
|
*/
|
||||||
|
class CompareByStdDev implements Comparator<StatisticsRecord> {
|
||||||
|
public int compare(StatisticsRecord a, StatisticsRecord b) {
|
||||||
|
if ( a.stddev < b.stddev) return -1;
|
||||||
|
if ( a.stddev > b.stddev) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Class CompareByMaxDuration compares two StatisticsRecord's by maxValue.
|
||||||
|
*/
|
||||||
|
class CompareByMaxDuration implements Comparator<StatisticsRecord> {
|
||||||
|
public int compare(StatisticsRecord a, StatisticsRecord b) {
|
||||||
|
if ( a.maxValue < b.maxValue) return -1;
|
||||||
|
if ( a.maxValue > b.maxValue) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Class CompareByMinDuration compares two StatisticsRecord's by minValue.
|
||||||
|
*/
|
||||||
|
class CompareByMinDuration implements Comparator<StatisticsRecord> {
|
||||||
|
public int compare(StatisticsRecord a, StatisticsRecord b) {
|
||||||
|
if ( a.minValue > b.minValue) return -1;
|
||||||
|
if ( a.minValue < b.minValue) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class JobStats represents the statistics, i.e., mean, std deviation, max value,
|
||||||
|
* and min value of the run-duration of each of the Trick jobs in jobExecList. The
|
||||||
|
* statistic records can be sorted by any of the statistics, and by the job id,
|
||||||
|
* prior to being written as a report.
|
||||||
|
*/
|
||||||
|
public class JobStats {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum SortCriterion enumerates the valid ways that JobStats records can be
|
||||||
|
* sorted.
|
||||||
|
*/
|
||||||
|
enum SortCriterion {
|
||||||
|
ID {
|
||||||
|
@Override
|
||||||
|
public String toString() { return "Identifier"; }
|
||||||
|
},
|
||||||
|
MEAN {
|
||||||
|
@Override
|
||||||
|
public String toString() { return "Mean Value"; }
|
||||||
|
},
|
||||||
|
STDDEV {
|
||||||
|
@Override
|
||||||
|
public String toString() { return "Standard Deviation"; }
|
||||||
|
},
|
||||||
|
MAX {
|
||||||
|
@Override
|
||||||
|
public String toString() { return "Maximum Value"; }
|
||||||
|
},
|
||||||
|
MIN {
|
||||||
|
@Override
|
||||||
|
public String toString() { return "Minimum Value"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortCriterion currentSortCriterion = SortCriterion.MEAN;
|
||||||
|
public ArrayList<StatisticsRecord> jobStatisticsList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param jobExecList - the timeline data.
|
||||||
|
*/
|
||||||
|
public JobStats( ArrayList<JobExecutionEvent> jobExecList ) {
|
||||||
|
|
||||||
|
Map<String, RunRegistry> runRegistryMap
|
||||||
|
= new HashMap<String, RunRegistry>();
|
||||||
|
|
||||||
|
for (JobExecutionEvent jobExec : jobExecList ) {
|
||||||
|
RunRegistry runRegistry = runRegistryMap.get(jobExec.id);
|
||||||
|
if (runRegistry != null) {
|
||||||
|
runRegistry.addTimeSpan(jobExec.start, jobExec.stop);
|
||||||
|
} else {
|
||||||
|
runRegistry = new RunRegistry();
|
||||||
|
runRegistry.addTimeSpan(jobExec.start, jobExec.stop);
|
||||||
|
runRegistryMap.put(jobExec.id, runRegistry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jobStatisticsList = new ArrayList<StatisticsRecord>();
|
||||||
|
|
||||||
|
for (Map.Entry<String, RunRegistry> entry : runRegistryMap.entrySet()) {
|
||||||
|
String id = entry.getKey();
|
||||||
|
RunRegistry runRegistry = entry.getValue();
|
||||||
|
double mean = runRegistry.getMeanDuration();
|
||||||
|
double stddev = runRegistry.getStdDev();
|
||||||
|
double min = runRegistry.getMinDuration();
|
||||||
|
double max = runRegistry.getMaxDuration();
|
||||||
|
|
||||||
|
jobStatisticsList.add( new StatisticsRecord(id, mean, stddev, min, max));
|
||||||
|
}
|
||||||
|
SortByMeanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by mean duration in descending order.
|
||||||
|
*/
|
||||||
|
public void SortByID() {
|
||||||
|
Collections.sort( jobStatisticsList, new CompareByID());
|
||||||
|
currentSortCriterion = SortCriterion.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by mean duration in descending order.
|
||||||
|
*/
|
||||||
|
public void SortByMeanValue() {
|
||||||
|
Collections.sort( jobStatisticsList, Collections.reverseOrder( new CompareByMeanValue()));
|
||||||
|
currentSortCriterion = SortCriterion.MEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by standard deviation of duration in descending order.
|
||||||
|
*/
|
||||||
|
public void SortByStdDev() {
|
||||||
|
Collections.sort( jobStatisticsList, Collections.reverseOrder( new CompareByStdDev()));
|
||||||
|
currentSortCriterion = SortCriterion.STDDEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by maximum duration in descending order.
|
||||||
|
*/
|
||||||
|
public void SortByMaxValue() {
|
||||||
|
Collections.sort( jobStatisticsList, Collections.reverseOrder( new CompareByMaxDuration()));
|
||||||
|
currentSortCriterion = SortCriterion.MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort by minimum duration in descending order.
|
||||||
|
*/
|
||||||
|
public void SortByMinValue() {
|
||||||
|
Collections.sort( jobStatisticsList, Collections.reverseOrder( new CompareByMinDuration()));
|
||||||
|
currentSortCriterion = SortCriterion.MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a text report to System.out.
|
||||||
|
*/
|
||||||
|
public void write( JobSpecificationMap jobSpecificationMap ) {
|
||||||
|
|
||||||
|
System.out.println(" [Job Duration Statistics Sorted by " + currentSortCriterion +"]");
|
||||||
|
System.out.println("--------------------------------------------------------------------------------------------------");
|
||||||
|
System.out.println(" Job Id Mean Duration Std Dev Min Duration Max Duration Name");
|
||||||
|
System.out.println("---------- -------------- -------------- -------------- -------------- ---------------------------");
|
||||||
|
|
||||||
|
for (StatisticsRecord jobStatisticsRecord : jobStatisticsList ) {
|
||||||
|
|
||||||
|
JobSpecification jobSpec = jobSpecificationMap.getJobSpecification( jobStatisticsRecord.id);
|
||||||
|
String jobName = null;
|
||||||
|
if (jobSpec != null) {
|
||||||
|
jobName = jobSpec.name;
|
||||||
|
} else {
|
||||||
|
jobName = "UNKNOWN";
|
||||||
|
}
|
||||||
|
System.out.println( String.format("%10s %14.6f %14.6f %14.6f %14.6f %s",
|
||||||
|
jobStatisticsRecord.id,
|
||||||
|
jobStatisticsRecord.meanValue,
|
||||||
|
jobStatisticsRecord.stddev,
|
||||||
|
jobStatisticsRecord.minValue,
|
||||||
|
jobStatisticsRecord.maxValue,
|
||||||
|
jobName
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
public class JobStatsViewCanvas extends JPanel {
|
||||||
|
|
||||||
|
private Font headingsFont;
|
||||||
|
private Font dataFont;
|
||||||
|
JobStats jobStats;
|
||||||
|
JobSpecificationMap jobSpecificationMap;
|
||||||
|
|
||||||
|
public JobStatsViewCanvas( JobStats jobStats,
|
||||||
|
JobSpecificationMap jobSpecificationMap ) {
|
||||||
|
this.jobStats = jobStats;
|
||||||
|
this.jobSpecificationMap = jobSpecificationMap;
|
||||||
|
|
||||||
|
dataFont = new Font("Arial", Font.PLAIN, 18);
|
||||||
|
headingsFont = new Font("Arial", Font.BOLD, 18);
|
||||||
|
|
||||||
|
setPreferredSize(new Dimension(800, neededPanelHeight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDrawing(Graphics g) {
|
||||||
|
|
||||||
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
|
|
||||||
|
RenderingHints rh = new RenderingHints(
|
||||||
|
RenderingHints.KEY_ANTIALIASING,
|
||||||
|
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
rh.put(RenderingHints.KEY_RENDERING,
|
||||||
|
RenderingHints.VALUE_RENDER_QUALITY);
|
||||||
|
|
||||||
|
// Panel Background Color Fill
|
||||||
|
g2d.setPaint(Color.WHITE);
|
||||||
|
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
|
||||||
|
// Title
|
||||||
|
g2d.setFont(headingsFont);
|
||||||
|
g2d.setPaint( Color.RED );
|
||||||
|
g2d.drawString("Jobs Duration Statistics Sorted by " + jobStats.currentSortCriterion, 100, 50);
|
||||||
|
|
||||||
|
// Column Headings
|
||||||
|
g2d.setFont(headingsFont);
|
||||||
|
|
||||||
|
g2d.setPaint( Color.BLUE );
|
||||||
|
g2d.drawString("Job-ID", 100, 80);
|
||||||
|
g2d.drawString("Mean Dur", 200, 80);
|
||||||
|
g2d.drawString("Std Dev", 300, 80);
|
||||||
|
g2d.drawString("Min Dur", 400, 80);
|
||||||
|
g2d.drawString("Max Dur", 500, 80);
|
||||||
|
g2d.drawString("Job-Name", 600, 80);
|
||||||
|
|
||||||
|
// For each record
|
||||||
|
int jobY = 100;
|
||||||
|
for (StatisticsRecord jobStatisticsRecord : jobStats.jobStatisticsList ) {
|
||||||
|
|
||||||
|
g2d.setFont(dataFont);
|
||||||
|
g2d.setPaint( Color.BLACK );
|
||||||
|
|
||||||
|
g2d.drawString(jobStatisticsRecord.id, 100, jobY);
|
||||||
|
g2d.drawString( String.format("%14.6f", jobStatisticsRecord.meanValue), 180, jobY);
|
||||||
|
g2d.drawString( String.format("%14.6f", jobStatisticsRecord.stddev), 280, jobY);
|
||||||
|
g2d.drawString( String.format("%14.6f", jobStatisticsRecord.minValue), 380, jobY);
|
||||||
|
g2d.drawString( String.format("%14.6f", jobStatisticsRecord.maxValue), 480, jobY);
|
||||||
|
|
||||||
|
JobSpecification jobSpec = jobSpecificationMap.getJobSpecification( jobStatisticsRecord.id);
|
||||||
|
if (jobSpec != null) {
|
||||||
|
g2d.drawString(jobSpec.name, 600, jobY);
|
||||||
|
} else {
|
||||||
|
g2d.setPaint( Color.RED );
|
||||||
|
g2d.drawString("UNKNOWN", 600, jobY);
|
||||||
|
}
|
||||||
|
|
||||||
|
jobY += 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the height of the JobStatsCanvas (JPanel) needed to render the
|
||||||
|
* jobs in the frame.
|
||||||
|
*/
|
||||||
|
private int neededPanelHeight() {
|
||||||
|
return 20 * jobStats.jobStatisticsList.size() + 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function paints the JobStatsCanvas (i.e, JPanel) when required.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
doDrawing(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
class SortButtonsToolBar extends JToolBar implements ActionListener {
|
||||||
|
JobStatsViewCanvas statsViewCanvas;
|
||||||
|
private JButton sortByIDButton;
|
||||||
|
private JButton sortByMean;
|
||||||
|
private JButton sortByStdDev;
|
||||||
|
private JButton sortByMin;
|
||||||
|
private JButton sortByMax;
|
||||||
|
|
||||||
|
public SortButtonsToolBar( JobStatsViewCanvas statsViewCanvas ) {
|
||||||
|
this.statsViewCanvas = statsViewCanvas;
|
||||||
|
|
||||||
|
add( new JLabel("Sort by : "));
|
||||||
|
sortByIDButton = new JButton("ID");
|
||||||
|
sortByIDButton.addActionListener(this);
|
||||||
|
sortByIDButton.setActionCommand("sort-by-ID");
|
||||||
|
sortByIDButton.setToolTipText("Sort by Job ID");
|
||||||
|
add(sortByIDButton);
|
||||||
|
|
||||||
|
sortByMean = new JButton("Mean");
|
||||||
|
sortByMean.addActionListener(this);
|
||||||
|
sortByMean.setActionCommand("sort-by-mean");
|
||||||
|
sortByMean.setToolTipText("Sort by Mean Job Run Duration");
|
||||||
|
add(sortByMean);
|
||||||
|
|
||||||
|
sortByStdDev = new JButton("Std Dev");
|
||||||
|
sortByStdDev.addActionListener(this);
|
||||||
|
sortByStdDev.setActionCommand("sort-by-std-dev");
|
||||||
|
sortByStdDev.setToolTipText("Sort by Std Deviation of Job Run Duration");
|
||||||
|
add(sortByStdDev);
|
||||||
|
|
||||||
|
sortByMin = new JButton("Min");
|
||||||
|
sortByMin.addActionListener(this);
|
||||||
|
sortByMin.setActionCommand("sort-by-min");
|
||||||
|
sortByMin.setToolTipText("Sort by Minimum Job Run Duration");
|
||||||
|
add(sortByMin);
|
||||||
|
|
||||||
|
sortByMax = new JButton("Max");
|
||||||
|
sortByMax.addActionListener(this);
|
||||||
|
sortByMax.setActionCommand("sort-by-max");
|
||||||
|
sortByMax.setToolTipText("Sort by Maximum Job Run Duration");
|
||||||
|
add(sortByMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
String s = e.getActionCommand();
|
||||||
|
switch (s) {
|
||||||
|
case "sort-by-ID":
|
||||||
|
statsViewCanvas.jobStats.SortByID();
|
||||||
|
statsViewCanvas.repaint();
|
||||||
|
break;
|
||||||
|
case "sort-by-mean":
|
||||||
|
statsViewCanvas.jobStats.SortByMeanValue();
|
||||||
|
statsViewCanvas.repaint();
|
||||||
|
break;
|
||||||
|
case "sort-by-std-dev":
|
||||||
|
statsViewCanvas.jobStats.SortByStdDev();
|
||||||
|
statsViewCanvas.repaint();
|
||||||
|
break;
|
||||||
|
case "sort-by-min":
|
||||||
|
statsViewCanvas.jobStats.SortByMinValue();
|
||||||
|
statsViewCanvas.repaint();
|
||||||
|
break;
|
||||||
|
case "sort-by-max":
|
||||||
|
statsViewCanvas.jobStats.SortByMaxValue();
|
||||||
|
statsViewCanvas.repaint();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.out.println("Unknown Action Command:" + s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JobStatsViewWindow extends JFrame {
|
||||||
|
|
||||||
|
public JobStatsViewWindow( JobStats jobStats, JobSpecificationMap jobSpecificationMap ) {
|
||||||
|
|
||||||
|
JobStatsViewCanvas statsViewCanvas = new JobStatsViewCanvas( jobStats, jobSpecificationMap);
|
||||||
|
|
||||||
|
JScrollPane scrollPane = new JScrollPane( statsViewCanvas );
|
||||||
|
scrollPane.setPreferredSize(new Dimension(800, 400));
|
||||||
|
scrollPane.getVerticalScrollBar().setUnitIncrement( 20 );
|
||||||
|
|
||||||
|
SortButtonsToolBar toolbar = new SortButtonsToolBar( statsViewCanvas);
|
||||||
|
|
||||||
|
JPanel scrollingJobStatsCanvas = new JPanel();
|
||||||
|
scrollingJobStatsCanvas.setPreferredSize(new Dimension(800, 400));
|
||||||
|
scrollingJobStatsCanvas.add(toolbar);
|
||||||
|
scrollingJobStatsCanvas.add(scrollPane);
|
||||||
|
|
||||||
|
scrollingJobStatsCanvas.setLayout( new BoxLayout(scrollingJobStatsCanvas, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
setTitle("Job Statistics");
|
||||||
|
// setSize(800, 500);
|
||||||
|
setPreferredSize(new Dimension(1200, 500));
|
||||||
|
add(scrollingJobStatsCanvas);
|
||||||
|
pack();
|
||||||
|
setVisible(true);
|
||||||
|
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||||
|
setFocusable(true);
|
||||||
|
setVisible(true);
|
||||||
|
|
||||||
|
statsViewCanvas.repaint();
|
||||||
|
}
|
||||||
|
}
|
125
trick_source/java/src/main/java/trick/jobperf/KeyedColorMap.java
Normal file
125
trick_source/java/src/main/java/trick/jobperf/KeyedColorMap.java
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class KeyedColorMap associates identifiers with unique RGB colors.
|
||||||
|
*/
|
||||||
|
public class KeyedColorMap {
|
||||||
|
private Map<String, Color> colorMap;
|
||||||
|
int minLuminance;
|
||||||
|
String fileName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public KeyedColorMap(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
colorMap = new HashMap<String, Color>();
|
||||||
|
minLuminance = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random color, that's not too dark.
|
||||||
|
* @ return the generated color.
|
||||||
|
*/
|
||||||
|
private Color generateColor () {
|
||||||
|
Random rand = new Random();
|
||||||
|
boolean found = false;
|
||||||
|
int R = 0;
|
||||||
|
int G = 0;
|
||||||
|
int B = 0;
|
||||||
|
|
||||||
|
while (!found) {
|
||||||
|
R = rand.nextInt(256);
|
||||||
|
G = rand.nextInt(256);
|
||||||
|
B = rand.nextInt(256);
|
||||||
|
found = true;
|
||||||
|
// Reference: https://www.w3.org/TR/AERT/#color-contrast
|
||||||
|
double luminance = (0.299*R + 0.587*G + 0.114*B);
|
||||||
|
if (luminance < minLuminance ) found = false;
|
||||||
|
}
|
||||||
|
return new Color( R,G,B);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an identifier, and a generated Color to the KeyedColorMap.
|
||||||
|
* The Color will be generated randomly.
|
||||||
|
* @ param identifier Specifies the key for which a color will be generated.
|
||||||
|
*/
|
||||||
|
public void addKey( String identifier ) {
|
||||||
|
if (!colorMap.containsKey(identifier)) {
|
||||||
|
colorMap.put(identifier, generateColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an identifier, return its color.
|
||||||
|
* @param identifier the key.
|
||||||
|
* @return the Color associated with the key.
|
||||||
|
*/
|
||||||
|
public Color getColor(String identifier) {
|
||||||
|
return colorMap.get(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a color, return the associated key, otherwise return null.
|
||||||
|
* @param searchColor the Color to search for.
|
||||||
|
* @return the identifier associated with the searchColor.
|
||||||
|
*/
|
||||||
|
public String getKeyOfColor(Color searchColor) {
|
||||||
|
for (Map.Entry<String, Color> entry : colorMap.entrySet()) {
|
||||||
|
String id = entry.getKey();
|
||||||
|
Color color = entry.getValue();
|
||||||
|
if (color.getRGB() == searchColor.getRGB()) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the identifier, color key/value pairs of the KeyedColorMap to a file.
|
||||||
|
* @param fileName
|
||||||
|
*/
|
||||||
|
public void writeFile() throws IOException {
|
||||||
|
BufferedWriter out = new BufferedWriter( new FileWriter(fileName) );
|
||||||
|
for (Map.Entry<String, Color> entry : colorMap.entrySet()) {
|
||||||
|
String id = entry.getKey();
|
||||||
|
Color color = entry.getValue();
|
||||||
|
String line = String.format(id + "," + color.getRed() +
|
||||||
|
"," + color.getGreen() +
|
||||||
|
"," + color.getBlue() + "\n");
|
||||||
|
out.write(line, 0, line.length());
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} // method writeFile
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read identifier, color key-value pairs into the KeyedColorMap from a file.
|
||||||
|
* @param fileName
|
||||||
|
*/
|
||||||
|
public void readFile() throws IOException {
|
||||||
|
try {
|
||||||
|
BufferedReader in = new BufferedReader( new FileReader(fileName) );
|
||||||
|
String line;
|
||||||
|
String field[];
|
||||||
|
|
||||||
|
while( (line = in.readLine()) !=null) {
|
||||||
|
field = line.split(",");
|
||||||
|
String id = field[0];
|
||||||
|
int R = Integer.parseInt( field[1]);
|
||||||
|
int G = Integer.parseInt( field[2]);
|
||||||
|
int B = Integer.parseInt( field[3]);
|
||||||
|
colorMap.put(id, new Color(R,G,B));
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
} catch ( java.io.FileNotFoundException e ) {
|
||||||
|
System.out.println("File \"" + fileName + "\" not found.\n");
|
||||||
|
}
|
||||||
|
} // method readFile
|
||||||
|
|
||||||
|
} // class KeyedColorMap
|
@ -0,0 +1,73 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.lang.Math;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RunRegistry represents a list of timeSpan's on which we can calculate
|
||||||
|
* the average (mean), standard deviation, minimum, and maximum of the timeSpans
|
||||||
|
* in the list.
|
||||||
|
*/
|
||||||
|
public class RunRegistry {
|
||||||
|
ArrayList<TimeSpan> timeSpanList;
|
||||||
|
/*
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public RunRegistry() {
|
||||||
|
timeSpanList = new ArrayList<TimeSpan>();
|
||||||
|
}
|
||||||
|
void addTimeSpan(double start, double stop) {
|
||||||
|
TimeSpan timeSpan = new TimeSpan(start, stop);
|
||||||
|
timeSpanList.add(timeSpan);
|
||||||
|
}
|
||||||
|
void addTimeSpan(TimeSpan timeSpan) {
|
||||||
|
timeSpanList.add(timeSpan);
|
||||||
|
}
|
||||||
|
double getMeanDuration() {
|
||||||
|
double mean = 0.0;
|
||||||
|
int N = timeSpanList.size();
|
||||||
|
if (N > 0) {
|
||||||
|
double sum = 0.0;
|
||||||
|
for (TimeSpan timeSpan : timeSpanList ) {
|
||||||
|
sum += timeSpan.getDuration();
|
||||||
|
}
|
||||||
|
mean = sum / N;
|
||||||
|
}
|
||||||
|
return mean;
|
||||||
|
}
|
||||||
|
double getStdDev() {
|
||||||
|
double stddev = 0.0;
|
||||||
|
int N = timeSpanList.size();
|
||||||
|
if (N > 0) {
|
||||||
|
double sum = 0.0;
|
||||||
|
double mean = getMeanDuration();
|
||||||
|
for (TimeSpan timeSpan : timeSpanList ) {
|
||||||
|
double duration = timeSpan.getDuration();
|
||||||
|
double difference = duration - mean;
|
||||||
|
sum += difference * difference;
|
||||||
|
}
|
||||||
|
stddev = Math.sqrt( sum / N );
|
||||||
|
}
|
||||||
|
return stddev;
|
||||||
|
}
|
||||||
|
double getMaxDuration() {
|
||||||
|
double maxDuration = Double.MIN_VALUE;
|
||||||
|
for (TimeSpan timeSpan : timeSpanList ) {
|
||||||
|
double duration = timeSpan.getDuration();
|
||||||
|
if (duration > maxDuration) {
|
||||||
|
maxDuration = duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxDuration;
|
||||||
|
}
|
||||||
|
double getMinDuration() {
|
||||||
|
double minDuration = Double.MAX_VALUE;
|
||||||
|
for (TimeSpan timeSpan : timeSpanList ) {
|
||||||
|
double duration = timeSpan.getDuration();
|
||||||
|
if (duration < minDuration) {
|
||||||
|
minDuration = duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minDuration;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class StatisticsRecord represents the statistics, i.e., mean, std deviation,
|
||||||
|
* max value, and min value of the run-duration of an identified Trick job.
|
||||||
|
*/
|
||||||
|
public class StatisticsRecord {
|
||||||
|
public String id;
|
||||||
|
public double meanValue;
|
||||||
|
public double stddev;
|
||||||
|
public double maxValue;
|
||||||
|
public double minValue;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param id - the job identifier.
|
||||||
|
* @param mean - the mean value of job duration.
|
||||||
|
* @param stddev - the standard deviation of job duration.
|
||||||
|
* @param min - the minimum value of job duration.
|
||||||
|
* @param max - the maximum value of job duration.
|
||||||
|
*/
|
||||||
|
public StatisticsRecord( String id, double mean, double stddev, double min, double max) {
|
||||||
|
this.id = id;
|
||||||
|
this.meanValue = mean;
|
||||||
|
this.stddev = stddev;
|
||||||
|
this.minValue = min;
|
||||||
|
this.maxValue = max;
|
||||||
|
}
|
||||||
|
}
|
24
trick_source/java/src/main/java/trick/jobperf/TimeSpan.java
Normal file
24
trick_source/java/src/main/java/trick/jobperf/TimeSpan.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TimeSpan represents a span of time.
|
||||||
|
*/
|
||||||
|
public class TimeSpan {
|
||||||
|
public double start;
|
||||||
|
public double stop;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param begin the start time.
|
||||||
|
* @param end the end time.
|
||||||
|
*/
|
||||||
|
public TimeSpan( double begin, double end) {
|
||||||
|
start = begin;
|
||||||
|
stop = end;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the stop time minus the start time.
|
||||||
|
*/
|
||||||
|
public double getDuration() {
|
||||||
|
return stop - start;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,456 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TraceViewCanvas renders the simulation timeline data stored in
|
||||||
|
* an ArrayList of JobExecutionEvent's [jobExecEvtList]. Information regarding
|
||||||
|
* mouse clicks are sent to the TraceViewOutputToolBar [outputToolBar.]
|
||||||
|
* @author John M. Penn
|
||||||
|
*/
|
||||||
|
public class TraceViewCanvas extends JPanel {
|
||||||
|
|
||||||
|
public static final int MIN_TRACE_WIDTH = 12;
|
||||||
|
public static final int DEFAULT_TRACE_WIDTH = 18;
|
||||||
|
public static final int MAX_TRACE_WIDTH = 24;
|
||||||
|
public static final int LEFT_MARGIN = 100;
|
||||||
|
public static final int RIGHT_MARGIN = 100;
|
||||||
|
public static final int TOP_MARGIN = 50;
|
||||||
|
public static final int BOTTOM_MARGIN = 20;
|
||||||
|
public static final int DEFAULT_FRAMES_TO_RENDER = 100;
|
||||||
|
|
||||||
|
public KeyedColorMap idToColorMap;
|
||||||
|
public JobSpecificationMap jobSpecificationMap;
|
||||||
|
public JobStats jobStats;
|
||||||
|
|
||||||
|
private int traceWidth;
|
||||||
|
private double frameSize;
|
||||||
|
private double totalDuration;
|
||||||
|
private FrameRecord[] frameArray;
|
||||||
|
private int selectedFrameNumber;
|
||||||
|
private FrameRange frameRenderRange;
|
||||||
|
private BufferedImage image;
|
||||||
|
private TraceViewOutputToolBar outputToolBar;
|
||||||
|
private Cursor crossHairCursor;
|
||||||
|
private Cursor defaultCursor;
|
||||||
|
private Font frameFont12;
|
||||||
|
private Font frameFont18;
|
||||||
|
|
||||||
|
public class FrameRange {
|
||||||
|
public int first;
|
||||||
|
public int last;
|
||||||
|
FrameRange (int first, int last) {
|
||||||
|
this.first = first;
|
||||||
|
this.last = last;
|
||||||
|
}
|
||||||
|
public boolean contains(int n) {
|
||||||
|
return ((first <= n) && (n <= last));
|
||||||
|
}
|
||||||
|
public int size() {
|
||||||
|
return last - first + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param jobExecEvtList the job time line data.
|
||||||
|
* @param outputToolBar the toolbar to which data is to be sent for display.
|
||||||
|
*/
|
||||||
|
public TraceViewCanvas( ArrayList<JobExecutionEvent> jobExecEvtList,
|
||||||
|
TraceViewOutputToolBar outputToolBar,
|
||||||
|
KeyedColorMap idToColorMap,
|
||||||
|
JobSpecificationMap jobSpecificationMap ) {
|
||||||
|
|
||||||
|
traceWidth = DEFAULT_TRACE_WIDTH;
|
||||||
|
frameSize = 1.0;
|
||||||
|
image = null;
|
||||||
|
selectedFrameNumber = 0;
|
||||||
|
|
||||||
|
this.outputToolBar = outputToolBar;
|
||||||
|
this.idToColorMap = idToColorMap;
|
||||||
|
this.jobSpecificationMap = jobSpecificationMap;
|
||||||
|
|
||||||
|
jobStats = new JobStats(jobExecEvtList);
|
||||||
|
|
||||||
|
crossHairCursor = new Cursor( Cursor.CROSSHAIR_CURSOR );
|
||||||
|
defaultCursor = new Cursor( Cursor.DEFAULT_CURSOR );
|
||||||
|
|
||||||
|
frameFont12 = new Font("Arial", Font.PLAIN, 12);
|
||||||
|
frameFont18 = new Font("Arial", Font.PLAIN, 18);
|
||||||
|
|
||||||
|
try {
|
||||||
|
boolean wasTOF = false;
|
||||||
|
boolean wasEOF = false;
|
||||||
|
|
||||||
|
List<FrameRecord> frameList = new ArrayList<FrameRecord>();
|
||||||
|
FrameRecord frameRecord = new FrameRecord();
|
||||||
|
for (JobExecutionEvent jobExec : jobExecEvtList ) {
|
||||||
|
|
||||||
|
if ((!wasTOF && jobExec.isTOF) || ( wasEOF && !jobExec.isEOF )) {
|
||||||
|
|
||||||
|
// Wrap up the previous frame record.
|
||||||
|
frameRecord.stop = jobExec.start;
|
||||||
|
frameRecord.CalculateJobContainment();
|
||||||
|
frameList.add(frameRecord);
|
||||||
|
|
||||||
|
// Start a new frame record.
|
||||||
|
frameRecord = new FrameRecord();
|
||||||
|
frameRecord.start = jobExec.start;
|
||||||
|
}
|
||||||
|
frameRecord.jobEvents.add(jobExec);
|
||||||
|
|
||||||
|
wasTOF = jobExec.isTOF;
|
||||||
|
wasEOF = jobExec.isEOF;
|
||||||
|
|
||||||
|
idToColorMap.addKey(jobExec.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
frameArray = frameList.toArray( new FrameRecord[ frameList.size() ]);
|
||||||
|
|
||||||
|
// Determine the total duration and the average frame size. Notice
|
||||||
|
// that we skip the first frame.
|
||||||
|
totalDuration = 0.0;
|
||||||
|
for (int n=1; n < frameArray.length; n++) {
|
||||||
|
totalDuration += frameArray[n].getDuration();
|
||||||
|
}
|
||||||
|
frameSize = totalDuration/(frameArray.length-1);
|
||||||
|
|
||||||
|
// Set the range of frames to be rendered.
|
||||||
|
int last_frame_to_render = frameArray.length-1;
|
||||||
|
if ( frameArray.length > DEFAULT_FRAMES_TO_RENDER) {
|
||||||
|
last_frame_to_render = DEFAULT_FRAMES_TO_RENDER-1;
|
||||||
|
}
|
||||||
|
frameRenderRange = new FrameRange(0, last_frame_to_render);
|
||||||
|
|
||||||
|
// Write the color map to a file.
|
||||||
|
idToColorMap.writeFile();
|
||||||
|
|
||||||
|
// System.out.println("File loaded.\n");
|
||||||
|
} catch ( java.io.IOException e ) {
|
||||||
|
System.out.println("IO Exception.\n");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPreferredSize(new Dimension(500, neededPanelHeight()));
|
||||||
|
|
||||||
|
ViewListener viewListener = new ViewListener();
|
||||||
|
addMouseListener(viewListener);
|
||||||
|
addMouseMotionListener(viewListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFrameTotal() {
|
||||||
|
return frameArray.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFirstRenderFrame() {
|
||||||
|
return frameRenderRange.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLastRenderFrame() {
|
||||||
|
return frameRenderRange.last;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveRenderFrameRangeBy(int advance) {
|
||||||
|
if ( frameArray.length > 50 ) {
|
||||||
|
|
||||||
|
int maxIndex = frameArray.length - 1;
|
||||||
|
int tFirst = frameRenderRange.first + advance;
|
||||||
|
int tLast = frameRenderRange.last + advance;
|
||||||
|
|
||||||
|
if (tLast > maxIndex) {
|
||||||
|
tLast = maxIndex;
|
||||||
|
tFirst = maxIndex - 49;
|
||||||
|
} else if (tFirst < 0) {
|
||||||
|
tFirst = 0;
|
||||||
|
tLast = 49;
|
||||||
|
}
|
||||||
|
frameRenderRange = new FrameRange(tFirst, tLast);
|
||||||
|
setPreferredSize(new Dimension(500, neededPanelHeight()));
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstRenderFrame(int first) throws InvalidFrameBoundsExpection {
|
||||||
|
if ( (first >= 0) && (first <= frameRenderRange.last)) {
|
||||||
|
frameRenderRange = new FrameRange(first, frameRenderRange.last);
|
||||||
|
setPreferredSize(new Dimension(500, neededPanelHeight()));
|
||||||
|
repaint();
|
||||||
|
} else {
|
||||||
|
throw new InvalidFrameBoundsExpection("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastRenderFrame(int last) throws InvalidFrameBoundsExpection {
|
||||||
|
if ((last >= frameRenderRange.first) && (last < frameArray.length)) {
|
||||||
|
frameRenderRange = new FrameRange(frameRenderRange.first, last);
|
||||||
|
// Re-render this TraceViewCanvas.
|
||||||
|
setPreferredSize(new Dimension(500, neededPanelHeight()));
|
||||||
|
repaint();
|
||||||
|
} else {
|
||||||
|
throw new InvalidFrameBoundsExpection("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the current working frame size (seconds) used for rendering.
|
||||||
|
* Initially this is estimated from the timeline data, but it can be set to
|
||||||
|
* the actual realtime frame size of the user's sim.
|
||||||
|
*/
|
||||||
|
public double getFrameSize() {
|
||||||
|
return frameSize;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Set the frame size (seconds) to be used for rendering the timeline data.
|
||||||
|
* @param duration the frame size.
|
||||||
|
*/
|
||||||
|
public void setFrameSize(double time) {
|
||||||
|
frameSize = time;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the width to be used to render the job traces if the current
|
||||||
|
* trace width is less than MAX_TRACE_WIDTH.
|
||||||
|
*/
|
||||||
|
public void incrementTraceWidth() {
|
||||||
|
if (traceWidth < MAX_TRACE_WIDTH) {
|
||||||
|
traceWidth ++;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrement the width to be used to render the job traces if the current
|
||||||
|
* trace width is greater than MIN_TRACE_WIDTH.
|
||||||
|
*/
|
||||||
|
public void decrementTraceWidth() {
|
||||||
|
if (traceWidth > MIN_TRACE_WIDTH) {
|
||||||
|
traceWidth --;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void displaySelectedFrame() {
|
||||||
|
FrameViewWindow window = new FrameViewWindow( this, frameArray[selectedFrameNumber], selectedFrameNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void displayJobStatsWindow() {
|
||||||
|
JobStatsViewWindow window = new JobStatsViewWindow( jobStats, jobSpecificationMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the trace rectangle contains the point <x,y>, otherwise
|
||||||
|
* false.
|
||||||
|
*/
|
||||||
|
private boolean traceRectContains(int x, int y) {
|
||||||
|
int traceRectXMax = getWidth() - RIGHT_MARGIN;
|
||||||
|
if ( x < (LEFT_MARGIN)) return false;
|
||||||
|
if ( x > (traceRectXMax)) return false;
|
||||||
|
if (( y < TOP_MARGIN) || (y > (TOP_MARGIN + traceRectHeight()))) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ViewListener monitors mouse activity within the TraceViewCanvas.
|
||||||
|
*/
|
||||||
|
private class ViewListener extends MouseInputAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased(MouseEvent e) {
|
||||||
|
int x = e.getX();
|
||||||
|
int y = e.getY();
|
||||||
|
Color color = new Color ( image.getRGB(x,y) );
|
||||||
|
|
||||||
|
// Get and display the ID of the job associated with the color.
|
||||||
|
String id = idToColorMap.getKeyOfColor( color );
|
||||||
|
outputToolBar.setJobID(id);
|
||||||
|
|
||||||
|
// Get and display the job name associated with the ID.
|
||||||
|
JobSpecification jobSpec = jobSpecificationMap.getJobSpecification(id);
|
||||||
|
if (jobSpec != null) {
|
||||||
|
outputToolBar.setJobName(jobSpec.name);
|
||||||
|
outputToolBar.setJobClass(jobSpec.jobClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the frame number that we clicked on from the y-
|
||||||
|
// coordinate of the click position.
|
||||||
|
if ( y > TOP_MARGIN) {
|
||||||
|
selectedFrameNumber = (y - TOP_MARGIN) / traceWidth + frameRenderRange.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the subframe-time where we clicked from the x-coordinate
|
||||||
|
// of the click position.
|
||||||
|
double subFrameClickTime = 0.0;
|
||||||
|
if ( traceRectContains(x, y)) {
|
||||||
|
double pixelsPerSecond = (double)traceRectWidth() / frameSize;
|
||||||
|
subFrameClickTime = (x - LEFT_MARGIN) / pixelsPerSecond;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we clicked on a job trace (above), show the start and stop
|
||||||
|
* times of the job, otherwise clear the start and stop fields.
|
||||||
|
*/
|
||||||
|
if (id != null) {
|
||||||
|
FrameRecord frame = frameArray[selectedFrameNumber];
|
||||||
|
Double clickTime = frame.start + subFrameClickTime;
|
||||||
|
for (JobExecutionEvent jobExec : frame.jobEvents) {
|
||||||
|
if (id.equals( jobExec.id) &&
|
||||||
|
clickTime >= jobExec.start &&
|
||||||
|
clickTime <= jobExec.stop ) {
|
||||||
|
outputToolBar.setJobTimes(jobExec.start, jobExec.stop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repaint();
|
||||||
|
} else {
|
||||||
|
outputToolBar.clearJobFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the cursor to a crossHairCursor if it's over the frame traces,
|
||||||
|
* otherwise, set it to the defaultCursor.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(MouseEvent e) {
|
||||||
|
int x = e.getX();
|
||||||
|
int y = e.getY();
|
||||||
|
if ( traceRectContains(x, y)) {
|
||||||
|
setCursor(crossHairCursor);
|
||||||
|
} else {
|
||||||
|
setCursor(defaultCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the height of the trace rectangle.
|
||||||
|
*/
|
||||||
|
private int traceRectHeight() {
|
||||||
|
return traceWidth * frameRenderRange.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the width of the trace rectangle.
|
||||||
|
*/
|
||||||
|
private int traceRectWidth() {
|
||||||
|
return ( getWidth() - LEFT_MARGIN - RIGHT_MARGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the height of the TraceViewCanvas (JPanel) needed to render the
|
||||||
|
* selected range of frames.
|
||||||
|
*/
|
||||||
|
private int neededPanelHeight() {
|
||||||
|
return traceWidth * frameRenderRange.size() + TOP_MARGIN + BOTTOM_MARGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the job execution traces in the jobExecEvtList.
|
||||||
|
*/
|
||||||
|
private void doDrawing(Graphics g) {
|
||||||
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
|
|
||||||
|
RenderingHints rh = new RenderingHints(
|
||||||
|
RenderingHints.KEY_ANTIALIASING,
|
||||||
|
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
|
||||||
|
rh.put(RenderingHints.KEY_RENDERING,
|
||||||
|
RenderingHints.VALUE_RENDER_QUALITY);
|
||||||
|
|
||||||
|
int traceRectHeight = traceRectHeight();
|
||||||
|
int traceRectWidth = traceRectWidth();
|
||||||
|
double pixelsPerSecond = (double)traceRectWidth / frameSize;
|
||||||
|
|
||||||
|
// Panel Background Color Fill
|
||||||
|
g2d.setPaint(Color.WHITE);
|
||||||
|
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
|
||||||
|
// Frame Trace Rectangle Fill
|
||||||
|
g2d.setPaint(Color.BLACK);
|
||||||
|
g2d.fillRect(LEFT_MARGIN, TOP_MARGIN, traceRectWidth, traceRectHeight());
|
||||||
|
|
||||||
|
if (traceWidth >= DEFAULT_TRACE_WIDTH) {
|
||||||
|
g2d.setFont(frameFont18);
|
||||||
|
} else {
|
||||||
|
g2d.setFont(frameFont12);
|
||||||
|
}
|
||||||
|
|
||||||
|
FontMetrics fm = g2d.getFontMetrics();
|
||||||
|
int TX = 0;
|
||||||
|
|
||||||
|
String FN_text = "Frame #";
|
||||||
|
TX = (LEFT_MARGIN - fm.stringWidth(FN_text))/2;
|
||||||
|
g2d.drawString (FN_text, TX, 40);
|
||||||
|
|
||||||
|
g2d.drawString ("Top of Frame", LEFT_MARGIN, 40);
|
||||||
|
|
||||||
|
String EOF_text = "End of Frame";
|
||||||
|
TX = LEFT_MARGIN + traceRectWidth - fm.stringWidth(EOF_text);
|
||||||
|
g2d.drawString (EOF_text, TX, 40);
|
||||||
|
|
||||||
|
// Draw each frame in the selected range of frames to be rendered.
|
||||||
|
for (int n = frameRenderRange.first;
|
||||||
|
n <= frameRenderRange.last;
|
||||||
|
n++) {
|
||||||
|
|
||||||
|
FrameRecord frame = frameArray[n];
|
||||||
|
int jobY = TOP_MARGIN + (n - frameRenderRange.first) * traceWidth;
|
||||||
|
|
||||||
|
// Draw frame number.
|
||||||
|
if (n == selectedFrameNumber) {
|
||||||
|
g2d.setPaint(Color.RED);
|
||||||
|
// g2d.drawString ( "\u25b6", 20, jobY + traceWidth - 2);
|
||||||
|
g2d.drawString ( "\u25c0", 80, jobY + traceWidth - 2);
|
||||||
|
// g2d.fillRect(LEFT_MARGIN-traceWidth, jobY, traceWidth, traceWidth);
|
||||||
|
} else {
|
||||||
|
g2d.setPaint(Color.BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
g2d.drawString ( String.format("%d", n), 40, jobY + traceWidth - 2);
|
||||||
|
|
||||||
|
// Draw the frame
|
||||||
|
// NOTE that the jobEvents within the frame are expected to be sorted in duration-order,
|
||||||
|
// so that smaller sub-jobs are not obscurred.
|
||||||
|
|
||||||
|
for (JobExecutionEvent jobExec : frame.jobEvents) {
|
||||||
|
int jobStartX = (int)((jobExec.start - frame.start) * pixelsPerSecond) + LEFT_MARGIN;
|
||||||
|
int jobWidth = (int)((jobExec.stop - jobExec.start) * pixelsPerSecond);
|
||||||
|
g2d.setPaint( idToColorMap.getColor( jobExec.id ) );
|
||||||
|
int jobHeight = traceWidth - 2;
|
||||||
|
if (jobExec.contained > 1) {
|
||||||
|
jobHeight = traceWidth / jobExec.contained;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int jobStartY = jobY + (traceWidth - 2) - jobHeight;
|
||||||
|
g2d.fillRect(jobStartX, jobY, jobWidth, jobHeight);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function paints the TraceViewCanvas (i.e, JPanel) when required.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
|
||||||
|
Graphics2D g2 = image.createGraphics();
|
||||||
|
doDrawing(g2);
|
||||||
|
g.drawImage(image, 0, 0, this);
|
||||||
|
g2.dispose();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,176 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TraceViewInputToolBar initially displays an estimate of the frame size
|
||||||
|
* for the JobPerf input timeline data. A user may also enter the intended frame
|
||||||
|
* size into the JTextField, and pressing the "Set" button, which calls
|
||||||
|
* traceView.setFrameSize( newFrameSize );
|
||||||
|
*
|
||||||
|
* Class TraceViewInputToolBar aggregates the following GUI components:
|
||||||
|
* TraceViewInputToolBar (isa JToolBar)
|
||||||
|
* JLabel ()
|
||||||
|
* JTextField [frameSizeField]
|
||||||
|
* JLabel
|
||||||
|
* JLabel
|
||||||
|
* JTextField [firstRenderFrameField]
|
||||||
|
* JLabel
|
||||||
|
* JTextField [lastRenderFrameField]
|
||||||
|
*/
|
||||||
|
public class TraceViewInputToolBar extends JToolBar implements ActionListener {
|
||||||
|
|
||||||
|
private TraceViewCanvas traceView;
|
||||||
|
private JTextField frameSizeField;
|
||||||
|
private JButton frameDetailsButton;
|
||||||
|
private JButton advanceRangeButton;
|
||||||
|
private JButton retreatRangeButton;
|
||||||
|
private JTextField firstRenderFrameField;
|
||||||
|
private JTextField lastRenderFrameField;
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param tvc TraceViewCanvas to be controlled.
|
||||||
|
*/
|
||||||
|
public TraceViewInputToolBar (TraceViewCanvas tvc) {
|
||||||
|
traceView = tvc;
|
||||||
|
|
||||||
|
add( new JLabel(" Frame Size (Avg): "));
|
||||||
|
frameSizeField = new JTextField(10);
|
||||||
|
frameSizeField.setText( String.format("%8.4f", traceView.getFrameSize()) );
|
||||||
|
add(frameSizeField);
|
||||||
|
frameSizeField.addKeyListener( new KeyAdapter() {
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
setFrameSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frameDetailsButton = new JButton("Frame Details");
|
||||||
|
frameDetailsButton.addActionListener(this);
|
||||||
|
frameDetailsButton.setActionCommand("display-frame-details");
|
||||||
|
frameDetailsButton.setToolTipText("Display the job details of the selected frame.");
|
||||||
|
add(frameDetailsButton);
|
||||||
|
|
||||||
|
add( new JLabel( String.format(" Frames : [%d ... %d]", 0, traceView.getFrameTotal()-1 )));
|
||||||
|
|
||||||
|
add( new JLabel(" Selected Range: "));
|
||||||
|
|
||||||
|
firstRenderFrameField = new JTextField(10);
|
||||||
|
firstRenderFrameField.setText( String.format("%d", traceView.getFirstRenderFrame()) );
|
||||||
|
add(firstRenderFrameField);
|
||||||
|
firstRenderFrameField.addKeyListener( new KeyAdapter() {
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
setFirstRenderFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add( new JLabel("..."));
|
||||||
|
lastRenderFrameField = new JTextField(10);
|
||||||
|
lastRenderFrameField.setText( String.format("%d", traceView.getLastRenderFrame()) );
|
||||||
|
add(lastRenderFrameField);
|
||||||
|
lastRenderFrameField.addKeyListener( new KeyAdapter() {
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
setLastRenderFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
advanceRangeButton = new JButton("\u25bc");
|
||||||
|
advanceRangeButton.addActionListener(this);
|
||||||
|
advanceRangeButton.setActionCommand("advance-frame-range");
|
||||||
|
advanceRangeButton.setToolTipText("Advance the selected range of frames to be displayed.");
|
||||||
|
add(advanceRangeButton);
|
||||||
|
|
||||||
|
retreatRangeButton = new JButton("\u25b2");
|
||||||
|
retreatRangeButton.addActionListener(this);
|
||||||
|
retreatRangeButton.setActionCommand("retreat-frame-range");
|
||||||
|
retreatRangeButton.setToolTipText("Retreat the selected range of frames to be displayed.");
|
||||||
|
add(retreatRangeButton);
|
||||||
|
|
||||||
|
add( new JLabel(" "));
|
||||||
|
|
||||||
|
// Add Trick LOGO.
|
||||||
|
try {
|
||||||
|
BufferedImage image = ImageIO.read(getClass().getResource("/trick/common/resources/trick_small.gif"));
|
||||||
|
add( new JLabel( new ImageIcon(image)));
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("Failed to load image.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
String s = e.getActionCommand();
|
||||||
|
switch (s) {
|
||||||
|
case "display-frame-details":
|
||||||
|
traceView.displaySelectedFrame();
|
||||||
|
break;
|
||||||
|
case "advance-frame-range":
|
||||||
|
moveRenderFrameRangeBy(50);
|
||||||
|
break;
|
||||||
|
case "retreat-frame-range":
|
||||||
|
moveRenderFrameRangeBy(-50);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.out.println("Unknown Action Command:" + s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveRenderFrameRangeBy(int advance) {
|
||||||
|
traceView.moveRenderFrameRangeBy(advance);
|
||||||
|
firstRenderFrameField.setText( String.format("%d", traceView.getFirstRenderFrame()));
|
||||||
|
lastRenderFrameField.setText( String.format("%d", traceView.getLastRenderFrame()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFirstRenderFrame() {
|
||||||
|
int newStartFrame = 0;
|
||||||
|
try {
|
||||||
|
newStartFrame = Integer.parseInt( firstRenderFrameField.getText() );
|
||||||
|
traceView.setFirstRenderFrame( newStartFrame );
|
||||||
|
} catch ( NumberFormatException e) {
|
||||||
|
firstRenderFrameField.setText( String.format("%d", traceView.getFirstRenderFrame()));
|
||||||
|
} catch ( InvalidFrameBoundsExpection e) {
|
||||||
|
firstRenderFrameField.setText( String.format("%d", traceView.getFirstRenderFrame()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLastRenderFrame() {
|
||||||
|
int newFinalFrame = 0;
|
||||||
|
try {
|
||||||
|
newFinalFrame = Integer.parseInt( lastRenderFrameField.getText() );
|
||||||
|
traceView.setLastRenderFrame( newFinalFrame );
|
||||||
|
} catch ( NumberFormatException e) {
|
||||||
|
lastRenderFrameField.setText( String.format("%d", traceView.getLastRenderFrame()));
|
||||||
|
} catch (InvalidFrameBoundsExpection e) {
|
||||||
|
lastRenderFrameField.setText( String.format("%d", traceView.getLastRenderFrame()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFrameSize() {
|
||||||
|
double newFrameSize = 0.0;
|
||||||
|
try {
|
||||||
|
newFrameSize = Double.parseDouble( frameSizeField.getText() );
|
||||||
|
} catch ( NumberFormatException e) {
|
||||||
|
frameSizeField.setText( String.format("%8.4f", traceView.getFrameSize()) );
|
||||||
|
}
|
||||||
|
if ( newFrameSize > 0.0) {
|
||||||
|
traceView.setFrameSize( newFrameSize );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TraceViewMenuBar represents the menu bar of the JobPerf application.
|
||||||
|
* It aggregates the following GUI components:
|
||||||
|
* JMenuBar [this]
|
||||||
|
* JMenu [fileMenu]
|
||||||
|
* JMenuItem [fileMenuExit], Action: Call System.exit(0);
|
||||||
|
* JMenu [viewMenu]
|
||||||
|
* JMenu [traceSizeMenu]
|
||||||
|
* JMenuItem [traceSizeIncrease], Action: Call traceView.incrementTraceWidth().
|
||||||
|
* JMenuItem [traceSizeDecrease], Action: Call traceView.decrementTraceWidth()
|
||||||
|
*/
|
||||||
|
public class TraceViewMenuBar extends JMenuBar implements ActionListener {
|
||||||
|
|
||||||
|
private TraceViewCanvas traceView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param tvc the TraceViewCanvas to be controlled by this menu bar.
|
||||||
|
*/
|
||||||
|
public TraceViewMenuBar(TraceViewCanvas tvc) {
|
||||||
|
traceView = tvc;
|
||||||
|
|
||||||
|
JMenu fileMenu = new JMenu("File");
|
||||||
|
JMenuItem fileMenuExit = new JMenuItem("Exit");
|
||||||
|
fileMenuExit.setActionCommand("exit");
|
||||||
|
KeyStroke ctrlQ = KeyStroke.getKeyStroke('Q', InputEvent.CTRL_MASK );
|
||||||
|
fileMenuExit.setAccelerator(ctrlQ);
|
||||||
|
fileMenuExit.addActionListener(this);
|
||||||
|
fileMenu.add(fileMenuExit);
|
||||||
|
add(fileMenu);
|
||||||
|
|
||||||
|
JMenu viewMenu = new JMenu("View");
|
||||||
|
|
||||||
|
JMenuItem traceSizeIncrease = new JMenuItem("Increase Trace Width");
|
||||||
|
traceSizeIncrease.setActionCommand("increase-trace_width");
|
||||||
|
KeyStroke ctrlPlus = KeyStroke.getKeyStroke('=', InputEvent.CTRL_MASK );
|
||||||
|
traceSizeIncrease.setAccelerator(ctrlPlus);
|
||||||
|
traceSizeIncrease.addActionListener(this);
|
||||||
|
viewMenu.add(traceSizeIncrease);
|
||||||
|
|
||||||
|
JMenuItem traceSizeDecrease = new JMenuItem("Decrease Trace Width");
|
||||||
|
traceSizeDecrease.setActionCommand("decrease-trace_width");
|
||||||
|
KeyStroke ctrlMinus = KeyStroke.getKeyStroke('-', InputEvent.CTRL_MASK);
|
||||||
|
traceSizeDecrease.setAccelerator(ctrlMinus);
|
||||||
|
traceSizeDecrease.addActionListener(this);
|
||||||
|
viewMenu.add(traceSizeDecrease);
|
||||||
|
|
||||||
|
viewMenu.addSeparator();
|
||||||
|
|
||||||
|
JMenuItem showFrame = new JMenuItem("Frame Details ...");
|
||||||
|
showFrame.setActionCommand("expand-selected-frame");
|
||||||
|
KeyStroke ctrlF = KeyStroke.getKeyStroke('F', InputEvent.CTRL_MASK);
|
||||||
|
showFrame.setAccelerator(ctrlF);
|
||||||
|
showFrame.addActionListener(this);
|
||||||
|
viewMenu.add(showFrame);
|
||||||
|
|
||||||
|
JMenuItem showStats = new JMenuItem("Job Statistics ...");
|
||||||
|
showStats.setActionCommand("show-job-stats");
|
||||||
|
KeyStroke ctrlV = KeyStroke.getKeyStroke('V', InputEvent.CTRL_MASK);
|
||||||
|
showStats.setAccelerator(ctrlV);
|
||||||
|
showStats.addActionListener(this);
|
||||||
|
viewMenu.add(showStats);
|
||||||
|
|
||||||
|
add(viewMenu);
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
String s = e.getActionCommand();
|
||||||
|
switch (s) {
|
||||||
|
case "increase-trace_width":
|
||||||
|
traceView.incrementTraceWidth();
|
||||||
|
break;
|
||||||
|
case "decrease-trace_width":
|
||||||
|
traceView.decrementTraceWidth();
|
||||||
|
break;
|
||||||
|
case "expand-selected-frame":
|
||||||
|
traceView.displaySelectedFrame();
|
||||||
|
break;
|
||||||
|
case "show-job-stats":
|
||||||
|
traceView.jobStats.SortByID();
|
||||||
|
traceView.displayJobStatsWindow();
|
||||||
|
break;
|
||||||
|
case "exit":
|
||||||
|
System.exit(0);
|
||||||
|
default:
|
||||||
|
System.out.println("Unknown Action Command:" + s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TraceViewOutputToolBar displays information output from a
|
||||||
|
* TraceViewCanvas.
|
||||||
|
*/
|
||||||
|
class TraceViewOutputToolBar extends JToolBar {
|
||||||
|
private JTextField IDField;
|
||||||
|
private JTextField nameField;
|
||||||
|
private JTextField classField;
|
||||||
|
private JTextField startField;
|
||||||
|
private JTextField stopField;
|
||||||
|
// private JTextField frameNumberField;
|
||||||
|
private JTextField durationField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
public TraceViewOutputToolBar () {
|
||||||
|
|
||||||
|
add( new JLabel(" Job ID: "));
|
||||||
|
IDField = new JTextField(5);
|
||||||
|
IDField.setEditable(false);
|
||||||
|
IDField.setText( "");
|
||||||
|
add(IDField);
|
||||||
|
|
||||||
|
add( new JLabel(" Name: "));
|
||||||
|
nameField = new JTextField(25);
|
||||||
|
nameField.setEditable(false);
|
||||||
|
nameField.setText( "");
|
||||||
|
add(nameField);
|
||||||
|
|
||||||
|
add( new JLabel(" Class: "));
|
||||||
|
classField = new JTextField(12);
|
||||||
|
classField.setEditable(false);
|
||||||
|
classField.setText( "");
|
||||||
|
add(classField);
|
||||||
|
|
||||||
|
add( new JLabel(" Start: "));
|
||||||
|
startField = new JTextField(6);
|
||||||
|
startField.setEditable(false);
|
||||||
|
startField.setText( "");
|
||||||
|
add(startField);
|
||||||
|
|
||||||
|
add( new JLabel(" Stop: "));
|
||||||
|
stopField = new JTextField(6);
|
||||||
|
stopField.setEditable(false);
|
||||||
|
stopField.setText( "");
|
||||||
|
add(stopField);
|
||||||
|
|
||||||
|
add( new JLabel(" Duration: "));
|
||||||
|
durationField = new JTextField(6);
|
||||||
|
durationField.setEditable(false);
|
||||||
|
durationField.setText( "");
|
||||||
|
add(durationField);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id job identifier to display.
|
||||||
|
*/
|
||||||
|
public void setJobID(String id) {
|
||||||
|
IDField.setText( id );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id job identifier to display.
|
||||||
|
*/
|
||||||
|
public void setJobName(String name) {
|
||||||
|
nameField.setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id job class to display.
|
||||||
|
*/
|
||||||
|
public void setJobClass(String name) {
|
||||||
|
classField.setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param time to be displayed in the job start field.
|
||||||
|
*/
|
||||||
|
public void setJobTimes(Double start_time, Double stop_time) {
|
||||||
|
startField.setText( String.format("%8.4f", start_time) );
|
||||||
|
stopField.setText( String.format("%8.4f", stop_time) );
|
||||||
|
Double duration = stop_time - start_time;
|
||||||
|
durationField.setText( String.format("%8.4f", duration) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the startField and stopField.
|
||||||
|
*/
|
||||||
|
public void clearJobFields() {
|
||||||
|
nameField.setText("");
|
||||||
|
classField.setText("");
|
||||||
|
startField.setText("");
|
||||||
|
stopField.setText("");
|
||||||
|
durationField.setText("");
|
||||||
|
IDField.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package trick.jobperf;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TraceViewWindow represents the main window of the JobPerf application.
|
||||||
|
* It aggregates the following GUI components:
|
||||||
|
*
|
||||||
|
* - TraceViewMenuBar [menuBar]
|
||||||
|
* - TraceViewInputToolBar [toolbar]
|
||||||
|
* - JPanel [mainPanel]
|
||||||
|
* - JPanel [tracePanel]
|
||||||
|
* - JScrollPane [scrollPane]
|
||||||
|
* - TraceViewCanvas [traceViewCanvas]
|
||||||
|
* - TraceViewOutputToolBar [outputToolBar]
|
||||||
|
*/
|
||||||
|
public class TraceViewWindow extends JFrame {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param jobExecList an ArrayList of JobExecutionEvent, i.e., the job timeline data.
|
||||||
|
*/
|
||||||
|
public TraceViewWindow( ArrayList<JobExecutionEvent> jobExecList,
|
||||||
|
KeyedColorMap idToColorMap,
|
||||||
|
JobSpecificationMap jobSpecificationMap ) {
|
||||||
|
|
||||||
|
TraceViewOutputToolBar outputToolBar = new TraceViewOutputToolBar();
|
||||||
|
|
||||||
|
TraceViewCanvas traceViewCanvas = new TraceViewCanvas( jobExecList, outputToolBar, idToColorMap, jobSpecificationMap);
|
||||||
|
|
||||||
|
TraceViewMenuBar menuBar = new TraceViewMenuBar( traceViewCanvas);
|
||||||
|
setJMenuBar(menuBar);
|
||||||
|
|
||||||
|
TraceViewInputToolBar nToolBar = new TraceViewInputToolBar( traceViewCanvas );
|
||||||
|
add(nToolBar, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
JScrollPane scrollPane = new JScrollPane( traceViewCanvas );
|
||||||
|
scrollPane.setPreferredSize(new Dimension(800, 400));
|
||||||
|
scrollPane.getVerticalScrollBar().setUnitIncrement( 20 );
|
||||||
|
|
||||||
|
JPanel tracePanel = new JPanel();
|
||||||
|
tracePanel.setPreferredSize(new Dimension(800, 400));
|
||||||
|
tracePanel.add(scrollPane);
|
||||||
|
tracePanel.setLayout(new BoxLayout(tracePanel, BoxLayout.X_AXIS));
|
||||||
|
|
||||||
|
JPanel mainPanel = new JPanel();
|
||||||
|
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
|
||||||
|
mainPanel.add(tracePanel);
|
||||||
|
|
||||||
|
add(outputToolBar, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
setTitle("JobPerf");
|
||||||
|
setSize(800, 500);
|
||||||
|
add(mainPanel);
|
||||||
|
pack();
|
||||||
|
setVisible(true);
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
setFocusable(true);
|
||||||
|
setVisible(true);
|
||||||
|
|
||||||
|
traceViewCanvas.repaint();
|
||||||
|
}
|
||||||
|
}
|
@ -385,6 +385,7 @@ int Trick::FrameLog::frame_clock_stop(Trick::JobData * curr_job) {
|
|||||||
mode = Run;
|
mode = Run;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @li Save all cyclic job start & stop times for this frame into timeline structure. */
|
/** @li Save all cyclic job start & stop times for this frame into timeline structure. */
|
||||||
if ((mode==Run) || (mode==Step)) { // cyclic job
|
if ((mode==Run) || (mode==Step)) { // cyclic job
|
||||||
if (tl_count[thread] < tl_max_samples) {
|
if (tl_count[thread] < tl_max_samples) {
|
||||||
@ -392,6 +393,8 @@ int Trick::FrameLog::frame_clock_stop(Trick::JobData * curr_job) {
|
|||||||
timeline[thread][tl_count[thread]].start = target_job->rt_start_time;
|
timeline[thread][tl_count[thread]].start = target_job->rt_start_time;
|
||||||
timeline[thread][tl_count[thread]].stop = target_job->rt_stop_time;
|
timeline[thread][tl_count[thread]].stop = target_job->rt_stop_time;
|
||||||
timeline[thread][tl_count[thread]].trick_job = target_job->tags.count("TRK");
|
timeline[thread][tl_count[thread]].trick_job = target_job->tags.count("TRK");
|
||||||
|
timeline[thread][tl_count[thread]].isEndOfFrame = target_job->isEndOfFrame;
|
||||||
|
timeline[thread][tl_count[thread]].isTopOfFrame = target_job->isTopOfFrame;
|
||||||
tl_count[thread]++;
|
tl_count[thread]++;
|
||||||
}
|
}
|
||||||
/** @li Save all non-cyclic job start & stop times for this frame into timeline_other structure. */
|
/** @li Save all non-cyclic job start & stop times for this frame into timeline_other structure. */
|
||||||
@ -583,8 +586,41 @@ int Trick::FrameLog::shutdown() {
|
|||||||
return(0) ;
|
return(0) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ================================================================
|
||||||
|
// NEW Time-line for Jperf
|
||||||
|
// ================================================================
|
||||||
|
for (int thread_num = 0; thread_num < num_threads; thread_num ++) {
|
||||||
|
|
||||||
|
if (thread_num == 0) {
|
||||||
|
snprintf(log_buff, sizeof(log_buff), "%s/log_newtimeline.csv", command_line_args_get_output_dir());
|
||||||
|
} else {
|
||||||
|
snprintf(log_buff, sizeof(log_buff), "%s/log_newtimelineC%d.csv", command_line_args_get_output_dir(), thread_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp_log;
|
||||||
|
if ((fp_log = fopen(log_buff, "w")) == NULL) {
|
||||||
|
message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp_log,"jobID,startTime,stopTime\n");
|
||||||
|
|
||||||
|
time_scale = 1.0 / exec_get_time_tic_value();
|
||||||
|
tl = timeline[thread_num];
|
||||||
|
for ( ii = 0 ; ii < tl_count[thread_num] ; ii++ ) {
|
||||||
|
start = tl[ii].start * time_scale;
|
||||||
|
stop = tl[ii].stop * time_scale;
|
||||||
|
fprintf(fp_log,"%5.2f, %f, %f\n", tl[ii].id, start, stop);
|
||||||
|
}
|
||||||
|
fflush(fp_log);
|
||||||
|
fclose(fp_log);
|
||||||
|
}
|
||||||
|
|
||||||
/** @li Manually create the log_timeline and log_timeline_init files from saved timeline data. */
|
/** @li Manually create the log_timeline and log_timeline_init files from saved timeline data. */
|
||||||
if (fp_time_main == NULL) {
|
if (fp_time_main == NULL) {
|
||||||
|
|
||||||
|
|
||||||
snprintf(log_buff, sizeof(log_buff), "%s/log_timeline.csv", command_line_args_get_output_dir());
|
snprintf(log_buff, sizeof(log_buff), "%s/log_timeline.csv", command_line_args_get_output_dir());
|
||||||
if ((fp_time_main = fopen(log_buff, "w")) == NULL) {
|
if ((fp_time_main = fopen(log_buff, "w")) == NULL) {
|
||||||
message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ;
|
message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ;
|
||||||
@ -592,11 +628,14 @@ int Trick::FrameLog::shutdown() {
|
|||||||
}
|
}
|
||||||
fprintf(fp_time_main, "trick_frame_log.frame_log.job_time {s},");
|
fprintf(fp_time_main, "trick_frame_log.frame_log.job_time {s},");
|
||||||
fprintf(fp_time_main, "trick_frame_log.frame_log.job_trick_id {--},frame_log.frame_log.job_user_id {--}");
|
fprintf(fp_time_main, "trick_frame_log.frame_log.job_trick_id {--},frame_log.frame_log.job_user_id {--}");
|
||||||
|
|
||||||
for (jj=1; jj<num_threads; jj++) {
|
for (jj=1; jj<num_threads; jj++) {
|
||||||
fprintf(fp_time_main, ",trick_frame_log.frame_log.job_userC%d_id {--}",jj);
|
fprintf(fp_time_main, ",trick_frame_log.frame_log.job_userC%d_id {--}",jj);
|
||||||
}
|
}
|
||||||
fprintf(fp_time_main, "\n");
|
fprintf(fp_time_main, "\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
snprintf(log_buff, sizeof(log_buff), "%s/log_timeline_init.csv", command_line_args_get_output_dir());
|
snprintf(log_buff, sizeof(log_buff), "%s/log_timeline_init.csv", command_line_args_get_output_dir());
|
||||||
if ((fp_time_other = fopen(log_buff, "w")) == NULL) {
|
if ((fp_time_other = fopen(log_buff, "w")) == NULL) {
|
||||||
message_publish(MSG_ERROR, "Could not open log_timeline_init.csv file for Job Timeline Logging\n") ;
|
message_publish(MSG_ERROR, "Could not open log_timeline_init.csv file for Job Timeline Logging\n") ;
|
||||||
@ -604,6 +643,9 @@ int Trick::FrameLog::shutdown() {
|
|||||||
}
|
}
|
||||||
fprintf(fp_time_other, "trick_frame_log.frame_log.job_init_time {s},");
|
fprintf(fp_time_other, "trick_frame_log.frame_log.job_init_time {s},");
|
||||||
fprintf(fp_time_other, "trick_frame_log.frame_log.job_trickinit_id {--},trick_frame_log.frame_log.job_userinit_id {--}\n");
|
fprintf(fp_time_other, "trick_frame_log.frame_log.job_trickinit_id {--},trick_frame_log.frame_log.job_userinit_id {--}\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
time_scale = 1.0 / exec_get_time_tic_value();
|
time_scale = 1.0 / exec_get_time_tic_value();
|
||||||
@ -615,17 +657,20 @@ int Trick::FrameLog::shutdown() {
|
|||||||
// stop job time, 0, 0
|
// stop job time, 0, 0
|
||||||
/** @li print a 0 id before each start time & after each stop time for a stairstep effect in plot. */
|
/** @li print a 0 id before each start time & after each stop time for a stairstep effect in plot. */
|
||||||
// cyclic jobs
|
// cyclic jobs
|
||||||
|
|
||||||
for ( thread = 0 ; thread < num_threads ; thread++ ) {
|
for ( thread = 0 ; thread < num_threads ; thread++ ) {
|
||||||
tl = timeline[thread];
|
tl = timeline[thread];
|
||||||
for ( ii = 0 ; ii < tl_count[thread] ; ii++ ) {
|
for ( ii = 0 ; ii < tl_count[thread] ; ii++ ) {
|
||||||
// start & stop time are in tics, so convert to seconds
|
// start & stop time are in tics, so convert to seconds
|
||||||
start = tl[ii].start * time_scale;
|
start = tl[ii].start * time_scale;
|
||||||
stop = tl[ii].stop * time_scale;
|
stop = tl[ii].stop * time_scale;
|
||||||
|
|
||||||
fprintf(fp_time_main, "%f,0", start); // start stairstep
|
fprintf(fp_time_main, "%f,0", start); // start stairstep
|
||||||
for (jj=0; jj<num_threads; jj++) {
|
for (jj=0; jj<num_threads; jj++) {
|
||||||
fprintf(fp_time_main, ",0");
|
fprintf(fp_time_main, ",0");
|
||||||
}
|
}
|
||||||
fprintf(fp_time_main, "\n");
|
fprintf(fp_time_main, "\n");
|
||||||
|
|
||||||
if (tl[ii].trick_job) {
|
if (tl[ii].trick_job) {
|
||||||
fprintf(fp_time_main, "%f,%f", start, tl[ii].id); // trick job start
|
fprintf(fp_time_main, "%f,%f", start, tl[ii].id); // trick job start
|
||||||
for (jj=0; jj<num_threads; jj++) {
|
for (jj=0; jj<num_threads; jj++) {
|
||||||
@ -714,11 +759,6 @@ int Trick::FrameLog::create_DP_files() {
|
|||||||
int Trick::FrameLog::create_DP_Product_dir() {
|
int Trick::FrameLog::create_DP_Product_dir() {
|
||||||
int ret=0;
|
int ret=0;
|
||||||
DP_dir = "DP_Product";
|
DP_dir = "DP_Product";
|
||||||
if (std::string(command_line_args_get_user_output_dir()) != std::string(command_line_args_get_output_dir())) {
|
|
||||||
if (!std::string(command_line_args_get_user_output_dir()).empty()) {
|
|
||||||
DP_dir = std::string(command_line_args_get_user_output_dir()) + "/DP_Product";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ret = mkdir(DP_dir.c_str(), 0777);
|
ret = mkdir(DP_dir.c_str(), 0777);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EEXIST) {
|
if (errno == EEXIST) {
|
||||||
|
Reference in New Issue
Block a user