package org.jactr.extensions.search.performance; /* * default logging */ import java.util.Collection; import java.util.Set; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.math.stat.descriptive.StatisticalSummary; import org.jactr.core.extensions.IExtension; import org.jactr.core.model.IModel; import org.jactr.core.module.declarative.IDeclarativeModule; import org.jactr.core.module.declarative.basic.DefaultDeclarativeModule; import org.jactr.core.module.declarative.search.ISearchSystem; import org.jactr.core.module.declarative.search.local.DefaultSearchSystem; import org.jactr.core.module.declarative.search.local.ExactParallelSearchDelegate; import org.jactr.core.module.declarative.search.local.ExactSingleThreadedSearchDelegate; import org.jactr.core.module.declarative.search.local.PartialParallelSearchDelegate; import org.jactr.core.module.declarative.search.local.PartialSingleThreadedSearchDelegate; import org.jactr.core.utils.parameter.BooleanParameterProcessor; import org.jactr.core.utils.parameter.ParameterHelper; /** * turns on profiling of local search. Can also enable parallel searches via * EnableParallelSearch=true. However, the overhead cost is generally too * expensive for most models. Install this extension, run it and get a sense of * the average runtimes, turn on parallel to see if you get any improvements. * * @author harrison */ public class DefaultSearchSystemOptimizer implements IExtension { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(DefaultSearchSystemOptimizer.class); private IModel _model; private DefaultSearchSystem _searchSystem; private ParameterHelper _parameters = new ParameterHelper(); private boolean _enableParallel = false; public DefaultSearchSystemOptimizer() { _parameters.addProcessor(new BooleanParameterProcessor( "EnableParallelSearch", this::setParallelEnabled, this::isParallelEnabled)); } public boolean isParallelEnabled() { return _enableParallel; } public void setParallelEnabled(boolean parallel) { _enableParallel = parallel; } @Override public void setParameter(String key, String value) { _parameters.setParameter(key, value); } @Override public String getParameter(String key) { return _parameters.getParameter(key); } @Override public Collection<String> getPossibleParameters() { Set<String> rtn = new TreeSet<String>(); _parameters.getParameterNames(rtn); return rtn; } @Override public Collection<String> getSetableParameters() { return getPossibleParameters(); } @Override public void initialize() throws Exception { if (_searchSystem != null) { // install the profiler _searchSystem.setExactDelegate(new ProfiledSearchDelegate( _enableParallel ? new ExactParallelSearchDelegate() : new ExactSingleThreadedSearchDelegate())); _searchSystem.setPartialDelegate(new ProfiledSearchDelegate( _enableParallel ? new PartialParallelSearchDelegate() : new PartialSingleThreadedSearchDelegate())); } } @Override public void install(IModel model) { _model = model; IDeclarativeModule decM = _model.getDeclarativeModule(); DefaultDeclarativeModule ddm = decM .getAdapter(DefaultDeclarativeModule.class); if (ddm == null) LOGGER.warn(String.format( "Could not install %s properly. No %s installed.", this.getClass() .getSimpleName(), DefaultDeclarativeModule.class.getName())); else { ISearchSystem sm = ddm.getSearchSystem(); if (sm instanceof DefaultSearchSystem) _searchSystem = (DefaultSearchSystem) sm; else LOGGER .warn(String .format( "Could not hook into DefaultSearchSystem, unknown search system %s", sm)); } } @Override public void uninstall(IModel model) { if (_searchSystem != null) { System.out.println("Search Performance Statistics"); System.out.println(getStats( (ProfiledSearchDelegate) _searchSystem.getExactDelegate(), "Exact")); System.out.println(getStats( (ProfiledSearchDelegate) _searchSystem.getPartialDelegate(), "Partial")); } } private String getStats(ProfiledSearchDelegate delegate, String type) { StatisticalSummary stats = delegate.getSummary(); StatisticalSummary slide = delegate.getSlidingSummary(); return String .format( "%s Search: Total : %.4f (%.4f) [%.4f - %.4f] ms. Last1000 : %.4f (%.4f) [%.4f - %.4f] ms.", type, stats.getMean(), stats.getStandardDeviation(), stats.getMin(), stats.getMax(), slide.getMean(), slide.getStandardDeviation(), slide.getMin(), slide.getMax()); } @Override public IModel getModel() { return _model; } @Override public String getName() { return "searchOptimizer"; } }