Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Support for Distributions in Templated Workloads #385

Merged
merged 36 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
760ede7
Added Random distributions
ETHenzlere Oct 26, 2023
9acfc19
Added Binomial Distribution
ETHenzlere Oct 26, 2023
36174c0
Min/Max for all Distributions
ETHenzlere Oct 30, 2023
b28f7ee
Added Timestamps, Time,Date
ETHenzlere Nov 7, 2023
d42d950
HashMap Solution with type casting
ETHenzlere Nov 10, 2023
572ca57
Multi random support
ETHenzlere Nov 14, 2023
6f287d9
Architecture change | Uniform distribution implemented
ETHenzlere Nov 17, 2023
33bef1e
Switched Dist and Type, changed subarray calculation
ETHenzlere Nov 20, 2023
bab1086
Merge branch 'main' into feature/templated-distributions
ETHenzlere Nov 29, 2023
573967c
Renamings and Documentation
ETHenzlere Nov 29, 2023
c12e60a
Enum, More Documentation
ETHenzlere Nov 30, 2023
3d3c9b2
Merge branch 'main' into feature/templated-distributions
bpkroth Dec 1, 2023
51f0f1d
Renamed autogenerated methods, readme format
ETHenzlere Dec 4, 2023
c97d35e
Resolved merge conflicts
ETHenzlere Dec 7, 2023
38747ae
Testing increased, size reduction of massive switch statement
ETHenzlere Dec 7, 2023
dafb90a
Test functionality after merge
ETHenzlere Jan 5, 2024
961d5c4
Lightweight constructor added
ETHenzlere Jan 17, 2024
5454f52
Insert statment modification
ETHenzlere Jan 23, 2024
3f59530
Merged with main
ETHenzlere Jan 24, 2024
06d3f39
Min-Max check
ETHenzlere Jan 24, 2024
949c93d
Changed distributions due to FK contraints
ETHenzlere Jan 24, 2024
19fad84
Typo
ETHenzlere Jan 24, 2024
c9dc450
Typo 2, build checked
ETHenzlere Jan 24, 2024
36318bd
Merge branch 'main' into feature/templated-distributions
bpkroth Jan 24, 2024
ce028cb
Merge branch 'main' into feature/templated-distributions
bpkroth Jan 24, 2024
ee8f4c1
Enums, removal of aliases, nits
ETHenzlere Jan 25, 2024
0235de7
Adapted description
ETHenzlere Jan 25, 2024
180b592
Merge branch 'main' into feature/templated-distributions
ETHenzlere Mar 13, 2024
9bb153f
Merge branch 'main' into feature/templated-distributions
bpkroth Mar 14, 2024
7154f6e
Merge branch 'main' into feature/templated-distributions
ETHenzlere Mar 20, 2024
ad94565
Templated Values with type information
ETHenzlere Mar 20, 2024
556ff15
README cleanup + Assert pattern
ETHenzlere Mar 21, 2024
c039d92
README update for access pattern
ETHenzlere Mar 25, 2024
1b25aa1
Merge branch 'main' into feature/templated-distributions
ETHenzlere Mar 25, 2024
5de5361
README adjustment showing a possible solution for value weighting
ETHenzlere Mar 25, 2024
1054ac9
Merge branch 'main' into feature/templated-distributions
bpkroth Mar 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion config/postgres/sample_templated_config.xml
ETHenzlere marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<work>
<time>10</time>
<rate>100</rate>
<weights>30,20,10,30,10</weights>
<weights>30,20,10,20,10,10</weights>
</work>
</works>

Expand All @@ -45,5 +45,8 @@
<transactiontype>
<name>GetItemByPrice</name>
</transactiontype>
<transactiontype>
<name>GetItemRandom</name>
</transactiontype>
</transactiontypes>
</parameters>
12 changes: 12 additions & 0 deletions data/templated/example.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,16 @@
<value>11</value>
</values>
</template>
<template name="GetItemRandom">
<query><![CDATA[SELECT COUNT(*) FROM item WHERE i_im_id = ?]]></query>
<types>
<type>RANDOM</type>
</types>
<values>
<value>binomial,0,9999</value>
ETHenzlere marked this conversation as resolved.
Show resolved Hide resolved
</values>
<values>
<value>uniform,0,9999</value>
ETHenzlere marked this conversation as resolved.
Show resolved Hide resolved
</values>
</template>
</templates>
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ protected List<Worker<? extends BenchmarkModule>> makeWorkersImpl() {
// Sanity check that the procedure has the right type.
if (!(kv.getValue() instanceof GenericQuery)) {
LOG.error(
String.format(
"Procedure %s does not have the correct class type (GenericQuery).",
kv.getValue().toString()));
String.format(
"Procedure %s does not have the correct class type (GenericQuery).",
kv.getValue().toString()));
continue;
}
GenericQuery proc = (GenericQuery) kv.getValue();
Expand Down Expand Up @@ -194,14 +194,14 @@ public final class %s extends %s {
}
}
""".formatted(
GenericQuery.class.getPackageName(),
qt.getName(),
GenericQuery.class.getCanonicalName(),
QueryTemplateInfo.class.getCanonicalName(),
SQLStmt.class.getCanonicalName(),
StringEscapeUtils.escapeJava(qt.getQuery()),
getParamsString(qt.getParamsTypes()),
getParamsString(qt.getParamsValues()));
GenericQuery.class.getPackageName(),
qt.getName(),
GenericQuery.class.getCanonicalName(),
QueryTemplateInfo.class.getCanonicalName(),
SQLStmt.class.getCanonicalName(),
StringEscapeUtils.escapeJava(qt.getQuery()),
getParamsString(qt.getParamsTypes()),
getParamsString(qt.getParamsValues()));
LOG.debug("Class definition for query template {}:\n {}", qt.getName(), s);
final String qualifiedClassName = GenericQuery.class.getPackageName() + "." + qt.getName();
final ISimpleCompiler compiler = compilerFactory.newSimpleCompiler();
Expand Down
ETHenzlere marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class TemplatedWorker extends Worker<TemplatedBenchmark> {
protected final Map<Class<? extends Procedure>, TraceTransactionGenerator> generators;

public TemplatedWorker(TemplatedBenchmark benchmarkModule, int id,
Map<Class<? extends Procedure>, TraceTransactionGenerator> generators) {
Map<Class<? extends Procedure>, TraceTransactionGenerator> generators) {
super(benchmarkModule, id);
this.rng().setSeed(benchmarkModule.getWorkloadConfiguration().getRandomSeed());
this.generators = generators;
Expand All @@ -49,7 +49,8 @@ protected TransactionStatus executeWork(Connection conn, TransactionType nextTra
// If there is a generator available use it to create a
// parameter binding.
TraceTransactionGenerator generator = generators.get(clazz);
proc.run(conn, generator.nextTransaction().getParams());
proc.run(conn, generator.nextTransaction().getParams(),
generator.nextTransaction().getRandomGenHashMap());
} else {
// If the generator has no transactions, there are no parameters.
proc.run(conn);
Expand All @@ -63,4 +64,3 @@ protected TransactionStatus executeWork(Connection conn, TransactionType nextTra

}
}

Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,38 @@
package com.oltpbenchmark.benchmarks.templated.procedures;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import org.immutables.value.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.oltpbenchmark.api.Procedure;
import com.oltpbenchmark.api.SQLStmt;
import com.oltpbenchmark.distributions.ScrambledZipfianGenerator;
import com.oltpbenchmark.distributions.ZipfianGenerator;
import com.oltpbenchmark.util.TextGenerator;

public abstract class GenericQuery extends Procedure {

protected static final Logger LOG = LoggerFactory.getLogger(GenericQuery.class);

/** Execution method with parameters. */
public void run(Connection conn, List<Object> params) throws SQLException {
try (PreparedStatement stmt = getStatement(conn, params); ResultSet rs = stmt.executeQuery()) {
public void run(Connection conn, List<Object> params, HashMap<Integer, Object> randomGenerators)
throws SQLException {
try (PreparedStatement stmt = getStatement(conn, params, randomGenerators);
ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
//do nothing
// do nothing
}
}
conn.commit();
Expand All @@ -48,33 +58,96 @@ public void run(Connection conn, List<Object> params) throws SQLException {
public void run(Connection conn) throws SQLException {
QueryTemplateInfo queryTemplateInfo = this.getQueryTemplateInfo();

try (PreparedStatement stmt = this.getPreparedStatement(conn, queryTemplateInfo.getQuery()); ResultSet rs = stmt.executeQuery()) {
try (PreparedStatement stmt = this.getPreparedStatement(conn, queryTemplateInfo.getQuery());
ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
//do nothing
// do nothing
}
}
conn.commit();
}

public PreparedStatement getStatement(Connection conn, List<Object> params) throws SQLException {
public PreparedStatement getStatement(Connection conn, List<Object> params,
HashMap<Integer, Object> randomGenerators) throws SQLException {
QueryTemplateInfo queryTemplateInfo = this.getQueryTemplateInfo();

PreparedStatement stmt = this.getPreparedStatement(conn, queryTemplateInfo.getQuery());
String[] paramsTypes = queryTemplateInfo.getParamsTypes();
int j = 0;
for (int i = 0; i < paramsTypes.length; i++) {
if (paramsTypes[i].equalsIgnoreCase("NULL")) {
stmt.setNull(i + 1, Types.NULL);
} else if (paramsTypes[i].equalsIgnoreCase("RANDOM")) {
int index = i + j;
String distType = params.get(index).toString();
int minI, maxI;
switch (distType) {
case "zipf":
ZipfianGenerator zipfGen = (ZipfianGenerator) randomGenerators.get(index);
stmt.setInt(i + 1, zipfGen.nextInt());
j += 2;
break;
case "uniform":
minI = Integer.parseInt(params.get(index + 1).toString());
maxI = Integer.parseInt(params.get(index + 2).toString());
Random rnd = (Random) randomGenerators.get(index);
int uVal = rnd.nextInt(maxI - minI) + minI;
stmt.setInt(i + 1, uVal);
j += 2;
break;
case "binomial":
minI = Integer.parseInt(params.get(index + 1).toString());
maxI = Integer.parseInt(params.get(index + 2).toString());
Random rng = (Random) randomGenerators.get(index);
int bVal;
do {
bVal = (int) (minI + Math.abs(rng.nextGaussian()) * maxI);
} while (bVal > maxI || bVal < minI);

stmt.setInt(i + 1, bVal);
j += 2;
break;
case "scrambled":
ScrambledZipfianGenerator scramZipf = (ScrambledZipfianGenerator) randomGenerators.get(index);
stmt.setInt(i + 1, scramZipf.nextInt());
j += 2;
break;
case "string":
maxI = Integer.parseInt(params.get(index + 1).toString());
Random rand = (Random) randomGenerators.get(index);
String randText = TextGenerator.randomStr(rand, maxI);
ETHenzlere marked this conversation as resolved.
Show resolved Hide resolved
stmt.setString(i + 1, randText);
j += 1;
break;
case "datetime":
case "timestamp":
stmt.setTimestamp(i + 1, new Timestamp(System.currentTimeMillis()));
break;
case "date":
stmt.setDate(i + 1, new Date(System.currentTimeMillis()));
break;
case "time":
stmt.setTime(i + 1, new Time(System.currentTimeMillis()));
ETHenzlere marked this conversation as resolved.
Show resolved Hide resolved
break;
default:
throw new RuntimeException(
"No suitable distribution found. Currently supported are 'zipf' | 'scrambled' | 'normal' | 'uniform' | 'string' | 'datetime' | 'timestamp' | 'date' | 'time' ");
bpkroth marked this conversation as resolved.
Show resolved Hide resolved
}

} else {
try {
// TODO: add support for nullable other types
// For instance, can we provide a <value /> tag in the XML file to represent a NULL value?
// For instance, can we provide a <value /> tag in the XML file to represent a
// NULL value?
// Or does it need a special marker like "$null" to signify a NULL value?
Object param = params.get(i);
stmt.setObject(i + 1, param, Integer.parseInt(Types.class.getDeclaredField(paramsTypes[i]).get(null).toString()));
stmt.setObject(i + 1, param,
Integer.parseInt(Types.class.getDeclaredField(paramsTypes[i]).get(null).toString()));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(
"Error when setting parameters. Parameter type: " + paramsTypes[i] + ", parameter value: " + params.get(i));
"Error when setting parameters. Parameter type: " + paramsTypes[i] + ", parameter value: "
+ params.get(i));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,68 @@

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import com.oltpbenchmark.api.Operation;
import com.oltpbenchmark.distributions.ScrambledZipfianGenerator;
import com.oltpbenchmark.distributions.ZipfianGenerator;

/**
* Immutable class containing information about transactions.
*/
public class GenericQueryOperation extends Operation {

public final List<Object> params;

public final HashMap<Integer, Object> randomGenerators;

public GenericQueryOperation(Object[] params) {
super();
this.params = Collections.unmodifiableList(Arrays.asList(params));
this.randomGenerators = this.mapRandom();
}

public List<Object> getParams() {
return params;
}

private HashMap<Integer, Object> mapRandom() {
HashMap<Integer, Object> randomGenerators = new HashMap<Integer, Object>();
Integer min, max;
for (int i = 0; i < params.size(); i++) {
String paramString = params.get(i).toString();
switch (paramString) {
case "zipf":
min = Integer.parseInt(params.get(i + 1).toString());
max = Integer.parseInt(params.get(i + 2).toString());
ZipfianGenerator zipf = new ZipfianGenerator(new Random(), min, max);
ETHenzlere marked this conversation as resolved.
Show resolved Hide resolved
randomGenerators.put(i, zipf);
break;
case "uniform":
randomGenerators.put(i, new Random());
break;
case "binomial":
randomGenerators.put(i, new Random());
break;
case "scrambled":
min = Integer.parseInt(params.get(i + 1).toString());
max = Integer.parseInt(params.get(i + 2).toString());
ScrambledZipfianGenerator scramZipf = new ScrambledZipfianGenerator(min, max);
randomGenerators.put(i, scramZipf);
break;
case "string":
randomGenerators.put(i, new Random());
i -= 1;
break;
}
i += 2;
}
return randomGenerators;

}

public HashMap<Integer, Object> getRandomGenHashMap() {
return this.randomGenerators;
}
}