Package edu.brown.hstore.estimators.markov

Source Code of edu.brown.hstore.estimators.markov.TestMarkovEstimator

package edu.brown.hstore.estimators.markov;

import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

import org.junit.Test;
import org.voltdb.VoltProcedure;
import org.voltdb.benchmark.tpcc.procedures.neworder;
import org.voltdb.catalog.*;
import org.voltdb.types.ExpressionType;

import edu.brown.BaseTestCase;
import edu.brown.catalog.CatalogUtil;
import edu.brown.hstore.HStoreConstants;
import edu.brown.hstore.conf.HStoreConf;
import edu.brown.hstore.estimators.Estimate;
import edu.brown.hstore.estimators.markov.MarkovEstimate;
import edu.brown.hstore.estimators.markov.MarkovEstimator;
import edu.brown.hstore.estimators.markov.MarkovEstimatorState;
import edu.brown.markov.EstimationThresholds;
import edu.brown.markov.MarkovGraph;
import edu.brown.markov.MarkovUtil.StatementWrapper;
import edu.brown.markov.MarkovVertex;
import edu.brown.markov.containers.MarkovGraphsContainerUtil;
import edu.brown.markov.containers.MarkovGraphsContainer;
import edu.brown.utils.*;
import edu.brown.workload.QueryTrace;
import edu.brown.workload.Workload;
import edu.brown.workload.TransactionTrace;
import edu.brown.workload.filters.BasePartitionTxnFilter;
import edu.brown.workload.filters.Filter;
import edu.brown.workload.filters.NoAbortFilter;
import edu.brown.workload.filters.ProcParameterArraySizeFilter;
import edu.brown.workload.filters.ProcParameterValueFilter;
import edu.brown.workload.filters.ProcedureLimitFilter;
import edu.brown.workload.filters.ProcedureNameFilter;

/**
*
* @author pavlo
*
*/
public class TestMarkovEstimator extends BaseTestCase {

    public static final Random rand = new Random();
   
    private static final int WORKLOAD_XACT_LIMIT = 50;
    private static final int BASE_PARTITION = 1;
    private static final int NUM_PARTITIONS = 5;
    private static final Class<? extends VoltProcedure> TARGET_PROCEDURE = neworder.class;
    private static AtomicLong XACT_ID = new AtomicLong(1000);

    private static Workload workload;
    private static MarkovGraphsContainer markovs;
    private static TransactionTrace singlep_trace;
    private static TransactionTrace multip_trace;
    private static final List<MarkovVertex> multip_path = new ArrayList<MarkovVertex>();
   
    private MarkovEstimator t_estimator;
    private EstimationThresholds thresholds;
    private Procedure catalog_proc;
   
    @Override
    protected void setUp() throws Exception {
        super.setUp(ProjectType.TPCC);
        this.addPartitions(NUM_PARTITIONS);
       
        HStoreConf hstore_conf = HStoreConf.singleton();
        hstore_conf.site.markov_path_caching = false;
        hstore_conf.site.markov_fast_path = false;
        hstore_conf.site.markov_force_traversal = true;
        hstore_conf.site.markov_learning_enable = false;
       
        this.catalog_proc = this.getProcedure(TARGET_PROCEDURE);
       
        if (isFirstSetup()) {
            Filter filter = new ProcedureNameFilter(false)
                    .include(TARGET_PROCEDURE.getSimpleName())
                    .attach(new NoAbortFilter())
                    .attach(new ProcParameterValueFilter().include(1, new Integer(5))) // D_ID
                    .attach(new ProcParameterArraySizeFilter(CatalogUtil.getArrayProcParameters(catalog_proc).get(0), 10, ExpressionType.COMPARE_EQUAL))
                    .attach(new BasePartitionTxnFilter(p_estimator, BASE_PARTITION))
                    .attach(new ProcedureLimitFilter(WORKLOAD_XACT_LIMIT));

            File file = this.getWorkloadFile(ProjectType.TPCC);
            workload = new Workload(catalogContext.catalog);
            ((Workload) workload).load(file, catalogContext.database, filter);
            assert(workload.getTransactionCount() > 0);
           
            // Generate MarkovGraphs
            markovs = MarkovGraphsContainerUtil.createBasePartitionMarkovGraphsContainer(catalogContext, workload, p_estimator);
            assertNotNull(markovs);
           
            // Find a single-partition and multi-partition trace
            PartitionSet multip_partitions = new PartitionSet();
            multip_partitions.add(BASE_PARTITION);
            for (TransactionTrace xact : workload.getTransactions()) {
                Object ol_supply_w_ids[] = (Object[])xact.getParam(5);
                assert(ol_supply_w_ids != null);
                boolean same_partition = true;
                for (Object i : ol_supply_w_ids) {
                    Integer partition = p_estimator.getHasher().hash(Integer.valueOf(i.toString()));
                    same_partition = same_partition && (partition == BASE_PARTITION);
                    if (same_partition == false && multip_trace == null) {
                        multip_partitions.add(partition);
                    }
                } // FOR
                if (same_partition && singlep_trace == null) singlep_trace = xact;
                if (same_partition == false && multip_trace == null) {
                    multip_trace = xact;
                    multip_path.addAll(markovs.get(BASE_PARTITION, this.catalog_proc).processTransaction(xact, p_estimator));
                }
                if (singlep_trace != null && multip_trace != null) break;
            } // FOR
            assert(multip_partitions.size() > 1);
        }
        assertNotNull(multip_trace);
        assertFalse(multip_path.isEmpty());
        assertNotNull(singlep_trace);
       
        // Setup
        this.t_estimator = new MarkovEstimator(catalogContext, p_estimator, markovs);
        this.thresholds = new EstimationThresholds();
    }

    /**
     * testUnknownPath
     */
    @Test
    public void testUnknownPath() throws Exception {
        // This is to test our ability to handle a transaction with
        // a path that we haven't seen before.
       
        // Find the S_W_ID that's different than the base partition, and change
        // all of the elements in the array to that value.
        TransactionTrace txn_trace = (TransactionTrace)multip_trace.clone();
        int w_id = (Integer)txn_trace.getParam(0);
        Short s_w_ids[] = (Short[])txn_trace.getParam(5);
        short remote_w_id = -1;
        assert(s_w_ids.length > 0);
        for (int i = 0; i < s_w_ids.length; i++) {
            if (w_id != s_w_ids[i]) {
                remote_w_id = s_w_ids[i];
                break;
            }
        } // FOR
        assert(remote_w_id >= 0);
        assertNotSame(w_id, remote_w_id);
        Arrays.fill(s_w_ids, remote_w_id);
//        System.err.println("S_W_ID: " + Arrays.toString(s_w_ids));
        txn_trace.setParam(5, s_w_ids);
       
        MarkovEstimatorState state = t_estimator.startTransaction(XACT_ID.getAndIncrement(),
                                                                  this.catalog_proc,
                                                                  txn_trace.getParams());
        assertNotNull(state);
           
        // Even though it won't correctly identify the exact path that we're going to
        // take (i.e., what partitions the getStockInfo queries will need), the path
        // should be complete (i.e., we should see each Statement in NewOrder executed
        // at least once)
        MarkovEstimate initialEst = state.getInitialEstimate();
//        System.err.println("FIRST ESTIMATE:\n" + initialEst);
        List<MarkovVertex> initialPath = initialEst.getMarkovPath();
        assertFalse(initialPath.isEmpty());
        Set<Statement> seenStmts = new HashSet<Statement>();
        for (MarkovVertex v : initialPath) {
            Statement stmt = v.getCatalogItem();
            if ((stmt instanceof StatementWrapper) == false) {
                seenStmts.add(stmt);
            }
        } // FOR
        Procedure proc = txn_trace.getCatalogItem(catalogContext.database);
        for (Statement stmt : proc.getStatements()) {
            assertTrue(stmt.fullName(), seenStmts.contains(stmt));
        }
//        System.err.println(proc + "\n" + StringUtil.join("\n", proc.getStatements()));
//        System.err.println("=======================================");
//        System.err.println("SEEN\n" + StringUtil.join("\n", seenStmts));
        assertEquals(proc.getStatements().size(), seenStmts.size());
    }
   
    /**
     * testMultipleStartTransaction
     */
    @Test
    public void testMultipleStartTransaction() throws Exception {
        Set<MarkovEstimatorState> all_states = new HashSet<MarkovEstimatorState>();
        int expected = 20;
        MarkovEstimate initialEst = null;
        for (int i = 0; i < expected; i++) {
            MarkovEstimatorState state = t_estimator.startTransaction(XACT_ID.getAndIncrement(),
                                                                      this.catalog_proc,
                                                                      multip_trace.getParams());
            assertNotNull(state);
            assertFalse(all_states.contains(state));
            all_states.add(state);
           
            if (initialEst == null) {
                initialEst = state.getInitialEstimate();
                // System.err.println("FIRST ESTIMATE:\n" + initialEst);
            } else {
                MarkovEstimate est = state.getInitialEstimate();
                // System.err.printf("ESTIMATE #%02d:\n%s", i, est);
                assertEquals(initialEst.getTouchedPartitions(thresholds), est.getTouchedPartitions(thresholds));
            }
           
        } // FOR
        assertEquals(expected, all_states.size());
    }
   
    /**
     * testStartTransaction
     */
    @Test
    public void testStartTransaction() throws Exception {
        long txn_id = XACT_ID.getAndIncrement();
        MarkovEstimatorState state = t_estimator.startTransaction(txn_id, this.catalog_proc, singlep_trace.getParams());
        assertNotNull(state);
        assertNotNull(state.getLastEstimate());
       
        MarkovEstimate est = state.getInitialEstimate();
        System.err.println(est);
        assertNotNull(est);
        assertTrue(est.toString(), est.isInitialized());
//        assertTrue(est.toString(), est.isSinglePartitionProbabilitySet());
        assertTrue(est.toString(), est.isAbortProbabilitySet());
        assertTrue(est.toString(), est.isConfidenceCoefficientSet());
        // assertTrue(est.toString(), est.getConfidenceCoefficient() >= 0f);
//        assertEquals(est.toString(), 1.0f, est.getSinglePartitionProbability());
        assertEquals(est.toString(), 1.0f, est.getConfidenceCoefficient());

        //        System.err.println(est.toString());
       
        MarkovGraph markov = state.getMarkovGraph();
        List<MarkovVertex> initial_path = est.getMarkovPath();
        assertNotNull(initial_path);
        assertFalse(initial_path.isEmpty());
       
        System.err.println("# of Vertices: " + markov.getVertexCount());
        System.err.println("# of Edges:    " + markov.getEdgeCount());
        System.err.println("Confidence:    " + String.format("%.4f", est.getConfidenceCoefficient()));
        System.err.println("\nINITIAL PATH:\n" + StringUtil.join("\n", initial_path));
//        System.err.println(multip_trace.debug(catalog_db));

        PartitionSet partitions = new PartitionSet();
        p_estimator.getAllPartitions(partitions, singlep_trace);
        assertNotNull(partitions);
//        assert(partitions.size() > 1) : partitions;
        System.err.println("partitions: " + partitions);
       
//        GraphvizExport<Vertex, Edge> gv = MarkovUtil.exportGraphviz(markov, false, null);
//        gv.highlightPath(markov.getPath(initial_path), "blue");
//        gv.writeToTempFile(this.catalog_proc, 0);
//
//        MarkovUtil.exportGraphviz(markov, false, markov.getPath(multip_path)).writeToTempFile(this.catalog_proc, 1);
       
        Collection<Integer> est_partitions = est.getTouchedPartitions(thresholds);
        assertNotNull(est_partitions);
        assertEquals(partitions.size(), est_partitions.size());
        assertEquals(partitions, est_partitions);
       
        assert(est.isSinglePartitioned(this.thresholds));
        assertTrue(est.isAbortable(this.thresholds));
       
        for (int partition : catalogContext.getAllPartitionIds()) {
            if (partitions.contains(partition)) { //  == BASE_PARTITION) {
                assertFalse("isFinishedPartition(" + partition + ")", est.isDonePartition(thresholds, partition));
                assertTrue("isWritePartition(" + partition + ")", est.isWritePartition(thresholds, partition));
                assertTrue("isTargetPartition(" + partition + ")", est.isTargetPartition(thresholds, partition));
            } else {
                assertTrue("isFinishedPartition(" + partition + ")", est.isDonePartition(thresholds, partition));
                assertFalse("isWritePartition(" + partition + ")", est.isWritePartition(thresholds, partition));
                assertFalse("isTargetPartition(" + partition + ")", est.isTargetPartition(thresholds, partition));
            }
        } // FOR
    }
   
    /**
     * testStartTransactionDtxn
     */
    @Test
    public void testStartTransactionDtxn() throws Exception {
        TransactionTrace txn_trace = multip_trace;
        long txn_id = XACT_ID.getAndIncrement();
        MarkovEstimatorState state = t_estimator.startTransaction(txn_id, this.catalog_proc, txn_trace.getParams());
        assertNotNull(state);
        assertNotNull(state.getLastEstimate());
       
        MarkovEstimate initialEst = state.getInitialEstimate();
        assertNotNull(initialEst);
        assertTrue(initialEst.toString(), initialEst.isInitialized());
//        assertTrue(initialEst.toString(), initialEst.isSinglePartitionProbabilitySet());
        assertTrue(initialEst.toString(), initialEst.isAbortProbabilitySet());
//        assertTrue(initialEst.toString(), initialEst.getSinglePartitionProbability() < 1.0f);
        assertTrue(initialEst.toString(), initialEst.isConfidenceCoefficientSet());
        assertTrue(initialEst.toString(), initialEst.getConfidenceCoefficient() >= 0f);
        assertTrue(initialEst.toString(), initialEst.getConfidenceCoefficient() <= 1f);
        assertFalse(initialEst.toString(), initialEst.isSinglePartitioned(this.thresholds));
        assertTrue(initialEst.toString(), initialEst.isAbortable(this.thresholds));
       
        MarkovGraph markov = state.getMarkovGraph();
        List<MarkovVertex> initial_path = initialEst.getMarkovPath();
        assertNotNull(initial_path);
        assertFalse(initial_path.isEmpty());
       
        System.err.println("# of Vertices: " + markov.getVertexCount());
        System.err.println("# of Edges:    " + markov.getEdgeCount());
        System.err.println("Confidence:    " + String.format("%.4f", initialEst.getConfidenceCoefficient()));
        System.err.println("\nINITIAL PATH:\n" + StringUtil.join("\n", initial_path));

        PartitionSet partitions = new PartitionSet();
        p_estimator.getAllPartitions(partitions, txn_trace);
        assertNotNull(partitions);
        assert(partitions.size() > 1) : partitions;
       
        Collection<Integer> est_partitions = initialEst.getTouchedPartitions(thresholds);
        assertNotNull(est_partitions);
        assertEquals(partitions.size(), est_partitions.size());
        assertEquals(partitions, est_partitions);
    }
   
    /**
     * testExecuteQueries
     */
    @Test
    public void testExecuteQueries() throws Exception {
        TransactionTrace txn_trace = multip_trace;
        long txn_id = XACT_ID.getAndIncrement();
        MarkovEstimatorState state = t_estimator.startTransaction(txn_id, this.catalog_proc, txn_trace.getParams());
        assertNotNull(state);
        assertNotNull(state.getLastEstimate());
       
        MarkovEstimate initialEst = state.getInitialEstimate();
        assertNotNull(initialEst);
        assertTrue(initialEst.toString(), initialEst.isInitialized());
//        assertTrue(initialEst.toString(), initialEst.isSinglePartitionProbabilitySet());
        assertTrue(initialEst.toString(), initialEst.isAbortProbabilitySet());
//        assertTrue(initialEst.toString(), initialEst.getSinglePartitionProbability() < 1.0f);
        assertTrue(initialEst.toString(), initialEst.isConfidenceCoefficientSet());
        assertTrue(initialEst.toString(), initialEst.getConfidenceCoefficient() >= 0f);
        assertTrue(initialEst.toString(), initialEst.getConfidenceCoefficient() <= 1f);

        // Get the list of partitions that we're going to touch in the beginning
        // We should never mark these as finished in subsequent estimates
        PartitionSet touched = initialEst.getTouchedPartitions(thresholds);
        assertFalse(touched.isEmpty());
        assertFalse(touched.contains(HStoreConstants.NULL_PARTITION_ID));
        System.err.println("TOUCHED: " + touched);
        assertFalse(touched.toString(), touched.size() == 1);
       
        // Execute a bunch of batches
        // All should say that the txn is not finished with the partitions until we
        // get to the one that contains the updateStock queries, which should be the last.
        Statement lastBatchStmt = this.getStatement(this.catalog_proc, "updateStock");
        for (int i = 0, cnt = txn_trace.getBatchCount(); i < cnt; i++) {
            List<QueryTrace> queries = txn_trace.getBatchQueries(i);
            assertFalse(queries.isEmpty());
            boolean is_last = (i+1 == cnt);
            Statement stmts[] = new Statement[queries.size()];
            PartitionSet partitions[] = new PartitionSet[queries.size()];
           
            boolean found = false;
            int idx = 0;
            for (QueryTrace q : queries) {
                stmts[idx] = q.getCatalogItem(catalogContext.database);
                assertNotNull(stmts[idx]);
                partitions[idx] = new PartitionSet();
                p_estimator.getAllPartitions(partitions[idx], q, state.getBasePartition());
                assertFalse(partitions[idx].isEmpty());
                assertFalse(partitions[idx].contains(HStoreConstants.NULL_PARTITION_ID));
               
                found = found || stmts[idx].equals(lastBatchStmt);
                idx++;
            } // FOR
            if (is_last) assertTrue(StringUtil.join("\n", queries), found);
               
            MarkovEstimate est = t_estimator.executeQueries(state, stmts, partitions);
            assertNotNull(est);
           
            for (int partition : catalogContext.getAllPartitionIds()) {
                String debug = String.format("Batch %02d / Partition %02d / isLast=%s\n%s",
                                             est.getBatchId(), partition, is_last, est.toString());
                assertTrue(debug, est.isDoneProbabilitySet(partition));
                assertTrue(debug, est.isWriteProbabilitySet(partition));
//                assertTrue(debug, est.isReadOnlyProbabilitySet(partition));
               
                if (touched.contains(partition) && is_last == false) { //  || partition == state.getBasePartition())) {
                    assertFalse(debug, est.isDonePartition(thresholds, partition));
                    assertTrue(debug, est.isWritePartition(thresholds, partition));
                } else {
                    assertTrue(debug, est.isDonePartition(thresholds, partition));
                }
            } // FOR
        } // FOR
    }
   
    /**
     * testFastPath
     */
    @Test
    public void testFastPath() throws Exception {
        TransactionTrace txn_trace = multip_trace;
        int base_partition = p_estimator.getBasePartition(txn_trace);
       
        List<QueryTrace> queries = txn_trace.getBatchQueries(1);
        assertFalse(queries.isEmpty());
        Statement stmts[] = new Statement[queries.size()];
        PartitionSet partitions[] = new PartitionSet[queries.size()];
        int idx = 0;
        for (QueryTrace q : queries) {
            stmts[idx] = q.getCatalogItem(catalogContext.database);
            assertNotNull(stmts[idx]);
            partitions[idx] = new PartitionSet();
            p_estimator.getAllPartitions(partitions[idx], q, base_partition);
            idx++;
        } // FOR
       
        MarkovEstimatorState states[] = new MarkovEstimatorState[2];
        MarkovEstimate ests[] = new MarkovEstimate[states.length];
        for (int i = 0; i < states.length; i++) {
            HStoreConf.singleton().site.markov_fast_path = (i != 0);
            states[i] = t_estimator.startTransaction(XACT_ID.getAndIncrement(), this.catalog_proc, txn_trace.getParams());
            assertNotNull(states[i]);
            assertNotNull(states[i].getLastEstimate());
            ests[i] = t_estimator.executeQueries(states[i], stmts, partitions);
            assertNotNull(ests[i]);
        } // FOR

        // Now compare that estimates look reasonable the same
        for (int i = 0; i < states.length; i++) {
            for (int ii = i+1; ii < states.length; ii++) {
                assertEquals(states[i].getBasePartition(), states[ii].getBasePartition());
                assertEquals(ests[i].getTouchedPartitions(thresholds), ests[ii].getTouchedPartitions(thresholds));
                assertEquals(ests[i].getBatchId(), ests[ii].getBatchId());
//                assertEquals(ests[i].getSinglePartitionProbability(), ests[ii].getSinglePartitionProbability());
                assertEquals(ests[i].getAbortProbability(), ests[ii].getAbortProbability());
               
                for (Integer partition : catalogContext.getAllPartitionIds()) {
                    String debug = String.format("Batch %02d / Partition %02d\n%s",
                                                 ests[i].getBatchId(), partition, ests[i].toString());
                   
                    assertEquals(debug, ests[i].getTouchedCounter(partition), ests[ii].getTouchedCounter(partition));
                    assertEquals(debug, ests[i].isDoneProbabilitySet(partition), ests[ii].isDoneProbabilitySet(partition));
                    assertEquals(debug, ests[i].isWriteProbabilitySet(partition), ests[ii].isWriteProbabilitySet(partition));
//                    assertEquals(debug, ests[i].isReadOnlyProbabilitySet(partition), ests[ii].isReadOnlyProbabilitySet(partition));
                    assertEquals(debug, ests[i].isDonePartition(thresholds, partition), ests[ii].isDonePartition(thresholds, partition));
                    assertEquals(debug, ests[i].isWritePartition(thresholds, partition), ests[ii].isWritePartition(thresholds, partition));
                    assertEquals(debug, ests[i].isReadOnlyPartition(thresholds, partition), ests[ii].isReadOnlyPartition(thresholds, partition));
                } // FOR
            } // FOR       
        }
    }
   
    /**
     * testProcessTransactionTrace
     */
    @Test
    public void testProcessTransactionTrace() throws Exception {
        TransactionTrace txn_trace = singlep_trace;
        assertNotNull(txn_trace);
        MarkovEstimatorState s = this.t_estimator.processTransactionTrace(txn_trace);
        assertNotNull(s);
       
        MarkovEstimate initialEst = s.getInitialEstimate();
        assertNotNull(initialEst);
        assertTrue(initialEst.toString(), initialEst.isInitialized());
//        assertTrue(initialEst.toString(), initialEst.isSinglePartitionProbabilitySet());
        assertTrue(initialEst.toString(), initialEst.isAbortProbabilitySet());
//        assertTrue(initialEst.toString(), initialEst.getSinglePartitionProbability() < 1.0f);
        assertTrue(initialEst.toString(), initialEst.isConfidenceCoefficientSet());
        assertTrue(initialEst.toString(), initialEst.getConfidenceCoefficient() >= 0f);
        assertTrue(initialEst.toString(), initialEst.getConfidenceCoefficient() <= 1f);
        assertTrue(initialEst.toString(), initialEst.getMarkovPath().isEmpty() == false);
       
        // We should have an MarkovEstimate for each batch
        assertEquals(txn_trace.getBatchCount(), s.getEstimateCount());
        List<Estimate> estimates = s.getEstimates();
        for (int i = 0, cnt = txn_trace.getBatchCount(); i < cnt; i++) {
            List<QueryTrace> queries = txn_trace.getBatchQueries(i);
            assertFalse(queries.isEmpty());
           
            MarkovEstimate est = (MarkovEstimate)estimates.get(i);
            assertNotSame(initialEst, est);
            assertNotNull(est);
//            assertTrue(est.toString(), est.isSinglePartitionProbabilitySet());
            assertTrue(est.toString(), est.isAbortProbabilitySet());
            assertTrue(est.toString(), est.isSinglePartitioned(thresholds));
            assertTrue(est.toString(), est.isConfidenceCoefficientSet());
            assertTrue(est.toString(), est.getConfidenceCoefficient() >= 0f);
            assertTrue(est.toString(), est.getConfidenceCoefficient() <= 1f);
            assertTrue(est.toString(), est.getMarkovPath().isEmpty() == false);
           
            // The last vertex in each MarkovEstimate should correspond to the last query in each batch
            MarkovVertex last_v = est.getVertex();
            assertNotNull(last_v);
            System.err.println("LAST VERTEX: " + last_v);
            assertEquals(CollectionUtil.last(queries).getCatalogItem(catalogContext.database), last_v.getCatalogItem());
        } // FOR
    }
}
TOP

Related Classes of edu.brown.hstore.estimators.markov.TestMarkovEstimator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.