Skip to content
This repository has been archived by the owner on Aug 23, 2021. It is now read-only.

Commit

Permalink
Made several changes for use with TPC-H implementation and col-stores…
Browse files Browse the repository at this point in the history
… DBs:

- New benchmark states for cold and hot query runs.
- Can run queries serially (run each query in sequential order on one terminal)
  exactly once (a `latency' run) or for a set amount of time (looping through
  the query list until the timer expires).
- Added support for MonetDB in TPC-C.
- Can re-run a test using the .raw output. Submits identical queries to the
  system at the same time; for repeatability of tests.
- Can specify `groupings' of query weights in config file. A shorthand to
  make config management a little easier.
  • Loading branch information
Ben Reilly committed Dec 13, 2013
1 parent 7f8d589 commit e371037
Show file tree
Hide file tree
Showing 23 changed files with 1,185 additions and 232 deletions.
Binary file added lib/monetdb-jdbc-2.9.jar
Binary file not shown.
18 changes: 9 additions & 9 deletions run/sql/sqlTableTruncates
@@ -1,18 +1,18 @@


truncate table warehouse; delete warehouse;


truncate table item; delete item;


truncate table stock; delete stock;


truncate table district; delete district;


truncate table customer; delete customer;


truncate table history; delete history;


truncate table oorder; delete oorder;


truncate table order_line; delete order_line;


truncate table new_order; delete new_order;
20 changes: 20 additions & 0 deletions src/com/oltpbenchmark/BenchmarkState.java
Expand Up @@ -70,6 +70,26 @@ public void startMeasure() {
state = State.MEASURE; state = State.MEASURE;
} }


public void startColdQuery() {
assert state == State.MEASURE;
state = State.COLD_QUERY;
}

public void startHotQuery() {
assert state == State.COLD_QUERY;
state = State.MEASURE;
}

public void signalLatencyComplete() {
assert state == State.MEASURE;
state = State.LATENCY_COMPLETE;
}

public void ackLatencyComplete() {
assert state == State.LATENCY_COMPLETE;
state = State.MEASURE;
}

public void startCoolDown() { public void startCoolDown() {
assert state == State.MEASURE; assert state == State.MEASURE;
state = State.DONE; state = State.DONE;
Expand Down
245 changes: 184 additions & 61 deletions src/com/oltpbenchmark/DBWorkload.java

Large diffs are not rendered by default.

64 changes: 31 additions & 33 deletions src/com/oltpbenchmark/LatencyRecord.java
Expand Up @@ -24,17 +24,16 @@


/** Efficiently stores a record of (start time, latency) pairs. */ /** Efficiently stores a record of (start time, latency) pairs. */
public class LatencyRecord implements Iterable<LatencyRecord.Sample> { public class LatencyRecord implements Iterable<LatencyRecord.Sample> {
/** Allocate int[] arrays of this length (262144 = 1 MB). */ /** Allocate space for 500k samples at a time */
static final int BLOCK_SIZE = 262144; static final int ALLOC_SIZE = 500000;


/** /**
* Contains (start time, latency, transactionType, workerid, phaseid) pentiplets * Contains (start time, latency, transactionType, workerid, phaseid) pentiplets
* in microsecond form. The start times are "compressed" by encoding them as * in microsecond form. The start times are "compressed" by encoding them as
* increments, starting from startNs. A 32-bit integer provides sufficient resolution * increments, starting from startNs. A 32-bit integer provides sufficient resolution
* for an interval of 2146 seconds, or 35 minutes. * for an interval of 2146 seconds, or 35 minutes.
*/ */
// TODO: Use a real variable length encoding? private final ArrayList<Sample[]> values = new ArrayList<Sample[]>();
private final ArrayList<long[]> values = new ArrayList<long[]>();
private int nextIndex; private int nextIndex;


private final long startNs; private final long startNs;
Expand All @@ -49,57 +48,54 @@ public LatencyRecord(long startNs) {


} }


public void addLatency(int transType, long startNs, long endNs, int workerId, int phaseId) { public void addLatency(int transType, long startNs, long endNs, int workerId, int phaseId) {
assert lastNs > 0; assert lastNs > 0;
assert lastNs - 500 <= startNs; assert lastNs - 500 <= startNs;
assert endNs >= startNs; assert endNs >= startNs;


if (nextIndex >= BLOCK_SIZE - 5) { // barzan: I changed this! if (nextIndex == ALLOC_SIZE) {
allocateChunk(); allocateChunk();
} }
long[] chunk = values.get(values.size() - 1); Sample[] chunk = values.get(values.size() - 1);


long startOffsetUs = ((startNs - lastNs + 500) / 1000); long startOffsetNs = (startNs - lastNs + 500);
assert startOffsetUs >= 0; assert startOffsetNs >= 0;
int latencyUs = (int) ((endNs - startNs + 500) / 1000); int latencyUs = (int) ((endNs - startNs + 500) / 1000);
assert latencyUs >= 0; assert latencyUs >= 0;


chunk[nextIndex] = transType; chunk[nextIndex] = new Sample(transType, startOffsetNs, latencyUs
chunk[nextIndex + 1] = startOffsetUs; , workerId, phaseId);
chunk[nextIndex + 2] = latencyUs; ++nextIndex;
chunk[nextIndex + 3] = workerId;
chunk[nextIndex + 4] = phaseId;
nextIndex += 5;


lastNs += startOffsetUs * 1000L; lastNs += startOffsetNs;
} }


private void allocateChunk() { private void allocateChunk() {
assert (values.isEmpty() && nextIndex == 0) assert (values.isEmpty() && nextIndex == 0)
|| nextIndex >= BLOCK_SIZE - 5; || nextIndex == ALLOC_SIZE;
values.add(new long[BLOCK_SIZE]); values.add(new Sample[ALLOC_SIZE]);
nextIndex = 0; nextIndex = 0;
} }


/** Returns the number of recorded samples. */ /** Returns the number of recorded samples. */
public int size() { public int size() {
// Samples stored in full chunks // Samples stored in full chunks
int samples = (values.size() - 1) * (BLOCK_SIZE / 5); int samples = (values.size() - 1) * ALLOC_SIZE;


// Samples stored in the last not full chunk // Samples stored in the last not full chunk
samples += nextIndex / 5; samples += nextIndex;
return samples; return samples;
} }


/** Stores the start time and latency for a single sample. Immutable. */ /** Stores the start time and latency for a single sample. Immutable. */
public static final class Sample implements Comparable<Sample> { public static final class Sample implements Comparable<Sample> {
public final int tranType; public final int tranType;
public final long startNs; public long startNs;
public final int latencyUs; public final int latencyUs;
public final int workerId; public final int workerId;
public final int phaseId; public final int phaseId;


public Sample(int tranType, long startNs, int latencyUs, int workerId, int phaseId) { public Sample(int tranType, long startNs, int latencyUs, int workerId, int phaseId) {
this.tranType = tranType; this.tranType = tranType;
this.startNs = startNs; this.startNs = startNs;
this.latencyUs = latencyUs; this.latencyUs = latencyUs;
Expand Down Expand Up @@ -145,21 +141,23 @@ public boolean hasNext() {


@Override @Override
public Sample next() { public Sample next() {
long[] chunk = values.get(chunkIndex); Sample[] chunk = values.get(chunkIndex);
int tranType = (int) chunk[subIndex]; Sample s = chunk[subIndex];
long offsetUs = chunk[subIndex + 1];
int latencyUs = (int) chunk[subIndex + 2]; // Iterate in chunk, and wrap to next one
int workerId = (int) chunk[subIndex + 3]; ++subIndex;
int phaseId = (int) chunk[subIndex + 4]; assert subIndex <= ALLOC_SIZE;
subIndex += 5; if (subIndex == ALLOC_SIZE) {
if (subIndex >= BLOCK_SIZE - 5) {
chunkIndex += 1; chunkIndex += 1;
subIndex = 0; subIndex = 0;
} }


long startNs = lastIteratorNs + offsetUs * 1000L; // Previously, s.startNs was just an offset from the previous
lastIteratorNs = startNs; // value. Now we make it an absolute.
return new Sample(tranType, startNs, latencyUs, workerId, phaseId); s.startNs += lastIteratorNs;
lastIteratorNs = s.startNs;

return s;
} }


@Override @Override
Expand Down
74 changes: 71 additions & 3 deletions src/com/oltpbenchmark/Phase.java
Expand Up @@ -20,12 +20,15 @@ public enum Arrival {


private final boolean rateLimited; private final boolean rateLimited;
private final boolean disabled; private final boolean disabled;
private final boolean serial;
private final boolean timed;
private final List<Double> weights; private final List<Double> weights;
private final int num_weights; private final int num_weights;
private int activeTerminals; private int activeTerminals;
private int nextSerial;




Phase(String benchmarkName, int id, int t, int r, List<String> o, boolean rateLimited, boolean disabled, int activeTerminals, Arrival a) { Phase(String benchmarkName, int id, int t, int r, List<String> o, boolean rateLimited, boolean disabled, boolean serial, boolean timed, int activeTerminals, Arrival a) {
ArrayList<Double> w = new ArrayList<Double>(); ArrayList<Double> w = new ArrayList<Double>();
for (String s : o) for (String s : o)
w.add(Double.parseDouble(s)); w.add(Double.parseDouble(s));
Expand All @@ -38,6 +41,9 @@ public enum Arrival {
this.num_weights = this.weights.size(); this.num_weights = this.weights.size();
this.rateLimited = rateLimited; this.rateLimited = rateLimited;
this.disabled = disabled; this.disabled = disabled;
this.serial = serial;
this.timed = timed;
this.nextSerial = 1;
this.activeTerminals = activeTerminals; this.activeTerminals = activeTerminals;
this.arrival=a; this.arrival=a;
} }
Expand All @@ -50,6 +56,26 @@ public boolean isDisabled() {
return disabled; return disabled;
} }


public boolean isSerial() {
return serial;
}

public boolean isTimed() {
return timed;
}

public boolean isLatencyRun() {
return !timed && serial;
}

public boolean isThroughputRun() {
return !isLatencyRun();
}

public void resetSerial() {
this.nextSerial = 1;
}

public int getActiveTerminals() { public int getActiveTerminals() {
return activeTerminals; return activeTerminals;
} }
Expand Down Expand Up @@ -80,14 +106,49 @@ public double totalWeight() {
* @return * @return
*/ */
public int chooseTransaction() { public int chooseTransaction() {
int randomPercentage = gen.nextInt(100) + 1; return chooseTransaction(false);
}
public int chooseTransaction(boolean isColdQuery) {
if (isDisabled())
return -1;

if (isSerial()) {
int ret;
synchronized(this) {
ret = this.nextSerial;

// Serial runs should not execute queries with non-positive
// weights.
while (ret <= this.num_weights && weights.get(ret - 1).doubleValue() <= 0.0)
ret = ++this.nextSerial;

// If it's a cold execution, then we don't want to advance yet,
// since the hot run needs to execute the same query.
if (!isColdQuery) {
// For timed, serial executions, we're doing a QPS (query
// throughput) run, so we loop through the list multiple
// times. Note that we do the modulus before the increment
// so that we end up in the range [1,num_weights]
if (isTimed()) {
assert this.isThroughputRun();
this.nextSerial %= this.num_weights;
}

++this.nextSerial;
}
}
return ret;
}
else {
int randomPercentage = gen.nextInt((int)totalWeight()) + 1;
double weight = 0.0; double weight = 0.0;
for (int i = 0; i < this.num_weights; i++) { for (int i = 0; i < this.num_weights; i++) {
weight += weights.get(i).doubleValue(); weight += weights.get(i).doubleValue();
if (randomPercentage <= weight) { if (randomPercentage <= weight) {
return i + 1; return i + 1;
} }
} // FOR } // FOR
}


return -1; return -1;
} }
Expand All @@ -102,7 +163,14 @@ public String currentPhaseString() {
if (isDisabled()){ if (isDisabled()){
retString += "[Disabled= true]"; retString += "[Disabled= true]";
} else { } else {
retString += "[Time= " + time + "] [Rate= " + (isRateLimited() ? rate : "unlimited") + "] [Arrival= " + arrival + "] [Ratios= " + getWeights() + "] [Active Workers=" + getActiveTerminals() + "]"; if (isLatencyRun()) {
retString += "[Serial= true] [Time= n/a] ";
}
else {
retString += "[Serial= " + (isSerial()? "true" : "false")
+ "] [Time= " + time + "] ";
}
retString += "[Rate= " + (isRateLimited() ? rate : "unlimited") + "] [Arrival= " + arrival + "] [Ratios= " + getWeights() + "] [Active Workers=" + getActiveTerminals() + "]";
} }
return retString; return retString;
} }
Expand Down
33 changes: 33 additions & 0 deletions src/com/oltpbenchmark/SubmittedProcedure.java
@@ -0,0 +1,33 @@
package com.oltpbenchmark;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;

import com.oltpbenchmark.types.State;
import com.oltpbenchmark.util.QueueLimitException;
import org.apache.log4j.Logger;

/**
* This class is used for keeping track of the procedures that have been
* submitted to the system when running a rate-limited benchmark.
* @author breilly
*/
public class SubmittedProcedure {
private final int type;
private final long startTime;

SubmittedProcedure(int type) {
this.type = type;
this.startTime = System.nanoTime();
}

SubmittedProcedure(int type, long startTime) {
this.type = type;
this.startTime = startTime;
}

public int getType() { return type; }
public long getStartTime() { return startTime; }
}

0 comments on commit e371037

Please sign in to comment.