package edu.brown.designer; import java.io.File; import java.util.Map.Entry; import org.apache.commons.collections15.map.ListOrderedMap; import org.apache.log4j.Logger; import edu.brown.costmodel.AbstractCostModel; import edu.brown.costmodel.LowerBoundsCostModel; import edu.brown.costmodel.SingleSitedCostModel; import edu.brown.costmodel.TimeIntervalCostModel; import edu.brown.designer.partitioners.MostPopularPartitioner; import edu.brown.designer.partitioners.plan.PartitionPlan; import edu.brown.profilers.ProfileMeasurement; import edu.brown.utils.ArgumentsParser; import edu.brown.workload.Workload; /** * @author pavlo */ public class LowerBoundsCalculator { private static final Logger LOG = Logger.getLogger(LowerBoundsCalculator.class); private final DesignerInfo info; private final TimeIntervalCostModel<? extends AbstractCostModel> costmodel; /** * Constructor * * @param info * @param hints * @param args */ public LowerBoundsCalculator(DesignerInfo info, int num_intervals) { this.info = info; this.costmodel = new TimeIntervalCostModel<LowerBoundsCostModel>(info.catalogContext, LowerBoundsCostModel.class, num_intervals); } /** * @param workload * @return * @throws Exception */ public double calculate(final Workload workload) throws Exception { if (LOG.isDebugEnabled()) LOG.debug("Calculating lower bounds using " + workload.getTransactionCount() + " transactions" + " on " + info.catalogContext.numberOfPartitions + " partitions"); return (this.costmodel.estimateWorkloadCost(this.info.catalogContext, workload)); } /** * @param args */ public static void main(String[] vargs) throws Exception { ArgumentsParser args = ArgumentsParser.load(vargs); args.require(ArgumentsParser.PARAM_CATALOG, ArgumentsParser.PARAM_WORKLOAD, ArgumentsParser.PARAM_STATS, ArgumentsParser.PARAM_MAPPINGS); // If given a PartitionPlan, then update the catalog if (args.hasParam(ArgumentsParser.PARAM_PARTITION_PLAN)) { File pplan_path = new File(args.getParam(ArgumentsParser.PARAM_PARTITION_PLAN)); if (pplan_path.exists()) { PartitionPlan pplan = new PartitionPlan(); pplan.load(pplan_path, args.catalog_db); pplan.apply(args.catalog_db); LOG.info("Applied PartitionPlan '" + pplan_path + "'"); } } // Create the container object that will hold all the information that // the designer will need to use DesignerInfo info = new DesignerInfo(args); // Upper Bounds Designer designer = new Designer(info, args.designer_hints, args); PartitionPlan initial_solution = new MostPopularPartitioner(designer, info).generate(args.designer_hints); initial_solution.apply(args.catalog_db); // Calculate the actual cost too while we're at it... TimeIntervalCostModel<SingleSitedCostModel> cm = new TimeIntervalCostModel<SingleSitedCostModel>(args.catalogContext, SingleSitedCostModel.class, args.num_intervals); cm.applyDesignerHints(args.designer_hints); double upper_bound = cm.estimateWorkloadCost(args.catalogContext, args.workload); final ProfileMeasurement timer = new ProfileMeasurement("timer").start(); LowerBoundsCalculator lb = new LowerBoundsCalculator(info, args.num_intervals); double lower_bound = lb.calculate(args.workload); timer.stop(); ListOrderedMap<String, Object> m = new ListOrderedMap<String, Object>(); m.put("# of Partitions", args.catalogContext.numberOfPartitions); m.put("# of Intervals", args.num_intervals); m.put("Lower Bound", String.format("%.03f", lower_bound)); m.put("Upper Bound", String.format("%.03f", upper_bound)); m.put("Search Time", String.format("%.2f sec", timer.getTotalThinkTimeSeconds())); for (Entry<String, Object> e : m.entrySet()) { LOG.info(String.format("%-20s%s", e.getKey() + ":", e.getValue().toString())); } // FOR } }