/* $Id$ * * This file is a part of jPapaBench providing a Java implementation * of PapaBench project. * Copyright (C) 2010 Michal Malohlava <michal.malohlava_at_d3s.mff.cuni.cz> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ package papabench.jop.commons.tasks; import java.io.PrintStream; import com.jopdesign.sys.*; import joprt.*; /** * This is a version witha JOP RT periodic thread. * * It carries information about periodic invocation, but it does not do it. * * @author Michal Malohlava * */ public class PJPeriodicTask extends RtThread { public static final int INSTRUMENTATION_RUNS = 100; public static final int TOTAL_RUNS = 500; private Runnable taskHandler; private int priority; private int releaseMs; private int periodMs; private Memory scope; private String name; public PJPeriodicTask(Runnable taskHandler, int priority, int releaseMs, int periodMs, String name) { super(priority, periodMs*1000, releaseMs*1000); this.taskHandler = taskHandler; this.priority = priority; this.releaseMs = releaseMs; this.periodMs = periodMs; this.name = name; } public Memory getScope() { return scope; } public void setScope(int words) { scope = new Memory(words, words); } public void run() { if (Config.MEASURE) initInstrumentation(); int cnt = 0; int total_cnt = 0; for (;;) { if (Config.MEASURE) startMeasurement(); if (scope != null) { scope.enter(taskHandler); } else { taskHandler.run(); } if (Config.MEASURE) endMeasurement(); if (Config.MEASURE && ++cnt == INSTRUMENTATION_RUNS) { printInstrumentation(); cnt = 0; } if (++total_cnt == TOTAL_RUNS) { System.out.println("JVM exit!"); System.exit(0); } waitForNextPeriod(); } } public Runnable getTaskHandler() { return taskHandler; } public int getPriority() { return priority; } public int getReleaseMs() { return releaseMs; } public int getPeriodMs() { return periodMs; } private static class MeasurementStatistic { int minElapsed, maxElapsed, totalRuns; long totalElapsed; int minICacheCost, maxICacheCost; String name; Dumper dumper; Memory dumperScope; public MeasurementStatistic(String str) { minElapsed = Integer.MAX_VALUE; maxElapsed = Integer.MIN_VALUE; totalElapsed = 0; totalRuns = 0; minICacheCost = Integer.MAX_VALUE; maxICacheCost = Integer.MIN_VALUE; name = str; dumper = new Dumper(); dumperScope = new Memory(1024, 1024); } public void recordRun(int elapsed) { totalRuns++; totalElapsed += elapsed; if(minElapsed > elapsed) minElapsed = elapsed; if(maxElapsed < elapsed) maxElapsed = elapsed; } public void recordICacheCost(int cost) { if(minICacheCost > cost) minICacheCost = cost; if(maxICacheCost < cost) maxICacheCost = cost; } private class Dumper implements Runnable { PrintStream out; public void run() { out.print(name); out.print(":\t"); out.print("min:\t"); out.print(minElapsed); out.print("\tmax:\t"); out.print(maxElapsed); out.print("\ttotal:\t"); out.print(totalElapsed); out.print("/\t"); out.print(totalRuns); if(maxICacheCost > 0) { out.print("\ti$-min:\t"); out.print(minICacheCost); out.print("\ti$-max:\t"); out.print(maxICacheCost); } out.println(""); } } public void dump(PrintStream out) { dumper.out = out; dumperScope.enter(dumper); } public String toString() { return "min:\t"+minElapsed+"\tmax:\t"+maxElapsed +"\ttotal:\t"+totalElapsed+"/"+totalRuns; } } private static class EmptyRunnable implements Runnable { public void run() { }; } private MeasurementStatistic problemStats; private Runnable emptyRunnable; private void initInstrumentation() { /* initialize statistics */ problemStats = new MeasurementStatistic(name); /* create a dummy runnable */ emptyRunnable = new EmptyRunnable(); /* JOP Specific instrumentation */ startMeasurement(); if (scope != null) { scope.enter(emptyRunnable); } else { emptyRunnable.run(); } endMeasurement(); to = te-ts; System.out.print(name); System.out.print(" overhead for empty run(): "); System.out.println(to); /* initialize statistics again to get rid of overhead measurement artifacts */ problemStats = new MeasurementStatistic(name); } private void printInstrumentation() { problemStats.dump(System.out); } private int ts, te, to; public void startMeasurement() { Native.wrMem(0, Const.IO_INT_ENA); ts = Native.rdMem(Const.IO_CNT); } public void endMeasurement() { /* JOP Specific instrumentation */ te = Native.rdMem(Const.IO_CNT); problemStats.recordRun(te-ts-to); Native.wrMem(-1, Const.IO_INT_ENA); } }