package org.jactr.tools.stat;
/*
* default logging
*/
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.concurrent.ExecutorServices;
import org.jactr.core.model.IModel;
import org.jactr.core.model.event.ModelEvent;
import org.jactr.core.model.event.ModelListenerAdaptor;
import org.jactr.core.runtime.ACTRRuntime;
import org.jactr.core.utils.parameter.IParameterized;
import org.jactr.instrument.IInstrument;
/**
* stat tracker that records the number of chunks, types and productions, as
* well as running time (simulated and actual). The tracker samples at a
* configurable rate of cycle firings.
*
* @author harrison
*/
public class StatTracker implements IInstrument, IParameterized
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(StatTracker.class);
static public final String CYCLES_PARAM = "SampleFrequency";
private long _cycleCount;
private long _cycleSamples = 100;
private Map<IModel, StatTrackingListener> _listeners;
public StatTracker()
{
_listeners = new HashMap<IModel, StatTrackingListener>();
}
public void initialize()
{
// TODO Auto-generated method stub
}
public void install(IModel model)
{
try
{
PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(
new File(ACTRRuntime.getRuntime().getWorkingDirectory(), model
.getName()
+ "-stats.txt"))));
StatTrackingListener listener = this.new StatTrackingListener(output);
model.addListener(listener, ExecutorServices
.getExecutor(ExecutorServices.BACKGROUND));
_listeners.put(model, listener);
}
catch (Exception e)
{
}
}
public void uninstall(IModel model)
{
model.removeListener(_listeners.get(model));
}
public String getParameter(String key)
{
return null;
}
public Collection<String> getPossibleParameters()
{
return getSetableParameters();
}
public Collection<String> getSetableParameters()
{
return Arrays.asList(CYCLES_PARAM);
}
public void setParameter(String key, String value)
{
if(CYCLES_PARAM.equalsIgnoreCase(key))
_cycleSamples = Integer.parseInt(value);
}
private class StatTrackingListener extends ModelListenerAdaptor
{
private PrintWriter _outputStream;
private double _simCycleStartTime = 0;
private long _realCycleStartTime = 0;
public StatTrackingListener(PrintWriter outputStream)
{
_outputStream = outputStream;
}
private void updateTimes(ModelEvent me)
{
double realRunTime = (me.getSystemTime() - _realCycleStartTime) / 1000.0;
double simRunTime = me.getSimulationTime() - _simCycleStartTime;
_realCycleStartTime = me.getSystemTime();
_simCycleStartTime = me.getSimulationTime();
output(me.getSource(), _cycleCount, realRunTime, simRunTime);
}
public void cycleStarted(ModelEvent me)
{
if (_cycleCount % _cycleSamples == 0) updateTimes(me);
_cycleCount++;
}
public void modelStopped(ModelEvent me)
{
updateTimes(me);
_outputStream.flush();
}
public void modelStarted(ModelEvent me)
{
_outputStream.println("Cycle\tChunks\tTypes\tProductions\tRealT\tSimT");
_realCycleStartTime = System.currentTimeMillis();
}
protected void output(IModel model, long cycle, double realTime,
double simTime)
{
try
{
long chunks = model.getDeclarativeModule().getNumberOfChunks();
long chunkTypes = model.getDeclarativeModule().getChunkTypes().get()
.size();
long productions = model.getProceduralModule().getProductions().get()
.size();
_outputStream.println(cycle + "\t" + chunks + "\t" + chunkTypes + "\t"
+ productions + "\t" + realTime + "\t" + simTime);
}
catch (Exception e)
{
/**
* Error : error
*/
LOGGER.error("could not output stats ", e);
}
}
}
}