From a82a77e542c58436b2d8cc05e19484ddd45bcc84 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Thu, 31 Aug 2023 15:34:48 +0200 Subject: [PATCH 01/20] Base commit (no examples). --- pom.xml | 5 + .../ConcurrentPerfStresstestTaskExecutor.java | 143 ++++++++++++++++++ .../lst_bench/common/CustomTaskExecutor.java | 54 +++++++ .../common/DependentTaskExecutor.java | 11 +- .../lst_bench/common/SessionExecutor.java | 7 +- .../input/BenchmarkObjectFactory.java | 59 ++++++-- .../microsoft/lst_bench/input/Session.java | 6 + .../com/microsoft/lst_bench/input/Task.java | 12 ++ .../microsoft/lst_bench/sql/SQLParser.java | 15 +- .../telemetry/SQLTelemetryRegistry.java | 16 +- .../microsoft/lst_bench/util/StringUtils.java | 10 +- src/main/resources/schemas/workload.json | 15 ++ .../microsoft/lst_bench/input/ParserTest.java | 2 + 13 files changed, 312 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java create mode 100644 src/main/java/com/microsoft/lst_bench/common/CustomTaskExecutor.java diff --git a/pom.xml b/pom.xml index f30b1601..b00b0928 100644 --- a/pom.xml +++ b/pom.xml @@ -127,6 +127,11 @@ 1.1.0 test + + commons-io + commons-io + 2.13.0 + diff --git a/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java new file mode 100644 index 00000000..bac7ba8e --- /dev/null +++ b/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.microsoft.lst_bench.common; + +import com.microsoft.lst_bench.client.ClientException; +import com.microsoft.lst_bench.client.Connection; +import com.microsoft.lst_bench.exec.FileExec; +import com.microsoft.lst_bench.exec.ImmutableStatementExec; +import com.microsoft.lst_bench.exec.StatementExec; +import com.microsoft.lst_bench.exec.TaskExec; +import com.microsoft.lst_bench.input.BenchmarkObjectFactory; +import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; +import com.microsoft.lst_bench.telemetry.EventInfo.Status; +import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; +import com.microsoft.lst_bench.util.StringUtils; +import java.time.Instant; +import java.util.Map; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Custom task executor implementation that allows users to execute dependent tasks. We call a + * dependent task a task that iteratively executes a) a statement that is expected to return a + * result; and b) a statement repeatedly that is expected to use that result. The result of the + * first statement is stored in an intermediate object that can be specific to the connection. The + * expected object for a JDBC connection is of type List>, handling of other + * objects would need to be added to the if-clause that checks the instance of the object. + */ +public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { + + private static final Logger LOGGER = + LoggerFactory.getLogger(ConcurrentPerfStresstestTaskExecutor.class); + + public ConcurrentPerfStresstestTaskExecutor( + SQLTelemetryRegistry telemetryRegistry, + String experimentStartTime, + CustomTaskExecutorArguments arguments) { + super(telemetryRegistry, experimentStartTime, arguments); + } + + @Override + public void executeTask(Connection connection, TaskExec task, Map values) + throws ClientException { + // Will never be null since they are set to default values. + int numJoins = this.getArguments().getConcurrentTaskNumJoins(); + int minQueryLength = this.getArguments().getConcurrentTaskMinQueryLength(); + + for (FileExec file : task.getFiles()) { + Instant fileStartTime = Instant.now(); + + if (file.getStatements().size() != 1) { + writeFileEvent(fileStartTime, file.getId(), Status.FAILURE); + throw new ClientException("Concurrent task execution requires one statement per file."); + } + StatementExec statement = file.getStatements().get(0); + + if (statement.getStatement().contains("WHERE") + || statement.getStatement().contains("ORDER") + || statement.getStatement().contains(";")) { + writeStatementEvent( + fileStartTime, + file.getId(), + Status.FAILURE, + /* payload= */ "Query contains invalid key words (WHERE, ORDER, etc.): " + + statement.getStatement()); + throw new ClientException( + "Query contains invalid key words (WHERE, ORDER, etc.): " + statement.getStatement()); + } else if (!statement.getStatement().contains("FROM")) { + writeStatementEvent( + fileStartTime, + file.getId(), + Status.FAILURE, + /* payload= */ "Query does not contain keyword 'FROM': " + statement.getStatement()); + throw new ClientException( + "Query does not contain keyword 'FROM': " + statement.getStatement()); + } + + try { + String query = statement.getStatement().split(";")[0]; + String join_clause = query.split("FROM")[1].trim(); + // Adjust number of joins. + for (int i = 0; i < numJoins; i++) { + query += ", " + join_clause + i; + } + // Adjust query padding. + int queryPadding = minQueryLength - query.length(); + if (queryPadding > 0) { + query += new String(new char[queryPadding]).replace('\0', ' '); + } + + StatementExec mod_statement = + ImmutableStatementExec.of( + statement.getId() + + BenchmarkObjectFactory.DEFAULT_ID_SEPARATOR + + "numJoins" + + numJoins + + BenchmarkObjectFactory.DEFAULT_ID_CONNECTOR + + "minQueryLength" + + minQueryLength, + query); + executeStatement(connection, values, mod_statement); + } catch (ClientException e) { + LOGGER.error("Exception executing file: " + file.getId()); + writeFileEvent(fileStartTime, file.getId(), Status.FAILURE); + throw e; + } + writeFileEvent(fileStartTime, file.getId(), Status.SUCCESS); + } + } + + private void executeStatement( + Connection connection, Map values, StatementExec statement) + throws ClientException { + Instant statementStartTime = Instant.now(); + try { + connection.execute(StringUtils.replaceParameters(statement, values).getStatement()); + } catch (Exception e) { + String error_msg = + "Exception executing statement: " + + statement.getId() + + "; " + + ExceptionUtils.getStackTrace(e); + LOGGER.error(error_msg); + writeStatementEvent(statementStartTime, statement.getId(), Status.FAILURE, error_msg); + throw new ClientException(error_msg); + } + writeStatementEvent(statementStartTime, statement.getId(), Status.SUCCESS, /* payload= */ null); + } +} diff --git a/src/main/java/com/microsoft/lst_bench/common/CustomTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/common/CustomTaskExecutor.java new file mode 100644 index 00000000..3268931a --- /dev/null +++ b/src/main/java/com/microsoft/lst_bench/common/CustomTaskExecutor.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.microsoft.lst_bench.common; + +import com.microsoft.lst_bench.client.ClientException; +import com.microsoft.lst_bench.client.Connection; +import com.microsoft.lst_bench.exec.TaskExec; +import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; +import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; +import java.util.Map; + +/** + * Custom task executor implementation that allows users to execute dependent tasks. We call a + * dependent task a task that iteratively executes a) a statement that is expected to return a + * result; and b) a statement repeatedly that is expected to use that result. The result of the + * first statement is stored in an intermediate object that can be specific to the connection. The + * expected object for a JDBC connection is of type List>, handling of other + * objects would need to be added to the if-clause that checks the instance of the object. + */ +public class CustomTaskExecutor extends TaskExecutor { + + protected final CustomTaskExecutorArguments arguments; + + public CustomTaskExecutor( + SQLTelemetryRegistry telemetryRegistry, + String experimentStartTime, + CustomTaskExecutorArguments arguments) { + super(telemetryRegistry, experimentStartTime); + this.arguments = arguments; + } + + @Override + public void executeTask(Connection connection, TaskExec task, Map values) + throws ClientException { + super.executeTask(connection, task, values); + } + + protected CustomTaskExecutorArguments getArguments() { + return this.arguments; + } +} diff --git a/src/main/java/com/microsoft/lst_bench/common/DependentTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/common/DependentTaskExecutor.java index b1566554..06997dc0 100644 --- a/src/main/java/com/microsoft/lst_bench/common/DependentTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/common/DependentTaskExecutor.java @@ -39,30 +39,27 @@ * expected object for a JDBC connection is of type List>, handling of other * objects would need to be added to the if-clause that checks the instance of the object. */ -public class DependentTaskExecutor extends TaskExecutor { +public class DependentTaskExecutor extends CustomTaskExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(DependentTaskExecutor.class); - private final CustomTaskExecutorArguments arguments; - private final int DEFAULT_BATCH_SIZE = 1; public DependentTaskExecutor( SQLTelemetryRegistry telemetryRegistry, String experimentStartTime, CustomTaskExecutorArguments arguments) { - super(telemetryRegistry, experimentStartTime); - this.arguments = arguments; + super(telemetryRegistry, experimentStartTime, arguments); } @Override public void executeTask(Connection connection, TaskExec task, Map values) throws ClientException { int batch_size; - if (this.arguments == null || this.arguments.getDependentTaskBatchSize() == null) { + if (this.getArguments() == null || this.getArguments().getDependentTaskBatchSize() == null) { batch_size = DEFAULT_BATCH_SIZE; } else { - batch_size = this.arguments.getDependentTaskBatchSize().intValue(); + batch_size = this.getArguments().getDependentTaskBatchSize().intValue(); } QueryResult queryResult = null; diff --git a/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java b/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java index 6e7b8074..0e63f522 100644 --- a/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -85,7 +86,11 @@ public Boolean call() throws ClientException { writeTaskEvent(taskStartTime, task.getId(), Status.SUCCESS); } } catch (Exception e) { - LOGGER.error("Exception executing session: " + session.getId()); + LOGGER.error( + "Exception executing session: " + + session.getId() + + ";" + + ExceptionUtils.getStackTrace(e)); writeSessionEvent(sessionStartTime, session.getId(), Status.FAILURE); throw e; } diff --git a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java index 45a8c9fe..3c4aa86d 100644 --- a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java +++ b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java @@ -20,12 +20,15 @@ import com.microsoft.lst_bench.client.SparkConnectionManager; import com.microsoft.lst_bench.common.BenchmarkConfig; import com.microsoft.lst_bench.exec.FileExec; +import com.microsoft.lst_bench.exec.ImmutableFileExec; import com.microsoft.lst_bench.exec.ImmutablePhaseExec; import com.microsoft.lst_bench.exec.ImmutableSessionExec; +import com.microsoft.lst_bench.exec.ImmutableStatementExec; import com.microsoft.lst_bench.exec.ImmutableTaskExec; import com.microsoft.lst_bench.exec.ImmutableWorkloadExec; import com.microsoft.lst_bench.exec.PhaseExec; import com.microsoft.lst_bench.exec.SessionExec; +import com.microsoft.lst_bench.exec.StatementExec; import com.microsoft.lst_bench.exec.TaskExec; import com.microsoft.lst_bench.input.config.ConnectionConfig; import com.microsoft.lst_bench.input.config.ExperimentConfig; @@ -44,6 +47,9 @@ /** Factory class for creating benchmark objects from the input configuration. */ public class BenchmarkObjectFactory { + public static final String DEFAULT_ID_SEPARATOR = ";"; + public static final String DEFAULT_ID_CONNECTOR = "_"; + private BenchmarkObjectFactory() { // Defeat instantiation } @@ -159,19 +165,26 @@ private static PhaseExec createPhaseExec( ExperimentConfig experimentConfig, Map taskTemplateIdToPermuteOrderCounter, Map taskTemplateIdToParameterValuesCounter) { + final String SESSION_PREFIX = "session"; List sessions = new ArrayList<>(); for (int i = 0; i < phase.getSessions().size(); i++) { Session session = phase.getSessions().get(i); - String sessionId = String.valueOf(i); - SessionExec sessionExec = - createSessionExec( - sessionId, - session, - idToTaskTemplate, - experimentConfig, - taskTemplateIdToPermuteOrderCounter, - taskTemplateIdToParameterValuesCounter); - sessions.add(sessionExec); + for (int j = 0; j <= session.getDuplicateSession(); j++) { + String sessionId = + phase.getId() + DEFAULT_ID_SEPARATOR + SESSION_PREFIX + DEFAULT_ID_CONNECTOR + i; + if (j > 0) { + sessionId += DEFAULT_ID_CONNECTOR + j; + } + SessionExec sessionExec = + createSessionExec( + sessionId, + session, + idToTaskTemplate, + experimentConfig, + taskTemplateIdToPermuteOrderCounter, + taskTemplateIdToParameterValuesCounter); + sessions.add(sessionExec); + } } return ImmutablePhaseExec.of(phase.getId(), sessions); } @@ -184,9 +197,10 @@ private static SessionExec createSessionExec( Map taskTemplateIdToPermuteOrderCounter, Map taskTemplateIdToParameterValuesCounter) { List tasks = new ArrayList<>(); - for (int j = 0; j < session.getTasks().size(); j++) { - Task task = session.getTasks().get(j); - String taskId = task.getTemplateId() + "_" + j; + for (int i = 0; i < session.getTasks().size(); i++) { + Task task = session.getTasks().get(i); + String taskId = + sessionId + DEFAULT_ID_SEPARATOR + task.getTemplateId() + DEFAULT_ID_CONNECTOR + i; TaskExec taskExec = createTaskExec( taskId, @@ -214,6 +228,7 @@ private static TaskExec createTaskExec( } List files = createFileExecList( + taskId, taskTemplate, task, experimentConfig, @@ -226,6 +241,7 @@ private static TaskExec createTaskExec( } private static List createFileExecList( + String taskId, TaskTemplate taskTemplate, Task task, ExperimentConfig experimentConfig, @@ -233,7 +249,10 @@ private static List createFileExecList( Map taskTemplateIdToParameterValuesCounter) { List files = new ArrayList<>(); for (String file : taskTemplate.getFiles()) { - files.add(SQLParser.getStatements(file)); + final String fileId = taskId + DEFAULT_ID_SEPARATOR + file; + files.add( + ImmutableFileExec.of( + fileId, createStatementExecList(fileId, SQLParser.getStatements(file)))); } files = applyPermutationOrder(taskTemplate, task, taskTemplateIdToPermuteOrderCounter, files); files = applyReplaceRegex(task, files); @@ -243,6 +262,18 @@ private static List createFileExecList( return files; } + private static List createStatementExecList( + String fileId, List statements) { + List statement_execs = new ArrayList<>(); + final String STATEMENT_PREFIX = "statement"; + for (int i = 0; i < statements.size(); i++) { + String statementId = + fileId + DEFAULT_ID_SEPARATOR + STATEMENT_PREFIX + DEFAULT_ID_CONNECTOR + i; + statement_execs.add(ImmutableStatementExec.of(statementId, statements.get(i))); + } + return statement_execs; + } + private static List applyPermutationOrder( TaskTemplate taskTemplate, Task task, diff --git a/src/main/java/com/microsoft/lst_bench/input/Session.java b/src/main/java/com/microsoft/lst_bench/input/Session.java index 59f1353d..175fc958 100644 --- a/src/main/java/com/microsoft/lst_bench/input/Session.java +++ b/src/main/java/com/microsoft/lst_bench/input/Session.java @@ -34,4 +34,10 @@ public interface Session { @JsonProperty("target_endpoint") @Nullable Integer getTargetEndpoint(); + + @JsonProperty("duplicate_session") + @Value.Default + default int getDuplicateSession() { + return 0; + } } diff --git a/src/main/java/com/microsoft/lst_bench/input/Task.java b/src/main/java/com/microsoft/lst_bench/input/Task.java index 38be48b7..a074bfdd 100644 --- a/src/main/java/com/microsoft/lst_bench/input/Task.java +++ b/src/main/java/com/microsoft/lst_bench/input/Task.java @@ -51,6 +51,18 @@ public interface Task { interface CustomTaskExecutorArguments { @JsonProperty("dependent_task_batch_size") @Nullable Integer getDependentTaskBatchSize(); + + @JsonProperty("concurrent_task_num_joins") + @Value.Default + default int getConcurrentTaskNumJoins() { + return 0; + } + + @JsonProperty("concurrent_task_min_query_length") + @Value.Default + default int getConcurrentTaskMinQueryLength() { + return 0; + } } @JsonProperty("replace_regex") diff --git a/src/main/java/com/microsoft/lst_bench/sql/SQLParser.java b/src/main/java/com/microsoft/lst_bench/sql/SQLParser.java index 7383948c..d4c71bb1 100644 --- a/src/main/java/com/microsoft/lst_bench/sql/SQLParser.java +++ b/src/main/java/com/microsoft/lst_bench/sql/SQLParser.java @@ -15,10 +15,6 @@ */ package com.microsoft.lst_bench.sql; -import com.microsoft.lst_bench.exec.FileExec; -import com.microsoft.lst_bench.exec.ImmutableFileExec; -import com.microsoft.lst_bench.exec.ImmutableStatementExec; -import com.microsoft.lst_bench.exec.StatementExec; import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -35,16 +31,15 @@ private SQLParser() { // Defeat instantiation } - public static FileExec getStatements(String filepath) { + public static List getStatements(String filepath) { return getStatements(new File(filepath)); } - public static FileExec getStatements(File file) { - final List statements = new ArrayList<>(); + public static List getStatements(File file) { + final List statements = new ArrayList<>(); try (BufferedReader br = new BufferedReader( new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8))) { - int i = 0; for (; ; ) { String statement; try { @@ -55,12 +50,12 @@ public static FileExec getStatements(File file) { if (statement == null) { break; } - statements.add(ImmutableStatementExec.of(file.getName() + "_" + i++, statement)); + statements.add(statement); } } catch (IOException e) { throw new RuntimeException("Cannot read query in file: " + file, e); } - return ImmutableFileExec.of(file.getName(), statements); + return statements; } private static String nextStatement(BufferedReader reader) throws IOException { diff --git a/src/main/java/com/microsoft/lst_bench/telemetry/SQLTelemetryRegistry.java b/src/main/java/com/microsoft/lst_bench/telemetry/SQLTelemetryRegistry.java index b1b9a81e..84d1a939 100644 --- a/src/main/java/com/microsoft/lst_bench/telemetry/SQLTelemetryRegistry.java +++ b/src/main/java/com/microsoft/lst_bench/telemetry/SQLTelemetryRegistry.java @@ -18,7 +18,6 @@ import com.microsoft.lst_bench.client.ClientException; import com.microsoft.lst_bench.client.Connection; import com.microsoft.lst_bench.client.ConnectionManager; -import com.microsoft.lst_bench.exec.StatementExec; import com.microsoft.lst_bench.sql.SQLParser; import com.microsoft.lst_bench.util.StringUtils; import java.util.ArrayList; @@ -37,7 +36,7 @@ public class SQLTelemetryRegistry { private final ConnectionManager connectionManager; - private final List insertFileStatements; + private final List insertFileStatements; // TODO: Make writing events thread-safe. private List eventsStream; @@ -52,9 +51,10 @@ public SQLTelemetryRegistry( this.connectionManager = connectionManager; this.eventsStream = Collections.synchronizedList(new ArrayList<>()); this.insertFileStatements = - SQLParser.getStatements(insertFile).getStatements().stream() + SQLParser.getStatements(insertFile).stream() .map(s -> StringUtils.replaceParameters(s, parameterValues)) .collect(Collectors.toUnmodifiableList()); + // Create the tables if they don't exist. if (executeDdl) { executeDdl(ddlFile, parameterValues); @@ -65,9 +65,9 @@ private void executeDdl(String ddlFile, Map parameterValues) throws ClientException { LOGGER.info("Creating new logging tables..."); try (Connection connection = connectionManager.createConnection()) { - List ddlFileStatements = SQLParser.getStatements(ddlFile).getStatements(); - for (StatementExec query : ddlFileStatements) { - String currentQuery = StringUtils.replaceParameters(query, parameterValues).getStatement(); + List ddlFileStatements = SQLParser.getStatements(ddlFile); + for (String query : ddlFileStatements) { + String currentQuery = StringUtils.replaceParameters(query, parameterValues); connection.execute(currentQuery); } } @@ -101,8 +101,8 @@ public void flush() throws EventException { StringUtils.quote(o.getStatus().toString()), StringUtils.quote(o.getPayload()))) .collect(Collectors.joining("),(", "(", ")"))); - for (StatementExec query : insertFileStatements) { - String currentQuery = StringUtils.replaceParameters(query, values).getStatement(); + for (String query : insertFileStatements) { + String currentQuery = StringUtils.replaceParameters(query, values); connection.execute(currentQuery); } diff --git a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java index f1194f35..96a9afea 100644 --- a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java +++ b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java @@ -50,14 +50,18 @@ public static String quote(String str) { return "'" + str + "'"; } - public static StatementExec replaceParameters( - StatementExec statement, Map parameterValues) { + public static String replaceParameters(String statement, Map parameterValues) { if (parameterValues == null || parameterValues.isEmpty()) { // Nothing to do return statement; } + return StringUtils.format(statement, parameterValues); + } + + public static StatementExec replaceParameters( + StatementExec statement, Map parameterValues) { return ImmutableStatementExec.of( - statement.getId(), StringUtils.format(statement.getStatement(), parameterValues)); + statement.getId(), replaceParameters(statement.getStatement(), parameterValues)); } public static FileExec replaceParameters(FileExec file, Map parameterValues) { diff --git a/src/main/resources/schemas/workload.json b/src/main/resources/schemas/workload.json index 7ad13283..fa2dacab 100644 --- a/src/main/resources/schemas/workload.json +++ b/src/main/resources/schemas/workload.json @@ -69,6 +69,16 @@ "type": "integer", "title": "Batch size for DependentTaskExecutor", "description": "Sets the batch size for a task executed; specific to the DependentTaskExecutor class" + }, + "concurrent_task_num_joins": { + "type": "integer", + "title": "List of number of joins that are to be tested", + "description": "Determines how the query will be extended with the number of joins" + }, + "concurrent_task_min_query_length": { + "type": "integer", + "title": "List of minimum query lengths that are to be tested", + "description": "Determines how the query will be extended with padding if the minimum query length is not exceeded" } } }, @@ -99,6 +109,11 @@ "type": "integer", "title": "Target endpoint index (default: 0)", "description": "The positional index (starting from 0) of the connection manager within the connections configuration file" + }, + "duplicate_session": { + "type": "integer", + "title": "Duplication count for this session", + "description": "Determines how often a session will be duplicated; total session count is duplicate_session + 1 (default: 0)" } } } diff --git a/src/test/java/com/microsoft/lst_bench/input/ParserTest.java b/src/test/java/com/microsoft/lst_bench/input/ParserTest.java index f30b37e3..6b128eea 100644 --- a/src/test/java/com/microsoft/lst_bench/input/ParserTest.java +++ b/src/test/java/com/microsoft/lst_bench/input/ParserTest.java @@ -496,6 +496,7 @@ public void testParseWP3RWConcurrencyMulti() throws IOException { List tasksDM = sessions.get(1).getTasks(); Assertions.assertEquals(2, tasksDM.size()); Assertions.assertEquals(1, sessions.get(1).getTargetEndpoint()); + Assertions.assertEquals(0, sessions.get(1).getDuplicateSession()); } break; case "single_user_2_optimize_1": @@ -505,6 +506,7 @@ public void testParseWP3RWConcurrencyMulti() throws IOException { List tasksO = sessions.get(1).getTasks(); Assertions.assertEquals(1, tasksO.size()); Assertions.assertEquals(1, sessions.get(1).getTargetEndpoint()); + Assertions.assertEquals(0, sessions.get(1).getDuplicateSession()); } break; case "setup": From 925ca70200e001e99aa87804e6a4d4df2c9470b2 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Thu, 31 Aug 2023 15:47:29 +0200 Subject: [PATCH 02/20] Adding some example configs. --- .../config/sqlserver/experiment_config.yaml | 7 +++++++ .../sqlserver/jdbc_connection_config.yaml | 9 +++++++++ .../config/sqlserver/task_library.yaml | 8 ++++++++ .../config/sqlserver/telemetry_config.yaml | 13 ++++++++++++ .../config/sqlserver/w_perf_stresstest.yaml | 20 +++++++++++++++++++ .../scripts/sqlserver/perf_stresstest.sql | 1 + 6 files changed, 58 insertions(+) create mode 100644 src/test/resources/config/sqlserver/experiment_config.yaml create mode 100644 src/test/resources/config/sqlserver/jdbc_connection_config.yaml create mode 100644 src/test/resources/config/sqlserver/task_library.yaml create mode 100644 src/test/resources/config/sqlserver/telemetry_config.yaml create mode 100644 src/test/resources/config/sqlserver/w_perf_stresstest.yaml create mode 100644 src/test/resources/scripts/sqlserver/perf_stresstest.sql diff --git a/src/test/resources/config/sqlserver/experiment_config.yaml b/src/test/resources/config/sqlserver/experiment_config.yaml new file mode 100644 index 00000000..1be530a7 --- /dev/null +++ b/src/test/resources/config/sqlserver/experiment_config.yaml @@ -0,0 +1,7 @@ +# Description: Experiment Configuration +--- +version: 1 +id: perf-stresstest +repetitions: 1 +metadata: + system: sqlserver diff --git a/src/test/resources/config/sqlserver/jdbc_connection_config.yaml b/src/test/resources/config/sqlserver/jdbc_connection_config.yaml new file mode 100644 index 00000000..6913bd39 --- /dev/null +++ b/src/test/resources/config/sqlserver/jdbc_connection_config.yaml @@ -0,0 +1,9 @@ +# Description: Connections Configuration +--- +version: 1 +connections: +- id: sqlserver_0 + driver: com.microsoft.sqlserver.jdbc.SQLServerDriver + url: jdbc:sqlserver://localhost:1433;encrypt=false;database=testdb; + username: $USER + password: $PASSWORD diff --git a/src/test/resources/config/sqlserver/task_library.yaml b/src/test/resources/config/sqlserver/task_library.yaml new file mode 100644 index 00000000..c968b22e --- /dev/null +++ b/src/test/resources/config/sqlserver/task_library.yaml @@ -0,0 +1,8 @@ +# Description: Tasks Library +--- +version: 1 +task_templates: +# Example task template for the base query of the custom concurrent performance stresstest. +- id: base_query + files: + - src/test/resources/scripts/sqlserver/perf_stresstest.sql diff --git a/src/test/resources/config/sqlserver/telemetry_config.yaml b/src/test/resources/config/sqlserver/telemetry_config.yaml new file mode 100644 index 00000000..4d2a2bd5 --- /dev/null +++ b/src/test/resources/config/sqlserver/telemetry_config.yaml @@ -0,0 +1,13 @@ +# Description: Telemetry Configuration +--- +version: 1 +connection: + id: duckdb_0 + driver: org.duckdb.DuckDBDriver + url: jdbc:duckdb:./telemetry +execute_ddl: true +ddl_file: 'src/main/resources/scripts/logging/duckdb/ddl.sql' +insert_file: 'src/main/resources/scripts/logging/duckdb/insert.sql' +# The following parameter values will be used to replace the variables in the logging statements. +parameter_values: + data_path: '' diff --git a/src/test/resources/config/sqlserver/w_perf_stresstest.yaml b/src/test/resources/config/sqlserver/w_perf_stresstest.yaml new file mode 100644 index 00000000..1e2ecda0 --- /dev/null +++ b/src/test/resources/config/sqlserver/w_perf_stresstest.yaml @@ -0,0 +1,20 @@ +# Description: Example for custom concurrent performance stresstest workload +--- +version: 1 +id: perfstress-test +phases: +- id: query_execution_1 + sessions: + - tasks: + - template_id: base_query + custom_task_executor: com.microsoft.lst_bench.common.ConcurrentPerfStresstestTaskExecutor + custom_task_executor_arguments: + concurrent_task_num_joins: 5 + duplicate_session: 5 +- id: query_execution_2 + sessions: + - tasks: + - template_id: base_query + custom_task_executor: com.microsoft.lst_bench.common.ConcurrentPerfStresstestTaskExecutor + custom_task_executor_arguments: + concurrent_task_min_query_length: 1000 \ No newline at end of file diff --git a/src/test/resources/scripts/sqlserver/perf_stresstest.sql b/src/test/resources/scripts/sqlserver/perf_stresstest.sql new file mode 100644 index 00000000..5481c25a --- /dev/null +++ b/src/test/resources/scripts/sqlserver/perf_stresstest.sql @@ -0,0 +1 @@ +SELECT t.* FROM test_table t; \ No newline at end of file From 4f8592257b33dcc54957772e39e659d44212650f Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Thu, 31 Aug 2023 16:58:36 +0200 Subject: [PATCH 03/20] bugfix --- src/main/java/com/microsoft/lst_bench/util/StringUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java index 96a9afea..9cc44194 100644 --- a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java +++ b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java @@ -60,6 +60,10 @@ public static String replaceParameters(String statement, Map par public static StatementExec replaceParameters( StatementExec statement, Map parameterValues) { + if (parameterValues == null || parameterValues.isEmpty()) { + // Nothing to do + return statement; + } return ImmutableStatementExec.of( statement.getId(), replaceParameters(statement.getStatement(), parameterValues)); } From 89cebc217d42468360383050f070b4ea1b4b5a55 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Thu, 31 Aug 2023 18:51:31 +0200 Subject: [PATCH 04/20] more bugfixing --- src/main/java/com/microsoft/lst_bench/util/StringUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java index 9cc44194..732e1138 100644 --- a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java +++ b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java @@ -65,7 +65,7 @@ public static StatementExec replaceParameters( return statement; } return ImmutableStatementExec.of( - statement.getId(), replaceParameters(statement.getStatement(), parameterValues)); + statement.getId(), StringUtils.format(statement.getStatement(), parameterValues)); } public static FileExec replaceParameters(FileExec file, Map parameterValues) { From 1b20723c9eda33064a3f1893aa16065c9adc5be7 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 1 Sep 2023 11:12:12 +0200 Subject: [PATCH 05/20] fix executor description and add debugging info --- .../common/ConcurrentPerfStresstestTaskExecutor.java | 7 +------ .../java/com/microsoft/lst_bench/util/StringUtils.java | 3 +++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java index bac7ba8e..1a01d8a8 100644 --- a/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java @@ -33,12 +33,7 @@ import org.slf4j.LoggerFactory; /** - * Custom task executor implementation that allows users to execute dependent tasks. We call a - * dependent task a task that iteratively executes a) a statement that is expected to return a - * result; and b) a statement repeatedly that is expected to use that result. The result of the - * first statement is stored in an intermediate object that can be specific to the connection. The - * expected object for a JDBC connection is of type List>, handling of other - * objects would need to be added to the if-clause that checks the instance of the object. + * Custom task executor implementation that allows users to execute concurrent tasks for specfic performance stress testing. This type of testing focuses on queries that a) get enhanced with additional joins (number specified by the user) and b) get augmented with query padding (empty characters) at the end of the query, if specified by the user. */ public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { diff --git a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java index 732e1138..9ddbec27 100644 --- a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java +++ b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java @@ -73,6 +73,9 @@ public static FileExec replaceParameters(FileExec file, Map para // Nothing to do return file; } + LOGGER.info("Trying to examine file: "); + LOGGER.info(file.toString()); + LOGGER.info(file.getId()); return ImmutableFileExec.of( file.getId(), file.getStatements().stream() From 2606e922f4af3e4309d5cfe43591d56b1613b76a Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 1 Sep 2023 11:23:02 +0200 Subject: [PATCH 06/20] spotless --- .../common/ConcurrentPerfStresstestTaskExecutor.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java index 1a01d8a8..1c711e17 100644 --- a/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java @@ -33,7 +33,10 @@ import org.slf4j.LoggerFactory; /** - * Custom task executor implementation that allows users to execute concurrent tasks for specfic performance stress testing. This type of testing focuses on queries that a) get enhanced with additional joins (number specified by the user) and b) get augmented with query padding (empty characters) at the end of the query, if specified by the user. + * Custom task executor implementation that allows users to execute concurrent tasks for specfic + * performance stress testing. This type of testing focuses on queries that a) get enhanced with + * additional joins (number specified by the user) and b) get augmented with query padding (empty + * characters) at the end of the query, if specified by the user. */ public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { From f95acd114515f3f8ee532f0db738ed21972adbb7 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 1 Sep 2023 11:33:25 +0200 Subject: [PATCH 07/20] more debugging --- src/main/java/com/microsoft/lst_bench/util/StringUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java index 9ddbec27..17f9c469 100644 --- a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java +++ b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java @@ -74,8 +74,8 @@ public static FileExec replaceParameters(FileExec file, Map para return file; } LOGGER.info("Trying to examine file: "); - LOGGER.info(file.toString()); LOGGER.info(file.getId()); + LOGGER.info("num statements: " + file.getStatements().size()); return ImmutableFileExec.of( file.getId(), file.getStatements().stream() From 46f47c76cf0f6fe84e73b57b25843855e170a192 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 1 Sep 2023 11:40:23 +0200 Subject: [PATCH 08/20] and even more debugging --- .../microsoft/lst_bench/input/BenchmarkObjectFactory.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java index 3c4aa86d..e48aec5d 100644 --- a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java +++ b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java @@ -43,10 +43,14 @@ import java.util.Map; import java.util.stream.Collectors; import org.apache.commons.lang3.ObjectUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** Factory class for creating benchmark objects from the input configuration. */ public class BenchmarkObjectFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(BenchmarkObjectFactory.class); + public static final String DEFAULT_ID_SEPARATOR = ";"; public static final String DEFAULT_ID_CONNECTOR = "_"; @@ -254,6 +258,7 @@ private static List createFileExecList( ImmutableFileExec.of( fileId, createStatementExecList(fileId, SQLParser.getStatements(file)))); } + LOGGER.info("Arraylist contains " + files.size() + " files."); files = applyPermutationOrder(taskTemplate, task, taskTemplateIdToPermuteOrderCounter, files); files = applyReplaceRegex(task, files); files = From 9d2f38c27c3e6b85abad0ff8e81ffdfd161ef6c9 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 1 Sep 2023 11:57:27 +0200 Subject: [PATCH 09/20] need more info --- .../com/microsoft/lst_bench/input/BenchmarkObjectFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java index e48aec5d..8266b50d 100644 --- a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java +++ b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java @@ -254,6 +254,7 @@ private static List createFileExecList( List files = new ArrayList<>(); for (String file : taskTemplate.getFiles()) { final String fileId = taskId + DEFAULT_ID_SEPARATOR + file; + LOGGER.info("adding file: " + fileId); files.add( ImmutableFileExec.of( fileId, createStatementExecList(fileId, SQLParser.getStatements(file)))); From 8c395c82f44ed5dda25c69dceacedea4d4623bc7 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 1 Sep 2023 12:20:05 +0200 Subject: [PATCH 10/20] bugfix --- .../input/BenchmarkObjectFactory.java | 43 +++++++++++++------ .../microsoft/lst_bench/util/StringUtils.java | 3 -- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java index 8266b50d..594c1a9e 100644 --- a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java +++ b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java @@ -15,6 +15,7 @@ */ package com.microsoft.lst_bench.input; +import com.microsoft.lst_bench.client.ClientException; import com.microsoft.lst_bench.client.ConnectionManager; import com.microsoft.lst_bench.client.JDBCConnectionManager; import com.microsoft.lst_bench.client.SparkConnectionManager; @@ -53,6 +54,7 @@ public class BenchmarkObjectFactory { public static final String DEFAULT_ID_SEPARATOR = ";"; public static final String DEFAULT_ID_CONNECTOR = "_"; + public static final String DEFAULT_FILE_SEPARATOR = "/"; private BenchmarkObjectFactory() { // Defeat instantiation @@ -102,9 +104,11 @@ private static SparkConnectionManager sparkConnectionManager( * @param taskLibrary the task library * @param workload the workload * @return a benchmark configuration + * @throws ClientException */ public static BenchmarkConfig benchmarkConfig( - ExperimentConfig experimentConfig, TaskLibrary taskLibrary, Workload workload) { + ExperimentConfig experimentConfig, TaskLibrary taskLibrary, Workload workload) + throws ClientException { Map idToTaskTemplate = parseTaskLibrary(taskLibrary); ImmutableWorkloadExec workloadExec = createWorkloadExec(workload, idToTaskTemplate, experimentConfig); @@ -141,12 +145,13 @@ private static Map parseTaskLibrary(TaskLibrary taskLibrar * @param idToTaskTemplate a map of task templates with unique IDs * @param experimentConfig the experiment configuration * @return a workload execution - * @throws IllegalArgumentException if the workload contains an invalid task template ID + * @throws ClientException */ private static ImmutableWorkloadExec createWorkloadExec( Workload workload, Map idToTaskTemplate, - ExperimentConfig experimentConfig) { + ExperimentConfig experimentConfig) + throws ClientException { Map taskTemplateIdToPermuteOrderCounter = new HashMap<>(); Map taskTemplateIdToParameterValuesCounter = new HashMap<>(); List phases = new ArrayList<>(); @@ -168,7 +173,8 @@ private static PhaseExec createPhaseExec( Map idToTaskTemplate, ExperimentConfig experimentConfig, Map taskTemplateIdToPermuteOrderCounter, - Map taskTemplateIdToParameterValuesCounter) { + Map taskTemplateIdToParameterValuesCounter) + throws ClientException { final String SESSION_PREFIX = "session"; List sessions = new ArrayList<>(); for (int i = 0; i < phase.getSessions().size(); i++) { @@ -199,7 +205,8 @@ private static SessionExec createSessionExec( Map idToTaskTemplate, ExperimentConfig experimentConfig, Map taskTemplateIdToPermuteOrderCounter, - Map taskTemplateIdToParameterValuesCounter) { + Map taskTemplateIdToParameterValuesCounter) + throws ClientException { List tasks = new ArrayList<>(); for (int i = 0; i < session.getTasks().size(); i++) { Task task = session.getTasks().get(i); @@ -225,7 +232,8 @@ private static TaskExec createTaskExec( Map idToTaskTemplate, ExperimentConfig experimentConfig, Map taskTemplateIdToPermuteOrderCounter, - Map taskTemplateIdToParameterValuesCounter) { + Map taskTemplateIdToParameterValuesCounter) + throws ClientException { TaskTemplate taskTemplate = idToTaskTemplate.get(task.getTemplateId()); if (taskTemplate == null) { throw new IllegalArgumentException("Unknown task template id: " + task.getTemplateId()); @@ -250,16 +258,15 @@ private static List createFileExecList( Task task, ExperimentConfig experimentConfig, Map taskTemplateIdToPermuteOrderCounter, - Map taskTemplateIdToParameterValuesCounter) { + Map taskTemplateIdToParameterValuesCounter) + throws ClientException { List files = new ArrayList<>(); for (String file : taskTemplate.getFiles()) { final String fileId = taskId + DEFAULT_ID_SEPARATOR + file; - LOGGER.info("adding file: " + fileId); files.add( ImmutableFileExec.of( fileId, createStatementExecList(fileId, SQLParser.getStatements(file)))); } - LOGGER.info("Arraylist contains " + files.size() + " files."); files = applyPermutationOrder(taskTemplate, task, taskTemplateIdToPermuteOrderCounter, files); files = applyReplaceRegex(task, files); files = @@ -284,14 +291,16 @@ private static List applyPermutationOrder( TaskTemplate taskTemplate, Task task, Map taskTemplateIdToPermuteOrderCounter, - List files) { + List files) + throws ClientException { if (taskTemplate.getPermutationOrdersDirectory() == null) { // Create statements with certain order return files; } - Map idToFile = new HashMap<>(); + Map nameToFile = new HashMap<>(); for (FileExec file : files) { - idToFile.put(file.getId(), file); + String[] fileNames = file.getId().split(DEFAULT_FILE_SEPARATOR); + nameToFile.put(fileNames[fileNames.length - 1], file); } int counter; if (Boolean.TRUE.equals(task.isPermuteOrder())) { @@ -305,7 +314,15 @@ private static List applyPermutationOrder( FileParser.getPermutationOrder(taskTemplate.getPermutationOrdersDirectory(), counter); List sortedFiles = new ArrayList<>(); for (String fileId : permutationOrder) { - sortedFiles.add(idToFile.get(fileId)); + if (!nameToFile.containsKey(fileId)) { + throw new ClientException( + "Could not find file " + + fileId + + " in file list: " + + nameToFile.toString() + + "; permutation of order unsuccessful."); + } + sortedFiles.add(nameToFile.get(fileId)); } return sortedFiles; } diff --git a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java index 17f9c469..732e1138 100644 --- a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java +++ b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java @@ -73,9 +73,6 @@ public static FileExec replaceParameters(FileExec file, Map para // Nothing to do return file; } - LOGGER.info("Trying to examine file: "); - LOGGER.info(file.getId()); - LOGGER.info("num statements: " + file.getStatements().size()); return ImmutableFileExec.of( file.getId(), file.getStatements().stream() From 0df499a18363b3d43b9f20bfa0cabff2f50ba597 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 8 Sep 2023 12:43:06 +0200 Subject: [PATCH 11/20] First round of comment fixes. --- .../lst_bench/task/TaskExecutor.java | 109 ++++++++++++++++ .../task/custom/DependentTaskExecutor.java | 118 ++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 src/main/java/com/microsoft/lst_bench/task/TaskExecutor.java create mode 100644 src/main/java/com/microsoft/lst_bench/task/custom/DependentTaskExecutor.java diff --git a/src/main/java/com/microsoft/lst_bench/task/TaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/TaskExecutor.java new file mode 100644 index 00000000..9ec72d0c --- /dev/null +++ b/src/main/java/com/microsoft/lst_bench/task/TaskExecutor.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.microsoft.lst_bench.task; + +import com.microsoft.lst_bench.client.ClientException; +import com.microsoft.lst_bench.client.Connection; +import com.microsoft.lst_bench.exec.FileExec; +import com.microsoft.lst_bench.exec.StatementExec; +import com.microsoft.lst_bench.exec.TaskExec; +import com.microsoft.lst_bench.telemetry.EventInfo; +import com.microsoft.lst_bench.telemetry.EventInfo.EventType; +import com.microsoft.lst_bench.telemetry.EventInfo.Status; +import com.microsoft.lst_bench.telemetry.ImmutableEventInfo; +import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; +import com.microsoft.lst_bench.util.StringUtils; +import java.time.Instant; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Default executor for tasks. Iterates over all files and all the statements contained in those + * files and executes them sequentially. + */ +public class TaskExecutor { + + private static final Logger LOGGER = LoggerFactory.getLogger(TaskExecutor.class); + + protected final SQLTelemetryRegistry telemetryRegistry; + protected final String experimentStartTime; + + public TaskExecutor(SQLTelemetryRegistry telemetryRegistry, String experimentStartTime) { + this.experimentStartTime = experimentStartTime; + this.telemetryRegistry = telemetryRegistry; + } + + public void executeTask(Connection connection, TaskExec task, Map values) + throws ClientException { + for (FileExec file : task.getFiles()) { + Instant fileStartTime = Instant.now(); + try { + for (StatementExec statement : file.getStatements()) { + Instant statementStartTime = Instant.now(); + try { + connection.execute(StringUtils.replaceParameters(statement, values).getStatement()); + } catch (Exception e) { + LOGGER.error("Exception executing statement: " + statement.getId()); + writeStatementEvent( + statementStartTime, + statement.getId(), + Status.FAILURE, + e.getMessage() + "; " + e.getStackTrace()); + throw e; + } + writeStatementEvent( + statementStartTime, statement.getId(), Status.SUCCESS, /* payload= */ null); + } + } catch (Exception e) { + LOGGER.error("Exception executing file: " + file.getId()); + writeFileEvent(fileStartTime, file.getId(), Status.FAILURE); + throw e; + } + writeFileEvent(fileStartTime, file.getId(), Status.SUCCESS); + } + } + + protected final EventInfo writeFileEvent(Instant startTime, String id, Status status) { + EventInfo eventInfo = + ImmutableEventInfo.of( + experimentStartTime, startTime, Instant.now(), id, EventType.EXEC_FILE, status); + telemetryRegistry.writeEvent(eventInfo); + return eventInfo; + } + + protected final EventInfo writeStatementEvent( + Instant startTime, String id, Status status, String payload) { + EventInfo eventInfo = null; + if (payload != null) { + eventInfo = + ImmutableEventInfo.of( + experimentStartTime, + startTime, + Instant.now(), + id, + EventType.EXEC_STATEMENT, + status) + .withPayload(payload); + } else { + eventInfo = + ImmutableEventInfo.of( + experimentStartTime, startTime, Instant.now(), id, EventType.EXEC_STATEMENT, status); + } + telemetryRegistry.writeEvent(eventInfo); + return eventInfo; + } +} diff --git a/src/main/java/com/microsoft/lst_bench/task/custom/DependentTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/DependentTaskExecutor.java new file mode 100644 index 00000000..6a240f3b --- /dev/null +++ b/src/main/java/com/microsoft/lst_bench/task/custom/DependentTaskExecutor.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.microsoft.lst_bench.task.custom; + +import com.microsoft.lst_bench.client.ClientException; +import com.microsoft.lst_bench.client.Connection; +import com.microsoft.lst_bench.client.QueryResult; +import com.microsoft.lst_bench.exec.FileExec; +import com.microsoft.lst_bench.exec.StatementExec; +import com.microsoft.lst_bench.exec.TaskExec; +import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; +import com.microsoft.lst_bench.telemetry.EventInfo.Status; +import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; +import com.microsoft.lst_bench.util.StringUtils; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Custom task executor implementation that allows users to execute dependent tasks. We call a + * dependent task a task that iteratively executes a) a statement that is expected to return a + * result; and b) a statement repeatedly that is expected to use that result. The result of the + * first statement is stored in an intermediate object that can be specific to the connection. The + * expected object for a JDBC connection is of type List>, handling of other + * objects would need to be added to the if-clause that checks the instance of the object. + */ +public class DependentTaskExecutor extends CustomTaskExecutor { + + private static final Logger LOGGER = LoggerFactory.getLogger(DependentTaskExecutor.class); + + private final int DEFAULT_BATCH_SIZE = 1; + + public DependentTaskExecutor( + SQLTelemetryRegistry telemetryRegistry, + String experimentStartTime, + CustomTaskExecutorArguments arguments) { + super(telemetryRegistry, experimentStartTime, arguments); + } + + @Override + public void executeTask(Connection connection, TaskExec task, Map values) + throws ClientException { + int batch_size; + if (this.getArguments() == null || this.getArguments().getDependentTaskBatchSize() == null) { + batch_size = DEFAULT_BATCH_SIZE; + } else { + batch_size = this.getArguments().getDependentTaskBatchSize().intValue(); + } + + QueryResult queryResult = null; + for (FileExec file : task.getFiles()) { + Instant fileStartTime = Instant.now(); + + if (file.getStatements().size() != 1) { + writeFileEvent(fileStartTime, file.getId(), Status.FAILURE); + throw new ClientException( + "For dependent task execution, statements have to be in separate files."); + } + + StatementExec statement = file.getStatements().get(0); + try { + if (queryResult == null) { + // Execute first query that retrieves the iterable input for the second query. + Instant statementStartTime = Instant.now(); + queryResult = + connection.executeQuery( + StringUtils.replaceParameters(statement, values).getStatement()); + writeStatementEvent( + statementStartTime, statement.getId(), Status.SUCCESS, /* payload= */ null); + if (queryResult == null || queryResult.containsEmptyResultColumnOnly()) { + // Reset queryResult variable if result is (intentionally) empty. + queryResult = null; + } + } else { + // Execute second query repeatedly with the parameters extracted from the first query. + Integer size = queryResult.getValueListSize(); + for (int j = 0; j < size; j += batch_size) { + int localMax = (j + batch_size) > size ? size : (j + batch_size); + Map localValues = new HashMap<>(values); + localValues.putAll(queryResult.getStringMappings(j, localMax)); + + Instant statementStartTime = Instant.now(); + connection.execute( + StringUtils.replaceParameters(statement, localValues).getStatement()); + writeStatementEvent( + statementStartTime, statement.getId(), Status.SUCCESS, /* payload= */ null); + } + // Reset query result. + queryResult = null; + } + } catch (Exception e) { + LOGGER.error("Exception executing file: " + file.getId()); + writeStatementEvent( + fileStartTime, + file.getId(), + Status.FAILURE, + /* payload= */ e.getMessage() + "; " + e.getStackTrace()); + throw e; + } + writeFileEvent(fileStartTime, file.getId(), Status.SUCCESS); + } + } +} From 3be88bb2e70dc36a93e524a938e02a72f59922cf Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 8 Sep 2023 12:43:17 +0200 Subject: [PATCH 12/20] First round of comment fixes. --- pom.xml | 10 +- .../common/DependentTaskExecutor.java | 118 ------------------ .../lst_bench/common/SessionExecutor.java | 7 +- .../lst_bench/common/TaskExecutor.java | 109 ---------------- .../input/BenchmarkObjectFactory.java | 6 +- .../ConcurrentPerfStresstestTaskExecutor.java | 3 +- .../custom}/CustomTaskExecutor.java | 3 +- .../wp1_longevity_trickle_1k_batches.yaml | 20 +-- .../config/spark/w_all_tpcds-delta.yaml | 2 +- .../config/spark/w_all_tpcds-hudi.yaml | 2 +- .../config/spark/w_all_tpcds-iceberg.yaml | 2 +- ...w_all_tpcds_single_session_jdbc-delta.yaml | 2 +- .../w_all_tpcds_single_session_jdbc-hudi.yaml | 2 +- ...all_tpcds_single_session_jdbc-iceberg.yaml | 2 +- .../config/sqlserver/w_perf_stresstest.yaml | 4 +- 15 files changed, 30 insertions(+), 262 deletions(-) delete mode 100644 src/main/java/com/microsoft/lst_bench/common/DependentTaskExecutor.java delete mode 100644 src/main/java/com/microsoft/lst_bench/common/TaskExecutor.java rename src/main/java/com/microsoft/lst_bench/{common => task/custom}/ConcurrentPerfStresstestTaskExecutor.java (98%) rename src/main/java/com/microsoft/lst_bench/{common => task/custom}/CustomTaskExecutor.java (95%) diff --git a/pom.xml b/pom.xml index 2e9d41c6..95d53f8e 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,11 @@ commons-cli 1.5.0 + + commons-io + commons-io + 2.13.0 + org.immutables value @@ -127,11 +132,6 @@ 1.1.0 test - - commons-io - commons-io - 2.13.0 - diff --git a/src/main/java/com/microsoft/lst_bench/common/DependentTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/common/DependentTaskExecutor.java deleted file mode 100644 index 06997dc0..00000000 --- a/src/main/java/com/microsoft/lst_bench/common/DependentTaskExecutor.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.microsoft.lst_bench.common; - -import com.microsoft.lst_bench.client.ClientException; -import com.microsoft.lst_bench.client.Connection; -import com.microsoft.lst_bench.client.QueryResult; -import com.microsoft.lst_bench.exec.FileExec; -import com.microsoft.lst_bench.exec.StatementExec; -import com.microsoft.lst_bench.exec.TaskExec; -import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; -import com.microsoft.lst_bench.telemetry.EventInfo.Status; -import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; -import com.microsoft.lst_bench.util.StringUtils; -import java.time.Instant; -import java.util.HashMap; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Custom task executor implementation that allows users to execute dependent tasks. We call a - * dependent task a task that iteratively executes a) a statement that is expected to return a - * result; and b) a statement repeatedly that is expected to use that result. The result of the - * first statement is stored in an intermediate object that can be specific to the connection. The - * expected object for a JDBC connection is of type List>, handling of other - * objects would need to be added to the if-clause that checks the instance of the object. - */ -public class DependentTaskExecutor extends CustomTaskExecutor { - - private static final Logger LOGGER = LoggerFactory.getLogger(DependentTaskExecutor.class); - - private final int DEFAULT_BATCH_SIZE = 1; - - public DependentTaskExecutor( - SQLTelemetryRegistry telemetryRegistry, - String experimentStartTime, - CustomTaskExecutorArguments arguments) { - super(telemetryRegistry, experimentStartTime, arguments); - } - - @Override - public void executeTask(Connection connection, TaskExec task, Map values) - throws ClientException { - int batch_size; - if (this.getArguments() == null || this.getArguments().getDependentTaskBatchSize() == null) { - batch_size = DEFAULT_BATCH_SIZE; - } else { - batch_size = this.getArguments().getDependentTaskBatchSize().intValue(); - } - - QueryResult queryResult = null; - for (FileExec file : task.getFiles()) { - Instant fileStartTime = Instant.now(); - - if (file.getStatements().size() != 1) { - writeFileEvent(fileStartTime, file.getId(), Status.FAILURE); - throw new ClientException( - "For dependent task execution, statements have to be in separate files."); - } - - StatementExec statement = file.getStatements().get(0); - try { - if (queryResult == null) { - // Execute first query that retrieves the iterable input for the second query. - Instant statementStartTime = Instant.now(); - queryResult = - connection.executeQuery( - StringUtils.replaceParameters(statement, values).getStatement()); - writeStatementEvent( - statementStartTime, statement.getId(), Status.SUCCESS, /* payload= */ null); - if (queryResult == null || queryResult.containsEmptyResultColumnOnly()) { - // Reset queryResult variable if result is (intentionally) empty. - queryResult = null; - } - } else { - // Execute second query repeatedly with the parameters extracted from the first query. - Integer size = queryResult.getValueListSize(); - for (int j = 0; j < size; j += batch_size) { - int localMax = (j + batch_size) > size ? size : (j + batch_size); - Map localValues = new HashMap<>(values); - localValues.putAll(queryResult.getStringMappings(j, localMax)); - - Instant statementStartTime = Instant.now(); - connection.execute( - StringUtils.replaceParameters(statement, localValues).getStatement()); - writeStatementEvent( - statementStartTime, statement.getId(), Status.SUCCESS, /* payload= */ null); - } - // Reset query result. - queryResult = null; - } - } catch (Exception e) { - LOGGER.error("Exception executing file: " + file.getId()); - writeStatementEvent( - fileStartTime, - file.getId(), - Status.FAILURE, - /* payload= */ e.getMessage() + "; " + e.getStackTrace()); - throw e; - } - writeFileEvent(fileStartTime, file.getId(), Status.SUCCESS); - } - } -} diff --git a/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java b/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java index 0e63f522..a906832e 100644 --- a/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java @@ -21,6 +21,7 @@ import com.microsoft.lst_bench.exec.SessionExec; import com.microsoft.lst_bench.exec.TaskExec; import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; +import com.microsoft.lst_bench.task.TaskExecutor; import com.microsoft.lst_bench.telemetry.EventInfo; import com.microsoft.lst_bench.telemetry.EventInfo.EventType; import com.microsoft.lst_bench.telemetry.EventInfo.Status; @@ -86,11 +87,7 @@ public Boolean call() throws ClientException { writeTaskEvent(taskStartTime, task.getId(), Status.SUCCESS); } } catch (Exception e) { - LOGGER.error( - "Exception executing session: " - + session.getId() - + ";" - + ExceptionUtils.getStackTrace(e)); + LOGGER.error("Exception executing session: " + session.getId()); writeSessionEvent(sessionStartTime, session.getId(), Status.FAILURE); throw e; } diff --git a/src/main/java/com/microsoft/lst_bench/common/TaskExecutor.java b/src/main/java/com/microsoft/lst_bench/common/TaskExecutor.java deleted file mode 100644 index bd417bf9..00000000 --- a/src/main/java/com/microsoft/lst_bench/common/TaskExecutor.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.microsoft.lst_bench.common; - -import com.microsoft.lst_bench.client.ClientException; -import com.microsoft.lst_bench.client.Connection; -import com.microsoft.lst_bench.exec.FileExec; -import com.microsoft.lst_bench.exec.StatementExec; -import com.microsoft.lst_bench.exec.TaskExec; -import com.microsoft.lst_bench.telemetry.EventInfo; -import com.microsoft.lst_bench.telemetry.EventInfo.EventType; -import com.microsoft.lst_bench.telemetry.EventInfo.Status; -import com.microsoft.lst_bench.telemetry.ImmutableEventInfo; -import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; -import com.microsoft.lst_bench.util.StringUtils; -import java.time.Instant; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Default executor for tasks. Iterates over all files and all the statements contained in those - * files and executes them sequentially. - */ -public class TaskExecutor { - - private static final Logger LOGGER = LoggerFactory.getLogger(TaskExecutor.class); - - protected final SQLTelemetryRegistry telemetryRegistry; - protected final String experimentStartTime; - - public TaskExecutor(SQLTelemetryRegistry telemetryRegistry, String experimentStartTime) { - this.experimentStartTime = experimentStartTime; - this.telemetryRegistry = telemetryRegistry; - } - - public void executeTask(Connection connection, TaskExec task, Map values) - throws ClientException { - for (FileExec file : task.getFiles()) { - Instant fileStartTime = Instant.now(); - try { - for (StatementExec statement : file.getStatements()) { - Instant statementStartTime = Instant.now(); - try { - connection.execute(StringUtils.replaceParameters(statement, values).getStatement()); - } catch (Exception e) { - LOGGER.error("Exception executing statement: " + statement.getId()); - writeStatementEvent( - statementStartTime, - statement.getId(), - Status.FAILURE, - e.getMessage() + "; " + e.getStackTrace()); - throw e; - } - writeStatementEvent( - statementStartTime, statement.getId(), Status.SUCCESS, /* payload= */ null); - } - } catch (Exception e) { - LOGGER.error("Exception executing file: " + file.getId()); - writeFileEvent(fileStartTime, file.getId(), Status.FAILURE); - throw e; - } - writeFileEvent(fileStartTime, file.getId(), Status.SUCCESS); - } - } - - protected final EventInfo writeFileEvent(Instant startTime, String id, Status status) { - EventInfo eventInfo = - ImmutableEventInfo.of( - experimentStartTime, startTime, Instant.now(), id, EventType.EXEC_FILE, status); - telemetryRegistry.writeEvent(eventInfo); - return eventInfo; - } - - protected final EventInfo writeStatementEvent( - Instant startTime, String id, Status status, String payload) { - EventInfo eventInfo = null; - if (payload != null) { - eventInfo = - ImmutableEventInfo.of( - experimentStartTime, - startTime, - Instant.now(), - id, - EventType.EXEC_STATEMENT, - status) - .withPayload(payload); - } else { - eventInfo = - ImmutableEventInfo.of( - experimentStartTime, startTime, Instant.now(), id, EventType.EXEC_STATEMENT, status); - } - telemetryRegistry.writeEvent(eventInfo); - return eventInfo; - } -} diff --git a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java index 594c1a9e..a1fe9c74 100644 --- a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java +++ b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java @@ -44,14 +44,10 @@ import java.util.Map; import java.util.stream.Collectors; import org.apache.commons.lang3.ObjectUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** Factory class for creating benchmark objects from the input configuration. */ public class BenchmarkObjectFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(BenchmarkObjectFactory.class); - public static final String DEFAULT_ID_SEPARATOR = ";"; public static final String DEFAULT_ID_CONNECTOR = "_"; public static final String DEFAULT_FILE_SEPARATOR = "/"; @@ -298,6 +294,8 @@ private static List applyPermutationOrder( return files; } Map nameToFile = new HashMap<>(); + // Per current convention, the id of a file is that of a task appended with the file path. + // Permutation order is referenced by file name, i.e., the last part of the file path. for (FileExec file : files) { String[] fileNames = file.getId().split(DEFAULT_FILE_SEPARATOR); nameToFile.put(fileNames[fileNames.length - 1], file); diff --git a/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java similarity index 98% rename from src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java rename to src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java index 1c711e17..e40c3b23 100644 --- a/src/main/java/com/microsoft/lst_bench/common/ConcurrentPerfStresstestTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.microsoft.lst_bench.common; +package com.microsoft.lst_bench.task.custom; import com.microsoft.lst_bench.client.ClientException; import com.microsoft.lst_bench.client.Connection; @@ -132,7 +132,6 @@ private void executeStatement( + statement.getId() + "; " + ExceptionUtils.getStackTrace(e); - LOGGER.error(error_msg); writeStatementEvent(statementStartTime, statement.getId(), Status.FAILURE, error_msg); throw new ClientException(error_msg); } diff --git a/src/main/java/com/microsoft/lst_bench/common/CustomTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/CustomTaskExecutor.java similarity index 95% rename from src/main/java/com/microsoft/lst_bench/common/CustomTaskExecutor.java rename to src/main/java/com/microsoft/lst_bench/task/custom/CustomTaskExecutor.java index 3268931a..8fbf1995 100644 --- a/src/main/java/com/microsoft/lst_bench/common/CustomTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/task/custom/CustomTaskExecutor.java @@ -13,12 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.microsoft.lst_bench.common; +package com.microsoft.lst_bench.task.custom; import com.microsoft.lst_bench.client.ClientException; import com.microsoft.lst_bench.client.Connection; import com.microsoft.lst_bench.exec.TaskExec; import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; +import com.microsoft.lst_bench.task.TaskExecutor; import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; import java.util.Map; diff --git a/src/main/resources/config/spark/tpcds/wp1_longevity_trickle_1k_batches.yaml b/src/main/resources/config/spark/tpcds/wp1_longevity_trickle_1k_batches.yaml index 9d13fb02..caeaee9e 100644 --- a/src/main/resources/config/spark/tpcds/wp1_longevity_trickle_1k_batches.yaml +++ b/src/main/resources/config/spark/tpcds/wp1_longevity_trickle_1k_batches.yaml @@ -36,11 +36,11 @@ phases: sessions: - tasks: - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - id: single_user_2 @@ -51,11 +51,11 @@ phases: sessions: - tasks: - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - id: single_user_3 @@ -66,11 +66,11 @@ phases: sessions: - tasks: - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - id: single_user_4 @@ -81,11 +81,11 @@ phases: sessions: - tasks: - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - id: single_user_5 @@ -96,11 +96,11 @@ phases: sessions: - tasks: - template_id: template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 1000 - id: single_user_6 diff --git a/src/test/resources/config/spark/w_all_tpcds-delta.yaml b/src/test/resources/config/spark/w_all_tpcds-delta.yaml index d057efea..4a0d35bb 100644 --- a/src/test/resources/config/spark/w_all_tpcds-delta.yaml +++ b/src/test/resources/config/spark/w_all_tpcds-delta.yaml @@ -31,7 +31,7 @@ phases: sessions: - tasks: - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 100 - id: optimize diff --git a/src/test/resources/config/spark/w_all_tpcds-hudi.yaml b/src/test/resources/config/spark/w_all_tpcds-hudi.yaml index 2e9307ac..cdad28d8 100644 --- a/src/test/resources/config/spark/w_all_tpcds-hudi.yaml +++ b/src/test/resources/config/spark/w_all_tpcds-hudi.yaml @@ -34,7 +34,7 @@ phases: sessions: - tasks: - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 100 - id: optimize diff --git a/src/test/resources/config/spark/w_all_tpcds-iceberg.yaml b/src/test/resources/config/spark/w_all_tpcds-iceberg.yaml index 6025973c..5b0ed8c0 100644 --- a/src/test/resources/config/spark/w_all_tpcds-iceberg.yaml +++ b/src/test/resources/config/spark/w_all_tpcds-iceberg.yaml @@ -31,7 +31,7 @@ phases: sessions: - tasks: - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor custom_task_executor_arguments: dependent_task_batch_size: 100 - id: optimize diff --git a/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-delta.yaml b/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-delta.yaml index fc580ee1..ef14c26d 100644 --- a/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-delta.yaml +++ b/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-delta.yaml @@ -13,5 +13,5 @@ phases: - template_id: single_user - template_id: data_maintenance_delta - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor - template_id: optimize_delta diff --git a/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-hudi.yaml b/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-hudi.yaml index f7a51282..6715e10e 100644 --- a/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-hudi.yaml +++ b/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-hudi.yaml @@ -16,5 +16,5 @@ phases: - template_id: single_user - template_id: data_maintenance_hudi - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor - template_id: optimize_hudi diff --git a/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-iceberg.yaml b/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-iceberg.yaml index 09c5e210..b304adf0 100644 --- a/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-iceberg.yaml +++ b/src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-iceberg.yaml @@ -13,5 +13,5 @@ phases: - template_id: single_user - template_id: data_maintenance_iceberg - template_id: data_maintenance_dependent - custom_task_executor: com.microsoft.lst_bench.common.DependentTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.DependentTaskExecutor - template_id: optimize_iceberg diff --git a/src/test/resources/config/sqlserver/w_perf_stresstest.yaml b/src/test/resources/config/sqlserver/w_perf_stresstest.yaml index 1e2ecda0..9d35e914 100644 --- a/src/test/resources/config/sqlserver/w_perf_stresstest.yaml +++ b/src/test/resources/config/sqlserver/w_perf_stresstest.yaml @@ -7,7 +7,7 @@ phases: sessions: - tasks: - template_id: base_query - custom_task_executor: com.microsoft.lst_bench.common.ConcurrentPerfStresstestTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.ConcurrentPerfStresstestTaskExecutor custom_task_executor_arguments: concurrent_task_num_joins: 5 duplicate_session: 5 @@ -15,6 +15,6 @@ phases: sessions: - tasks: - template_id: base_query - custom_task_executor: com.microsoft.lst_bench.common.ConcurrentPerfStresstestTaskExecutor + custom_task_executor: com.microsoft.lst_bench.task.custom.ConcurrentPerfStresstestTaskExecutor custom_task_executor_arguments: concurrent_task_min_query_length: 1000 \ No newline at end of file From c4ef1f77f7f97b26c08e7f0701d9006a7a451416 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Fri, 8 Sep 2023 12:47:32 +0200 Subject: [PATCH 13/20] Spotless --- .../java/com/microsoft/lst_bench/common/SessionExecutor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java b/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java index a906832e..8f753453 100644 --- a/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java @@ -35,7 +35,6 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From 353477079ad69cedf0c27e9fff9353e1ea8f91e7 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Mon, 11 Sep 2023 12:09:11 +0200 Subject: [PATCH 14/20] BOF identifier changes. --- .../microsoft/lst_bench/exec/FileExec.java | 2 + .../input/BenchmarkObjectFactory.java | 68 +++++++++++++------ 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/microsoft/lst_bench/exec/FileExec.java b/src/main/java/com/microsoft/lst_bench/exec/FileExec.java index a02f60e6..8158f1e2 100644 --- a/src/main/java/com/microsoft/lst_bench/exec/FileExec.java +++ b/src/main/java/com/microsoft/lst_bench/exec/FileExec.java @@ -25,5 +25,7 @@ public interface FileExec { String getId(); + String getName(); + List getStatements(); } diff --git a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java index a1fe9c74..b807bbdc 100644 --- a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java +++ b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java @@ -45,7 +45,14 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.ObjectUtils; -/** Factory class for creating benchmark objects from the input configuration. */ +/** + * Factory class for creating benchmark objects from the input configuration. + * + *

Per convention, the identifiers for each phase, session, task, file, and statement are + * hierarchically constructed. For example, task template 'test-task' that is only task in phase + * 'test-phase' which only has a single session will be identified as + * test-phase;session-0;test-task-0. + */ public class BenchmarkObjectFactory { public static final String DEFAULT_ID_SEPARATOR = ";"; @@ -171,19 +178,13 @@ private static PhaseExec createPhaseExec( Map taskTemplateIdToPermuteOrderCounter, Map taskTemplateIdToParameterValuesCounter) throws ClientException { - final String SESSION_PREFIX = "session"; List sessions = new ArrayList<>(); for (int i = 0; i < phase.getSessions().size(); i++) { Session session = phase.getSessions().get(i); for (int j = 0; j <= session.getDuplicateSession(); j++) { - String sessionId = - phase.getId() + DEFAULT_ID_SEPARATOR + SESSION_PREFIX + DEFAULT_ID_CONNECTOR + i; - if (j > 0) { - sessionId += DEFAULT_ID_CONNECTOR + j; - } SessionExec sessionExec = createSessionExec( - sessionId, + createSessionId(phase.getId(), i, j), session, idToTaskTemplate, experimentConfig, @@ -195,6 +196,16 @@ private static PhaseExec createPhaseExec( return ImmutablePhaseExec.of(phase.getId(), sessions); } + private static String createSessionId(String phaseId, int number, int duplicate_number) { + final String SESSION_PREFIX = "session"; + String sessionId = + phaseId + DEFAULT_ID_SEPARATOR + SESSION_PREFIX + DEFAULT_ID_CONNECTOR + number; + if (duplicate_number > 0) { + sessionId += DEFAULT_ID_CONNECTOR + duplicate_number; + } + return sessionId; + } + private static SessionExec createSessionExec( String sessionId, Session session, @@ -206,11 +217,9 @@ private static SessionExec createSessionExec( List tasks = new ArrayList<>(); for (int i = 0; i < session.getTasks().size(); i++) { Task task = session.getTasks().get(i); - String taskId = - sessionId + DEFAULT_ID_SEPARATOR + task.getTemplateId() + DEFAULT_ID_CONNECTOR + i; TaskExec taskExec = createTaskExec( - taskId, + createTaskId(sessionId, task.getTemplateId(), i), task, idToTaskTemplate, experimentConfig, @@ -222,6 +231,10 @@ private static SessionExec createSessionExec( sessionId, tasks, ObjectUtils.defaultIfNull(session.getTargetEndpoint(), 0)); } + private static String createTaskId(String sessionId, String templateId, int number) { + return sessionId + DEFAULT_ID_SEPARATOR + templateId + DEFAULT_ID_CONNECTOR + number; + } + private static TaskExec createTaskExec( String taskId, Task task, @@ -258,10 +271,12 @@ private static List createFileExecList( throws ClientException { List files = new ArrayList<>(); for (String file : taskTemplate.getFiles()) { - final String fileId = taskId + DEFAULT_ID_SEPARATOR + file; + final String fileId = createFileId(taskId, file); files.add( ImmutableFileExec.of( - fileId, createStatementExecList(fileId, SQLParser.getStatements(file)))); + fileId, + createFileName(file), + createStatementExecList(fileId, SQLParser.getStatements(file)))); } files = applyPermutationOrder(taskTemplate, task, taskTemplateIdToPermuteOrderCounter, files); files = applyReplaceRegex(task, files); @@ -271,18 +286,30 @@ private static List createFileExecList( return files; } + private static String createFileId(String taskId, String filePath) { + return taskId + DEFAULT_ID_SEPARATOR + filePath; + } + + private static String createFileName(String filePath) { + String[] fileNames = filePath.split(DEFAULT_FILE_SEPARATOR); + return fileNames[fileNames.length - 1]; + } + private static List createStatementExecList( String fileId, List statements) { List statement_execs = new ArrayList<>(); - final String STATEMENT_PREFIX = "statement"; for (int i = 0; i < statements.size(); i++) { - String statementId = - fileId + DEFAULT_ID_SEPARATOR + STATEMENT_PREFIX + DEFAULT_ID_CONNECTOR + i; - statement_execs.add(ImmutableStatementExec.of(statementId, statements.get(i))); + statement_execs.add( + ImmutableStatementExec.of(createStatementId(fileId, i), statements.get(i))); } return statement_execs; } + private static String createStatementId(String fileId, int number) { + final String STATEMENT_PREFIX = "statement"; + return fileId + DEFAULT_ID_SEPARATOR + STATEMENT_PREFIX + DEFAULT_ID_CONNECTOR + number; + } + private static List applyPermutationOrder( TaskTemplate taskTemplate, Task task, @@ -294,11 +321,10 @@ private static List applyPermutationOrder( return files; } Map nameToFile = new HashMap<>(); - // Per current convention, the id of a file is that of a task appended with the file path. - // Permutation order is referenced by file name, i.e., the last part of the file path. + // The permutation order is identified by file name, i.e., the last part of the file path, as + // per current convention. for (FileExec file : files) { - String[] fileNames = file.getId().split(DEFAULT_FILE_SEPARATOR); - nameToFile.put(fileNames[fileNames.length - 1], file); + nameToFile.put(file.getName(), file); } int counter; if (Boolean.TRUE.equals(task.isPermuteOrder())) { From 6f573a8a949486680eb0a4c530352656ddf76d59 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Mon, 11 Sep 2023 12:13:10 +0200 Subject: [PATCH 15/20] Replace 'duplicate_sessions' with 'num_instances'. --- .../microsoft/lst_bench/input/BenchmarkObjectFactory.java | 8 ++++---- src/main/java/com/microsoft/lst_bench/input/Session.java | 6 +++--- src/main/resources/schemas/workload.json | 6 +++--- .../java/com/microsoft/lst_bench/input/ParserTest.java | 4 ++-- .../resources/config/sqlserver/w_perf_stresstest.yaml | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java index b807bbdc..98d9d0d1 100644 --- a/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java +++ b/src/main/java/com/microsoft/lst_bench/input/BenchmarkObjectFactory.java @@ -181,7 +181,7 @@ private static PhaseExec createPhaseExec( List sessions = new ArrayList<>(); for (int i = 0; i < phase.getSessions().size(); i++) { Session session = phase.getSessions().get(i); - for (int j = 0; j <= session.getDuplicateSession(); j++) { + for (int j = 1; j <= session.getNumInstances(); j++) { SessionExec sessionExec = createSessionExec( createSessionId(phase.getId(), i, j), @@ -196,12 +196,12 @@ private static PhaseExec createPhaseExec( return ImmutablePhaseExec.of(phase.getId(), sessions); } - private static String createSessionId(String phaseId, int number, int duplicate_number) { + private static String createSessionId(String phaseId, int number, int numInstances) { final String SESSION_PREFIX = "session"; String sessionId = phaseId + DEFAULT_ID_SEPARATOR + SESSION_PREFIX + DEFAULT_ID_CONNECTOR + number; - if (duplicate_number > 0) { - sessionId += DEFAULT_ID_CONNECTOR + duplicate_number; + if (numInstances > 1) { + sessionId += DEFAULT_ID_CONNECTOR + numInstances; } return sessionId; } diff --git a/src/main/java/com/microsoft/lst_bench/input/Session.java b/src/main/java/com/microsoft/lst_bench/input/Session.java index 175fc958..52b2395c 100644 --- a/src/main/java/com/microsoft/lst_bench/input/Session.java +++ b/src/main/java/com/microsoft/lst_bench/input/Session.java @@ -35,9 +35,9 @@ public interface Session { @JsonProperty("target_endpoint") @Nullable Integer getTargetEndpoint(); - @JsonProperty("duplicate_session") + @JsonProperty("num_instances") @Value.Default - default int getDuplicateSession() { - return 0; + default int getNumInstances() { + return 1; } } diff --git a/src/main/resources/schemas/workload.json b/src/main/resources/schemas/workload.json index fa2dacab..8376efc1 100644 --- a/src/main/resources/schemas/workload.json +++ b/src/main/resources/schemas/workload.json @@ -110,10 +110,10 @@ "title": "Target endpoint index (default: 0)", "description": "The positional index (starting from 0) of the connection manager within the connections configuration file" }, - "duplicate_session": { + "num_instances": { "type": "integer", - "title": "Duplication count for this session", - "description": "Determines how often a session will be duplicated; total session count is duplicate_session + 1 (default: 0)" + "title": "Number of instances for this session", + "description": "Determines how often a session will be instantiated (default: 1)" } } } diff --git a/src/test/java/com/microsoft/lst_bench/input/ParserTest.java b/src/test/java/com/microsoft/lst_bench/input/ParserTest.java index 6b128eea..2ce17df1 100644 --- a/src/test/java/com/microsoft/lst_bench/input/ParserTest.java +++ b/src/test/java/com/microsoft/lst_bench/input/ParserTest.java @@ -496,7 +496,7 @@ public void testParseWP3RWConcurrencyMulti() throws IOException { List tasksDM = sessions.get(1).getTasks(); Assertions.assertEquals(2, tasksDM.size()); Assertions.assertEquals(1, sessions.get(1).getTargetEndpoint()); - Assertions.assertEquals(0, sessions.get(1).getDuplicateSession()); + Assertions.assertEquals(1, sessions.get(1).getNumInstances()); } break; case "single_user_2_optimize_1": @@ -506,7 +506,7 @@ public void testParseWP3RWConcurrencyMulti() throws IOException { List tasksO = sessions.get(1).getTasks(); Assertions.assertEquals(1, tasksO.size()); Assertions.assertEquals(1, sessions.get(1).getTargetEndpoint()); - Assertions.assertEquals(0, sessions.get(1).getDuplicateSession()); + Assertions.assertEquals(1, sessions.get(1).getNumInstances()); } break; case "setup": diff --git a/src/test/resources/config/sqlserver/w_perf_stresstest.yaml b/src/test/resources/config/sqlserver/w_perf_stresstest.yaml index 9d35e914..7e7d0a21 100644 --- a/src/test/resources/config/sqlserver/w_perf_stresstest.yaml +++ b/src/test/resources/config/sqlserver/w_perf_stresstest.yaml @@ -10,7 +10,7 @@ phases: custom_task_executor: com.microsoft.lst_bench.task.custom.ConcurrentPerfStresstestTaskExecutor custom_task_executor_arguments: concurrent_task_num_joins: 5 - duplicate_session: 5 + num_instances: 5 - id: query_execution_2 sessions: - tasks: From be4e316c15109e83024cbc2b98897f59e1a22d30 Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Mon, 11 Sep 2023 12:41:59 +0200 Subject: [PATCH 16/20] Modify custom task executor arguments. --- .../lst_bench/common/SessionExecutor.java | 4 +-- .../microsoft/lst_bench/exec/TaskExec.java | 4 +-- .../com/microsoft/lst_bench/input/Task.java | 23 ++------------- .../ConcurrentPerfStresstestTaskExecutor.java | 29 +++++++++++++++---- .../task/custom/CustomTaskExecutor.java | 7 ++--- .../task/custom/DependentTaskExecutor.java | 23 ++++++++------- .../microsoft/lst_bench/util/StringUtils.java | 8 +++-- src/main/resources/schemas/workload.json | 19 +----------- 8 files changed, 49 insertions(+), 68 deletions(-) diff --git a/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java b/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java index 8f753453..99a62854 100644 --- a/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/common/SessionExecutor.java @@ -20,7 +20,6 @@ import com.microsoft.lst_bench.client.ConnectionManager; import com.microsoft.lst_bench.exec.SessionExec; import com.microsoft.lst_bench.exec.TaskExec; -import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; import com.microsoft.lst_bench.task.TaskExecutor; import com.microsoft.lst_bench.telemetry.EventInfo; import com.microsoft.lst_bench.telemetry.EventInfo.EventType; @@ -121,8 +120,7 @@ private TaskExecutor getTaskExecutor(TaskExec task) { try { Constructor constructor = Class.forName(task.getCustomTaskExecutor()) - .getDeclaredConstructor( - SQLTelemetryRegistry.class, String.class, CustomTaskExecutorArguments.class); + .getDeclaredConstructor(SQLTelemetryRegistry.class, String.class, Map.class); return (TaskExecutor) constructor.newInstance( this.telemetryRegistry, diff --git a/src/main/java/com/microsoft/lst_bench/exec/TaskExec.java b/src/main/java/com/microsoft/lst_bench/exec/TaskExec.java index 5abf0ed9..bfc2883b 100644 --- a/src/main/java/com/microsoft/lst_bench/exec/TaskExec.java +++ b/src/main/java/com/microsoft/lst_bench/exec/TaskExec.java @@ -15,8 +15,8 @@ */ package com.microsoft.lst_bench.exec; -import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; import java.util.List; +import java.util.Map; import javax.annotation.Nullable; import org.immutables.value.Value; @@ -36,5 +36,5 @@ public interface TaskExec { @Nullable String getCustomTaskExecutor(); @Value.Parameter(false) - @Nullable CustomTaskExecutorArguments getCustomTaskExecutorArguments(); + @Nullable Map getCustomTaskExecutorArguments(); } diff --git a/src/main/java/com/microsoft/lst_bench/input/Task.java b/src/main/java/com/microsoft/lst_bench/input/Task.java index a074bfdd..0f267e61 100644 --- a/src/main/java/com/microsoft/lst_bench/input/Task.java +++ b/src/main/java/com/microsoft/lst_bench/input/Task.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.List; +import java.util.Map; import javax.annotation.Nullable; import org.immutables.value.Value; @@ -43,27 +44,7 @@ public interface Task { @Nullable String getCustomTaskExecutor(); @JsonProperty("custom_task_executor_arguments") - @Nullable CustomTaskExecutorArguments getCustomTaskExecutorArguments(); - - @Value.Immutable - @JsonSerialize(as = ImmutableCustomTaskExecutorArguments.class) - @JsonDeserialize(as = ImmutableCustomTaskExecutorArguments.class) - interface CustomTaskExecutorArguments { - @JsonProperty("dependent_task_batch_size") - @Nullable Integer getDependentTaskBatchSize(); - - @JsonProperty("concurrent_task_num_joins") - @Value.Default - default int getConcurrentTaskNumJoins() { - return 0; - } - - @JsonProperty("concurrent_task_min_query_length") - @Value.Default - default int getConcurrentTaskMinQueryLength() { - return 0; - } - } + @Nullable Map getCustomTaskExecutorArguments(); @JsonProperty("replace_regex") @Nullable List getReplaceRegex(); diff --git a/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java index e40c3b23..e69aa4cd 100644 --- a/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java @@ -22,7 +22,6 @@ import com.microsoft.lst_bench.exec.StatementExec; import com.microsoft.lst_bench.exec.TaskExec; import com.microsoft.lst_bench.input.BenchmarkObjectFactory; -import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; import com.microsoft.lst_bench.telemetry.EventInfo.Status; import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; import com.microsoft.lst_bench.util.StringUtils; @@ -36,26 +35,44 @@ * Custom task executor implementation that allows users to execute concurrent tasks for specfic * performance stress testing. This type of testing focuses on queries that a) get enhanced with * additional joins (number specified by the user) and b) get augmented with query padding (empty - * characters) at the end of the query, if specified by the user. + * characters) at the end of the query, if specified by the user. These properties are defined via + * the 'custom_task_executor_arguments' property that are part of the workload configuration. Valid + * parameter names are 'concurrent_task_num_joins' and 'concurrent_task_min_query_length'. */ public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(ConcurrentPerfStresstestTaskExecutor.class); + private final int DEFAULT_CONCURRENT_TASK_NUM_JOINS = 0; + private final int DEFAULT_CONCURRENT_TASK_MIN_QUERY_LENGTH = 0; + private final String CONCURRENT_TASK_NUM_JOINS = "concurrent_task_num_joins"; + private final String CONCURRENT_TASK_MIN_QUERY_LENGTH = "concurrent_task_min_query_length"; + public ConcurrentPerfStresstestTaskExecutor( SQLTelemetryRegistry telemetryRegistry, String experimentStartTime, - CustomTaskExecutorArguments arguments) { + Map arguments) { super(telemetryRegistry, experimentStartTime, arguments); } @Override public void executeTask(Connection connection, TaskExec task, Map values) throws ClientException { - // Will never be null since they are set to default values. - int numJoins = this.getArguments().getConcurrentTaskNumJoins(); - int minQueryLength = this.getArguments().getConcurrentTaskMinQueryLength(); + // Set default values. + int numJoins; + if (this.getArguments() == null || this.getArguments().get(CONCURRENT_TASK_NUM_JOINS) == null) { + numJoins = DEFAULT_CONCURRENT_TASK_NUM_JOINS; + } else { + numJoins = Integer.valueOf(this.getArguments().get(CONCURRENT_TASK_NUM_JOINS)); + } + int minQueryLength; + if (this.getArguments() == null + || this.getArguments().get(CONCURRENT_TASK_MIN_QUERY_LENGTH) == null) { + minQueryLength = DEFAULT_CONCURRENT_TASK_MIN_QUERY_LENGTH; + } else { + minQueryLength = Integer.valueOf(this.getArguments().get(CONCURRENT_TASK_MIN_QUERY_LENGTH)); + } for (FileExec file : task.getFiles()) { Instant fileStartTime = Instant.now(); diff --git a/src/main/java/com/microsoft/lst_bench/task/custom/CustomTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/CustomTaskExecutor.java index 8fbf1995..cbe222b4 100644 --- a/src/main/java/com/microsoft/lst_bench/task/custom/CustomTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/task/custom/CustomTaskExecutor.java @@ -18,7 +18,6 @@ import com.microsoft.lst_bench.client.ClientException; import com.microsoft.lst_bench.client.Connection; import com.microsoft.lst_bench.exec.TaskExec; -import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; import com.microsoft.lst_bench.task.TaskExecutor; import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; import java.util.Map; @@ -33,12 +32,12 @@ */ public class CustomTaskExecutor extends TaskExecutor { - protected final CustomTaskExecutorArguments arguments; + protected final Map arguments; public CustomTaskExecutor( SQLTelemetryRegistry telemetryRegistry, String experimentStartTime, - CustomTaskExecutorArguments arguments) { + Map arguments) { super(telemetryRegistry, experimentStartTime); this.arguments = arguments; } @@ -49,7 +48,7 @@ public void executeTask(Connection connection, TaskExec task, Map getArguments() { return this.arguments; } } diff --git a/src/main/java/com/microsoft/lst_bench/task/custom/DependentTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/DependentTaskExecutor.java index 6a240f3b..bb5b243f 100644 --- a/src/main/java/com/microsoft/lst_bench/task/custom/DependentTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/task/custom/DependentTaskExecutor.java @@ -21,7 +21,6 @@ import com.microsoft.lst_bench.exec.FileExec; import com.microsoft.lst_bench.exec.StatementExec; import com.microsoft.lst_bench.exec.TaskExec; -import com.microsoft.lst_bench.input.Task.CustomTaskExecutorArguments; import com.microsoft.lst_bench.telemetry.EventInfo.Status; import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; import com.microsoft.lst_bench.util.StringUtils; @@ -35,31 +34,33 @@ * Custom task executor implementation that allows users to execute dependent tasks. We call a * dependent task a task that iteratively executes a) a statement that is expected to return a * result; and b) a statement repeatedly that is expected to use that result. The result of the - * first statement is stored in an intermediate object that can be specific to the connection. The - * expected object for a JDBC connection is of type List>, handling of other - * objects would need to be added to the if-clause that checks the instance of the object. + * first statement is stored in a QueryResult object which is then used and interpreted by the + * second statement. For this task executor, we allow the second statement to be executed in + * batches. The batch size can be set via the 'custom_task_executor_arguments' property that is part + * of the workload configuration. The parameter name is 'dependent_task_batch_size'. */ public class DependentTaskExecutor extends CustomTaskExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(DependentTaskExecutor.class); private final int DEFAULT_BATCH_SIZE = 1; + private final String DEPENDENT_TASK_BATCH_SIZE = "dependent_task_batch_size"; public DependentTaskExecutor( SQLTelemetryRegistry telemetryRegistry, String experimentStartTime, - CustomTaskExecutorArguments arguments) { + Map arguments) { super(telemetryRegistry, experimentStartTime, arguments); } @Override public void executeTask(Connection connection, TaskExec task, Map values) throws ClientException { - int batch_size; - if (this.getArguments() == null || this.getArguments().getDependentTaskBatchSize() == null) { - batch_size = DEFAULT_BATCH_SIZE; + int batchSize; + if (this.getArguments() == null || this.getArguments().get(DEPENDENT_TASK_BATCH_SIZE) == null) { + batchSize = DEFAULT_BATCH_SIZE; } else { - batch_size = this.getArguments().getDependentTaskBatchSize().intValue(); + batchSize = Integer.valueOf(this.getArguments().get(DEPENDENT_TASK_BATCH_SIZE)); } QueryResult queryResult = null; @@ -89,8 +90,8 @@ public void executeTask(Connection connection, TaskExec task, Map size ? size : (j + batch_size); + for (int j = 0; j < size; j += batchSize) { + int localMax = (j + batchSize) > size ? size : (j + batchSize); Map localValues = new HashMap<>(values); localValues.putAll(queryResult.getStringMappings(j, localMax)); diff --git a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java index 732e1138..9a0650cd 100644 --- a/src/main/java/com/microsoft/lst_bench/util/StringUtils.java +++ b/src/main/java/com/microsoft/lst_bench/util/StringUtils.java @@ -75,16 +75,18 @@ public static FileExec replaceParameters(FileExec file, Map para } return ImmutableFileExec.of( file.getId(), + file.getName(), file.getStatements().stream() .map(s -> replaceParameters(s, parameterValues)) .collect(Collectors.toList())); } - public static FileExec replaceRegex(FileExec f, String regex, String replacement) { + public static FileExec replaceRegex(FileExec file, String regex, String replacement) { Pattern pattern = Pattern.compile(regex); return ImmutableFileExec.of( - f.getId(), - f.getStatements().stream() + file.getId(), + file.getName(), + file.getStatements().stream() .map( s -> ImmutableStatementExec.of( diff --git a/src/main/resources/schemas/workload.json b/src/main/resources/schemas/workload.json index 8376efc1..1f84066b 100644 --- a/src/main/resources/schemas/workload.json +++ b/src/main/resources/schemas/workload.json @@ -63,24 +63,7 @@ "custom_task_executor_arguments": { "type": "object", "title": "Custom task executor arguments", - "description": "Any arguments passed to a custom executor need to be defined here.", - "properties": { - "dependent_task_batch_size": { - "type": "integer", - "title": "Batch size for DependentTaskExecutor", - "description": "Sets the batch size for a task executed; specific to the DependentTaskExecutor class" - }, - "concurrent_task_num_joins": { - "type": "integer", - "title": "List of number of joins that are to be tested", - "description": "Determines how the query will be extended with the number of joins" - }, - "concurrent_task_min_query_length": { - "type": "integer", - "title": "List of minimum query lengths that are to be tested", - "description": "Determines how the query will be extended with padding if the minimum query length is not exceeded" - } - } + "description": "Any arguments passed to a custom executor need to be defined here." }, "replace_regex": { "type": "array", From a0cf2608eae48c9267425d8655d8b91176265fda Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Mon, 11 Sep 2023 14:11:13 +0200 Subject: [PATCH 17/20] Pattern matching for stress test query. --- .../ConcurrentPerfStresstestTaskExecutor.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java index e69aa4cd..b86c3a8e 100644 --- a/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java @@ -27,6 +27,7 @@ import com.microsoft.lst_bench.util.StringUtils; import java.time.Instant; import java.util.Map; +import java.util.regex.Pattern; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,8 +36,10 @@ * Custom task executor implementation that allows users to execute concurrent tasks for specfic * performance stress testing. This type of testing focuses on queries that a) get enhanced with * additional joins (number specified by the user) and b) get augmented with query padding (empty - * characters) at the end of the query, if specified by the user. These properties are defined via - * the 'custom_task_executor_arguments' property that are part of the workload configuration. Valid + * characters) at the end of the query, if specified by the user. This augmentation requires a + * specific query of the form "SELECT ... FROM ..." without additional clauses such as "WHERE" or + * "ORDER" to allow for join extensions. The properties of this class are defined via the + * 'custom_task_executor_arguments' property that are part of the workload configuration. Valid * parameter names are 'concurrent_task_num_joins' and 'concurrent_task_min_query_length'. */ public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { @@ -49,6 +52,9 @@ public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { private final String CONCURRENT_TASK_NUM_JOINS = "concurrent_task_num_joins"; private final String CONCURRENT_TASK_MIN_QUERY_LENGTH = "concurrent_task_min_query_length"; + private final Pattern WHERE_PATTERN = Pattern.compile("WHERE|where|Where"); + private final Pattern ORDER_PATTERN = Pattern.compile("ORDER|order|Order"); + public ConcurrentPerfStresstestTaskExecutor( SQLTelemetryRegistry telemetryRegistry, String experimentStartTime, @@ -83,14 +89,14 @@ public void executeTask(Connection connection, TaskExec task, Map Date: Mon, 11 Sep 2023 14:19:05 +0200 Subject: [PATCH 18/20] Modify separator/connector in CPSTExecutor --- .../ConcurrentPerfStresstestTaskExecutor.java | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java index b86c3a8e..80c03371 100644 --- a/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java @@ -21,7 +21,6 @@ import com.microsoft.lst_bench.exec.ImmutableStatementExec; import com.microsoft.lst_bench.exec.StatementExec; import com.microsoft.lst_bench.exec.TaskExec; -import com.microsoft.lst_bench.input.BenchmarkObjectFactory; import com.microsoft.lst_bench.telemetry.EventInfo.Status; import com.microsoft.lst_bench.telemetry.SQLTelemetryRegistry; import com.microsoft.lst_bench.util.StringUtils; @@ -40,7 +39,10 @@ * specific query of the form "SELECT ... FROM ..." without additional clauses such as "WHERE" or * "ORDER" to allow for join extensions. The properties of this class are defined via the * 'custom_task_executor_arguments' property that are part of the workload configuration. Valid - * parameter names are 'concurrent_task_num_joins' and 'concurrent_task_min_query_length'. + * parameter names are 'concurrent_task_num_joins' and 'concurrent_task_min_query_length', their + * defaults are set to '0'. The user may further choose to specify parameters + * 'concurrent_id_separator' and 'concurrent_id_connector' which are used to build the id of the + * newly generated queries. The default for these parameters is set to ';' resp. '-'. */ public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { @@ -51,6 +53,10 @@ public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { private final int DEFAULT_CONCURRENT_TASK_MIN_QUERY_LENGTH = 0; private final String CONCURRENT_TASK_NUM_JOINS = "concurrent_task_num_joins"; private final String CONCURRENT_TASK_MIN_QUERY_LENGTH = "concurrent_task_min_query_length"; + private final String DEFAULT_CONCURRENT_ID_SEPARATOR = ";"; + private final String DEFAULT_CONCURRENT_ID_CONNECTOR = "-"; + private final String CONCURRENT_ID_SEPARATOR = "concurrent_id_separator"; + private final String CONCURRENT_ID_CONNECTOR = "concurrent_id_connector"; private final Pattern WHERE_PATTERN = Pattern.compile("WHERE|where|Where"); private final Pattern ORDER_PATTERN = Pattern.compile("ORDER|order|Order"); @@ -126,10 +132,10 @@ public void executeTask(Connection connection, TaskExec task, Map Date: Mon, 11 Sep 2023 14:59:57 +0200 Subject: [PATCH 19/20] First draft for Spark CI test. --- .../microsoft/lst_bench/DriverSparkTest.java | 13 ++++++++++ .../conc_perf_stresstest_task_library.yaml | 12 ++++++++++ .../config/spark/w_perf_stresstest.yaml | 24 +++++++++++++++++++ .../config/sqlserver/w_perf_stresstest.yaml | 2 +- .../scripts/spark/perf_stresstest.sql | 1 + .../scripts/sqlserver/perf_stresstest.sql | 2 +- 6 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/test/resources/config/spark/conc_perf_stresstest_task_library.yaml create mode 100644 src/test/resources/config/spark/w_perf_stresstest.yaml create mode 100644 src/test/resources/scripts/spark/perf_stresstest.sql diff --git a/src/test/java/com/microsoft/lst_bench/DriverSparkTest.java b/src/test/java/com/microsoft/lst_bench/DriverSparkTest.java index 261ee5ba..a4843c4a 100644 --- a/src/test/java/com/microsoft/lst_bench/DriverSparkTest.java +++ b/src/test/java/com/microsoft/lst_bench/DriverSparkTest.java @@ -181,6 +181,19 @@ public void testJDBCSessionIceberg() throws Exception { "src/test/resources/config/spark/w_all_tpcds_single_session_jdbc-iceberg.yaml"); } + /* TODO: Replace eventually with SQL Server version, once CI pipeline has been established. */ + @Test + @EnabledIfSystemProperty(named = "lst-bench.test.lst", matches = "delta") + @EnabledIfSystemProperty(named = "lst-bench.test.connection", matches = "jdbc") + public void testJDBCConcurrentPerfStresstest() throws Exception { + runDriver( + "src/test/resources/config/spark/jdbc_connection_config.yaml", + "src/test/resources/config/spark/experiment_config-delta.yaml", + "src/test/resources/config/spark/telemetry_config.yaml", + "src/test/resources/config/spark/conc_perf_stresstest_task_library.yaml", + "src/test/resources/config/spark/w_perf_stresstest.yaml"); + } + private void runDriver(String arg0, String arg1, String arg2, String arg3, String arg4) throws Exception { Driver.main(new String[] {"-c", arg0, "-e", arg1, "-t", arg2, "-l", arg3, "-w", arg4}); diff --git a/src/test/resources/config/spark/conc_perf_stresstest_task_library.yaml b/src/test/resources/config/spark/conc_perf_stresstest_task_library.yaml new file mode 100644 index 00000000..64a9e6d0 --- /dev/null +++ b/src/test/resources/config/spark/conc_perf_stresstest_task_library.yaml @@ -0,0 +1,12 @@ +# Description: Tasks Library +--- +version: 1 +task_templates: +# Create external tables needed for benchmark +- id: setup + files: + - src/main/resources/scripts/tpcds/setup/spark/ddl-external-tables.sql +# Example task template for the base query of the custom concurrent performance stresstest. +- id: base_query + files: + - src/test/resources/scripts/spark/perf_stresstest.sql diff --git a/src/test/resources/config/spark/w_perf_stresstest.yaml b/src/test/resources/config/spark/w_perf_stresstest.yaml new file mode 100644 index 00000000..ae8098ec --- /dev/null +++ b/src/test/resources/config/spark/w_perf_stresstest.yaml @@ -0,0 +1,24 @@ +# Description: Example for custom concurrent performance stresstest workload +--- +version: 1 +id: perf-stresstest +phases: +- id: setup + sessions: + - tasks: + - template_id: setup +- id: query_execution_1 + sessions: + - tasks: + - template_id: base_query + custom_task_executor: com.microsoft.lst_bench.task.custom.ConcurrentPerfStresstestTaskExecutor + custom_task_executor_arguments: + concurrent_task_num_joins: 5 + num_instances: 5 +- id: query_execution_2 + sessions: + - tasks: + - template_id: base_query + custom_task_executor: com.microsoft.lst_bench.task.custom.ConcurrentPerfStresstestTaskExecutor + custom_task_executor_arguments: + concurrent_task_min_query_length: 1000 \ No newline at end of file diff --git a/src/test/resources/config/sqlserver/w_perf_stresstest.yaml b/src/test/resources/config/sqlserver/w_perf_stresstest.yaml index 7e7d0a21..1926c884 100644 --- a/src/test/resources/config/sqlserver/w_perf_stresstest.yaml +++ b/src/test/resources/config/sqlserver/w_perf_stresstest.yaml @@ -1,7 +1,7 @@ # Description: Example for custom concurrent performance stresstest workload --- version: 1 -id: perfstress-test +id: perf-stresstest phases: - id: query_execution_1 sessions: diff --git a/src/test/resources/scripts/spark/perf_stresstest.sql b/src/test/resources/scripts/spark/perf_stresstest.sql new file mode 100644 index 00000000..282d395d --- /dev/null +++ b/src/test/resources/scripts/spark/perf_stresstest.sql @@ -0,0 +1 @@ +SELECT s.* FROM ${catalog}.${database}.store s \ No newline at end of file diff --git a/src/test/resources/scripts/sqlserver/perf_stresstest.sql b/src/test/resources/scripts/sqlserver/perf_stresstest.sql index 5481c25a..fecc6c73 100644 --- a/src/test/resources/scripts/sqlserver/perf_stresstest.sql +++ b/src/test/resources/scripts/sqlserver/perf_stresstest.sql @@ -1 +1 @@ -SELECT t.* FROM test_table t; \ No newline at end of file +SELECT t.* FROM test_table t \ No newline at end of file From 50db65a023cbfed1c1c3e96e7d78a2d2693220eb Mon Sep 17 00:00:00 2001 From: Anja Gruenheid Date: Mon, 11 Sep 2023 16:10:37 +0200 Subject: [PATCH 20/20] bugfixing --- .../ConcurrentPerfStresstestTaskExecutor.java | 15 +++++++++------ .../resources/scripts/spark/perf_stresstest.sql | 2 +- .../scripts/sqlserver/perf_stresstest.sql | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java index 80c03371..354dfcff 100644 --- a/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java +++ b/src/main/java/com/microsoft/lst_bench/task/custom/ConcurrentPerfStresstestTaskExecutor.java @@ -60,6 +60,9 @@ public class ConcurrentPerfStresstestTaskExecutor extends CustomTaskExecutor { private final Pattern WHERE_PATTERN = Pattern.compile("WHERE|where|Where"); private final Pattern ORDER_PATTERN = Pattern.compile("ORDER|order|Order"); + private final Pattern FROM_PATTERN = Pattern.compile("FROM|from|From"); + + private final String QUERY_END_TOKEN = ";"; public ConcurrentPerfStresstestTaskExecutor( SQLTelemetryRegistry telemetryRegistry, @@ -96,17 +99,16 @@ public void executeTask(Connection connection, TaskExec task, Map 0) { query += new String(new char[queryPadding]).replace('\0', ' '); } + query += QUERY_END_TOKEN; StatementExec mod_statement = ImmutableStatementExec.of( diff --git a/src/test/resources/scripts/spark/perf_stresstest.sql b/src/test/resources/scripts/spark/perf_stresstest.sql index 282d395d..8e00b432 100644 --- a/src/test/resources/scripts/spark/perf_stresstest.sql +++ b/src/test/resources/scripts/spark/perf_stresstest.sql @@ -1 +1 @@ -SELECT s.* FROM ${catalog}.${database}.store s \ No newline at end of file +SELECT s.* FROM ${catalog}.${database}.store s; \ No newline at end of file diff --git a/src/test/resources/scripts/sqlserver/perf_stresstest.sql b/src/test/resources/scripts/sqlserver/perf_stresstest.sql index fecc6c73..5481c25a 100644 --- a/src/test/resources/scripts/sqlserver/perf_stresstest.sql +++ b/src/test/resources/scripts/sqlserver/perf_stresstest.sql @@ -1 +1 @@ -SELECT t.* FROM test_table t \ No newline at end of file +SELECT t.* FROM test_table t; \ No newline at end of file