From 52b1f91ccbcb317250b3b7701af9c60b9dac1219 Mon Sep 17 00:00:00 2001 From: Tobias Hafner Date: Sat, 22 Mar 2025 15:35:22 +0100 Subject: [PATCH 1/6] Add new locking benchmark --- .../simpleclient/cli/LockingBenchCommand.java | 90 ++++++ .../org/polypheny/simpleclient/cli/Main.java | 1 + .../main/LockingBenchScenario.java | 82 ++++++ .../polypheny/simpleclient/query/Query.java | 2 +- .../scenario/EvaluationThread.java | 112 ++++--- .../scenario/EvaluationThreadMonitor.java | 6 +- .../scenario/PolyphenyScenario.java | 2 +- .../scenario/scalingBench/Entity.java | 45 +++ .../ErrorHandlingEvaluationThread.java | 102 +++++++ .../ErrorHandlingPolyphenyScenario.java | 122 ++++++++ .../scenario/scalingBench/LockingBench.java | 274 ++++++++++++++++++ .../scalingBench/LockingBenchConfig.java | 60 ++++ .../LockingBenchDataGenerator.java | 91 ++++++ .../scalingBench/LockingBenchSchema.java | 93 ++++++ .../scenario/scalingBench/NumberTracker.java | 73 +++++ .../queryBuilder/CreateNamespace.java | 88 ++++++ .../scalingBench/queryBuilder/FullRead.java | 89 ++++++ .../scalingBench/queryBuilder/RangeRead.java | 108 +++++++ .../queryBuilder/RangeUpdate.java | 117 ++++++++ .../queryBuilder/SingleDelete.java | 104 +++++++ .../queryBuilder/SingleInsert.java | 183 ++++++++++++ .../scalingBench/queryBuilder/SingleRead.java | 104 +++++++ .../queryBuilder/SingleUpdate.java | 107 +++++++ .../scalingbench/scalingbench.properties | 31 ++ 24 files changed, 2024 insertions(+), 62 deletions(-) create mode 100644 src/main/java/org/polypheny/simpleclient/cli/LockingBenchCommand.java create mode 100644 src/main/java/org/polypheny/simpleclient/main/LockingBenchScenario.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/Entity.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchConfig.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchDataGenerator.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchSchema.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/NumberTracker.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/CreateNamespace.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/FullRead.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeRead.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeUpdate.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleDelete.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleRead.java create mode 100644 src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleUpdate.java create mode 100644 src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties diff --git a/src/main/java/org/polypheny/simpleclient/cli/LockingBenchCommand.java b/src/main/java/org/polypheny/simpleclient/cli/LockingBenchCommand.java new file mode 100644 index 0000000..3c1ba17 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/cli/LockingBenchCommand.java @@ -0,0 +1,90 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 1:02 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.cli; + +import com.github.rvesse.airline.annotations.Arguments; +import com.github.rvesse.airline.annotations.Command; +import com.github.rvesse.airline.annotations.Option; +import java.sql.SQLException; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.executor.Executor.ExecutorFactory; +import org.polypheny.simpleclient.executor.PolyphenyDbJdbcExecutor.PolyphenyDbJdbcExecutorFactory; +import org.polypheny.simpleclient.main.LockingBenchScenario; + +@Slf4j +@Command(name = "locking", description = "Mode for quick testing of Polypheny-DB using the locking benchmark.") +public class LockingBenchCommand implements CliRunnable { + + @Arguments(description = "Task { schema | data | workload | warmup }.") + private List args; + + @Option(name = { "-pdb", "--polyphenydb" }, title = "IP or Hostname", arity = 1, description = "IP or Hostname of Polypheny-DB (default: 127.0.0.1).") + public static String polyphenyDbHost = "127.0.0.1"; + + @Option(name = { "-s", "--sessions" }, title = "Numbers of sessions", arity = 1, description = "The number of session accessing the database simultaneously (default 5).") + public int sessionCount = 5; + + @Option(name = { "-n", "--namespaces" }, title = "Numbers of namespaces", arity = 1, description = "The number of namespaces the entities are distributed over (default 2).") + public int namespaceCount = 2; + + @Option(name = { "-e", "--entities" }, title = "Numbers of entities", arity = 1, description = "The number of entities to be used created in each namespace (default 5).") + public int entityCount = 5; + + @Option(name = { "-r", "--rwRatio" }, title = "Read Write Ratio", arity = 1, description = "The ratio between read and modify/write queries from 0 to 1 (default 0.5).") + public double readWriteRatio = 0.5; + + + @Override + public int run() throws SQLException { + if ( args == null || args.isEmpty() ) { + System.err.println( "Missing task" ); + System.exit( 1 ); + } + + ExecutorFactory executorFactory = new PolyphenyDbJdbcExecutorFactory( polyphenyDbHost, false ); + + try { + if ( args.getFirst().equalsIgnoreCase( "schema" ) ) { + LockingBenchScenario.schema( executorFactory, sessionCount, namespaceCount, entityCount, readWriteRatio ); + } else if ( args.getFirst().equalsIgnoreCase( "data" ) ) { + LockingBenchScenario.data( executorFactory, sessionCount, namespaceCount, entityCount, readWriteRatio ); + } else if ( args.getFirst().equalsIgnoreCase( "workload" ) ) { + LockingBenchScenario.workload( executorFactory, sessionCount, namespaceCount, entityCount, readWriteRatio ); + } else if ( args.getFirst().equalsIgnoreCase( "warmup" ) ) { + LockingBenchScenario.warmup( executorFactory, sessionCount, namespaceCount, entityCount, readWriteRatio ); + } else { + System.err.println( "Unknown task: " + args.get( 0 ) ); + } + } catch ( Throwable t ) { + log.error( "Exception while executing LockingBench!", t ); + System.exit( 1 ); + } + + return 0; + } + + +} diff --git a/src/main/java/org/polypheny/simpleclient/cli/Main.java b/src/main/java/org/polypheny/simpleclient/cli/Main.java index 988ac96..5a503b4 100644 --- a/src/main/java/org/polypheny/simpleclient/cli/Main.java +++ b/src/main/java/org/polypheny/simpleclient/cli/Main.java @@ -53,6 +53,7 @@ public static void main( String[] args ) throws SQLException { builder.withCommands( YcsbCommand.class ); builder.withCommands( DumpCommand.class ); builder.withCommands( HelpCommand.class ); + builder.withCommands( LockingBenchCommand.class ); builder.withDefaultCommand( HelpCommand.class ); Cli cli = builder.build(); diff --git a/src/main/java/org/polypheny/simpleclient/main/LockingBenchScenario.java b/src/main/java/org/polypheny/simpleclient/main/LockingBenchScenario.java new file mode 100644 index 0000000..70201fc --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/main/LockingBenchScenario.java @@ -0,0 +1,82 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 1:19 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.main; + +import java.io.File; +import java.io.IOException; +import java.util.Objects; +import java.util.Properties; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.executor.Executor.ExecutorFactory; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBench; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchConfig; + +@Slf4j +public class LockingBenchScenario { + + public static void schema( ExecutorFactory executorFactory, int sessionCount, int namespaceCount, int entityCount, double readWriteRatio ) { + LockingBenchConfig config = new LockingBenchConfig( getProperties(sessionCount), sessionCount, namespaceCount, entityCount, readWriteRatio ); + LockingBench lockingBench = new LockingBench( executorFactory, config ); + lockingBench.createSchema( null, false ); + } + + + public static void data( ExecutorFactory executorFactory, int sessionCount, int namespaceCount, int entityCount, double readWriteRatio ) { + LockingBenchConfig config = new LockingBenchConfig( getProperties(sessionCount), sessionCount, namespaceCount, entityCount, readWriteRatio ); + LockingBench lockingBench = new LockingBench( executorFactory, config ); + ProgressReporter progressReporter = new ProgressBar( config.sessionCount, config.progressReportBase ); + lockingBench.generateData( null, progressReporter ); + } + + + public static void warmup( ExecutorFactory executorFactory, int sessionCount, int namespaceCount, int entityCount, double readWriteRatio ) { + LockingBenchConfig config = new LockingBenchConfig( getProperties(sessionCount), sessionCount, namespaceCount, entityCount, readWriteRatio ); + LockingBench lockingBench = new LockingBench( executorFactory, config ); + ProgressReporter progressReporter = new ProgressBar( config.sessionCount, config.progressReportBase ); + lockingBench.warmUp( progressReporter ); + } + + + public static void workload( ExecutorFactory executorFactory, int sessionCount, int namespaceCount, int entityCount, double readWriteRatio ) { + LockingBenchConfig config = new LockingBenchConfig( getProperties(sessionCount), sessionCount, namespaceCount, entityCount, readWriteRatio ); + LockingBench lockingBench = new LockingBench( executorFactory, config ); + ProgressReporter progressReporter = new ProgressBar( config.sessionCount, config.progressReportBase ); + final CsvWriter writer = new CsvWriter( "results.csv" ); + lockingBench.execute( progressReporter, writer, new File("."), config.sessionCount ); + } + + + private static Properties getProperties(int sessionCount) { + Properties props = new Properties(); + try { + props.load( Objects.requireNonNull( ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties" ) ) ); + props.put("numberOfThreads", String.valueOf( sessionCount ) ); + } catch ( IOException e ) { + log.error( "Exception while reading properties file", e ); + } + return props; + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/query/Query.java b/src/main/java/org/polypheny/simpleclient/query/Query.java index 99f578f..7ab8b84 100644 --- a/src/main/java/org/polypheny/simpleclient/query/Query.java +++ b/src/main/java/org/polypheny/simpleclient/query/Query.java @@ -52,7 +52,7 @@ public Query( boolean expectResultSet ) { } - public enum DataTypes {INTEGER, VARCHAR, TIMESTAMP, DATE, ARRAY_INT, ARRAY_REAL, BYTE_ARRAY, FILE} + public enum DataTypes {SMALLINT, TEXT, DECIMAL, INTEGER, BIGINT, TINYINT, BOOLEAN, VARCHAR, TIMESTAMP, DATE, ARRAY_INT, ARRAY_REAL, BYTE_ARRAY, FILE} public abstract String getSql(); diff --git a/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThread.java b/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThread.java index 94a7ea2..bec338a 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThread.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThread.java @@ -43,17 +43,17 @@ @Slf4j public class EvaluationThread extends Thread { - private final Executor executor; - private final Queue queries; - private boolean abort = false; + protected final Executor executor; + protected final Queue queries; + protected boolean abort = false; @Setter - private EvaluationThreadMonitor threadMonitor; + protected EvaluationThreadMonitor threadMonitor; - private final List measuredTimes = Collections.synchronizedList( new LinkedList<>() ); + protected final List measuredTimes = Collections.synchronizedList( new LinkedList<>() ); - private final Map> measuredTimePerQueryType = new ConcurrentHashMap<>(); + protected final Map> measuredTimePerQueryType = new ConcurrentHashMap<>(); - final boolean commitAfterEveryQuery; + protected final boolean commitAfterEveryQuery; public EvaluationThread( Queue queryList, Executor executor, Set templateIds, boolean commitAfterEveryQuery ) { @@ -67,66 +67,64 @@ public EvaluationThread( Queue queryList, Executor executor, Set @Override public void run() { - long measuredTimeStart; - long measuredTime; - QueryListEntry queryListEntry; - - while ( !queries.isEmpty() && !abort ) { - measuredTimeStart = System.nanoTime(); - queryListEntry = queries.poll(); - if ( queryListEntry == null ) { + while (!queries.isEmpty() && !abort) { + QueryListEntry queryListEntry = queries.poll(); + if (queryListEntry == null) { break; } - try { - executor.executeQuery( queryListEntry.query ); - } catch ( ExecutorException e ) { - log.error( "Caught exception while executing queries", e ); - threadMonitor.notifyAboutError( e ); - try { - executor.executeRollback(); - } catch ( ExecutorException ex ) { - log.error( "Error while rollback", e ); - } - throw new RuntimeException( e ); - } - measuredTime = System.nanoTime() - measuredTimeStart; - measuredTimes.add( measuredTime ); - measuredTimePerQueryType.get( queryListEntry.templateId ).add( measuredTime ); - for ( Integer id : queryListEntry.templateIds ) { - if ( id != queryListEntry.templateId ) { - measuredTimePerQueryType.get( id ).add( measuredTime ); - } + + long measuredTime = executeAndMeasure(queryListEntry); + recordMeasuredTime(queryListEntry, measuredTime); + + if (commitAfterEveryQuery) { + commitSafely(); } - if ( commitAfterEveryQuery ) { - try { - executor.executeCommit(); - } catch ( ExecutorException e ) { - log.error( "Caught exception while committing", e ); - threadMonitor.notifyAboutError( e ); - try { - executor.executeRollback(); - } catch ( ExecutorException ex ) { - log.error( "Error while rollback", e ); - } - throw new RuntimeException( e ); - } + } + + commitSafely(); + executor.flushCsvWriter(); + } + + protected long executeAndMeasure(QueryListEntry queryListEntry) { + long startTime = System.nanoTime(); + try { + executor.executeQuery(queryListEntry.query); + } catch (ExecutorException e) { + log.error("Caught exception while executing queries", e); + threadMonitor.notifyAboutError(e); + rollbackSafely(e); + throw new RuntimeException(e); + } + return System.nanoTime() - startTime; + } + + protected void recordMeasuredTime(QueryListEntry entry, long measuredTime) { + measuredTimes.add(measuredTime); + measuredTimePerQueryType.get(entry.templateId).add(measuredTime); + for (Integer id : entry.templateIds) { + if (!id.equals(entry.templateId)) { + measuredTimePerQueryType.get(id).add(measuredTime); } } + } + protected void commitSafely() { try { executor.executeCommit(); - } catch ( ExecutorException e ) { - log.error( "Caught exception while committing", e ); - threadMonitor.notifyAboutError( e ); - try { - executor.executeRollback(); - } catch ( ExecutorException ex ) { - log.error( "Error while rollback", e ); - } - throw new RuntimeException( e ); + } catch (ExecutorException e) { + log.error("Caught exception while committing", e); + threadMonitor.notifyAboutError(e); + rollbackSafely(e); + throw new RuntimeException(e); } + } - executor.flushCsvWriter(); + protected void rollbackSafely(Exception originalException) { + try { + executor.executeRollback(); + } catch (ExecutorException rollbackException) { + log.error("Error while rollback", originalException); + } } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThreadMonitor.java b/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThreadMonitor.java index 79534f8..610e540 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThreadMonitor.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThreadMonitor.java @@ -27,16 +27,16 @@ import java.util.List; import lombok.Getter; -public final class EvaluationThreadMonitor { +public class EvaluationThreadMonitor { - private final List threads; + private final List threads; @Getter private Exception exception; @Getter private boolean aborted; - public EvaluationThreadMonitor( List threads ) { + public EvaluationThreadMonitor( List threads ) { this.threads = threads; this.aborted = false; } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/PolyphenyScenario.java b/src/main/java/org/polypheny/simpleclient/scenario/PolyphenyScenario.java index 5b200e3..21c4acc 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/PolyphenyScenario.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/PolyphenyScenario.java @@ -130,7 +130,7 @@ public void analyze( Properties properties, File outputDirectory ) { } - private void dumpQueryList( File outputDirectory, List queryList, Function toString ) { + protected void dumpQueryList( File outputDirectory, List queryList, Function toString ) { if ( outputDirectory != null && dumpQueryList ) { log.info( "Dump query list..." ); try { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/Entity.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/Entity.java new file mode 100644 index 0000000..fa49903 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/Entity.java @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/22/25, 9:43 AM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench; + +import lombok.Getter; + +@Getter +public class Entity { + private static final String NAMESPACE_NAME_TEMPLATE = "ns_%d"; + private static final String ENTITY_NAME_TEMPLATE = "ent_%d"; + + private final String namespaceName; + private final String entityName; + + public Entity( int namespaceIndex, int entityIndex ) { + this.namespaceName = String.format( NAMESPACE_NAME_TEMPLATE, namespaceIndex ); + this.entityName = String.format( ENTITY_NAME_TEMPLATE, entityIndex ); + } + + public String getFullName() { + return namespaceName + "." + entityName; + } +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java new file mode 100644 index 0000000..ecd71ae --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java @@ -0,0 +1,102 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/22/25, 1:33 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench; + +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.executor.Executor; +import org.polypheny.simpleclient.executor.ExecutorException; +import org.polypheny.simpleclient.query.QueryListEntry; +import org.polypheny.simpleclient.scenario.EvaluationThread; + +@Slf4j +@Getter +public class ErrorHandlingEvaluationThread extends EvaluationThread { + + long numberOfFailedQueries = 0; + Map, Set> expectedExceptions; + + + public ErrorHandlingEvaluationThread( Queue queryList, Executor executor, Set templateIds, boolean commitAfterEveryQuery, Map, Set> expectedExceptions ) { + super( queryList, executor, templateIds, commitAfterEveryQuery ); + this.expectedExceptions = expectedExceptions; + } + + + public boolean isExpectedException( Throwable e ) { + for ( Map.Entry, Set> entry : expectedExceptions.entrySet() ) { + if ( entry.getKey().isInstance( e ) ) { + return entry.getValue().stream().anyMatch( msg -> e.getMessage() != null && e.getMessage().contains( msg ) ); + } + } + return false; + } + + + @Override + protected long executeAndMeasure( QueryListEntry queryListEntry ) { + long startTime = System.nanoTime(); + try { + executor.executeQuery( queryListEntry.query ); + } catch ( ExecutorException e ) { + throwIfUnexpected( e, "executing queries", queryListEntry.query.getSql() ); + } + return System.nanoTime() - startTime; + } + + + @Override + protected void commitSafely() { + try { + executor.executeCommit(); + } catch ( ExecutorException e ) { + throwIfUnexpected( e, "committing" ); + } + } + + + private void throwIfUnexpected( ExecutorException e, String operationDescription ) { + throwIfUnexpected( e, operationDescription, null ); + } + + + private void throwIfUnexpected( ExecutorException e, String operationDescription, String statement ) { + if ( !isExpectedException( e ) ) { + if ( statement != null ) { + log.error( "Caught exception while {}. Statement: {}", operationDescription, statement, e ); + } else { + log.error( "Caught exception while {}", operationDescription, e ); + } + threadMonitor.notifyAboutError( e ); + rollbackSafely( e ); + throw new RuntimeException( e ); + } + numberOfFailedQueries++; + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java new file mode 100644 index 0000000..fe6554f --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java @@ -0,0 +1,122 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/22/25, 1:27 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Queue; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.function.Function; +import java.util.function.Supplier; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.executor.Executor; +import org.polypheny.simpleclient.executor.Executor.ExecutorFactory; +import org.polypheny.simpleclient.main.ProgressReporter; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryListEntry; +import org.polypheny.simpleclient.scenario.EvaluationThread; +import org.polypheny.simpleclient.scenario.EvaluationThreadMonitor; +import org.polypheny.simpleclient.scenario.PolyphenyScenario; + +@Slf4j +public abstract class ErrorHandlingPolyphenyScenario extends PolyphenyScenario { + protected long failedQueries = 0; + + public ErrorHandlingPolyphenyScenario( ExecutorFactory executorFactory, boolean commitAfterEveryQuery, boolean dumpQueryList, QueryMode queryMode ) { + super( executorFactory, commitAfterEveryQuery, dumpQueryList, queryMode ); + } + + + protected long commonExecuteWithExpectedErrors( List queries, ProgressReporter progressReporter, File outputDirectory, int numberOfThreads, Function toString, Supplier executor, Random random, Map, Set> expectedExceptions ) { + Collections.shuffle( queries, random ); + + // This dumps the queries independent of the selected interface + dumpQueryList( outputDirectory, queries, toString ); + + Queue queryList = new ConcurrentLinkedQueue<>( queries ); + + log.info( "Executing benchmark..." ); + (new Thread( new ProgressReporter.ReportQueryListProgress( queryList, progressReporter ) )).start(); + long startTime = System.nanoTime(); + + List threads = new ArrayList<>(); + for ( int i = 0; i < numberOfThreads; i++ ) { + threads.add( new ErrorHandlingEvaluationThread( queryList, executor.get(), queryTypes.keySet(), commitAfterEveryQuery, expectedExceptions ) ); + } + + EvaluationThreadMonitor threadMonitor = new EvaluationThreadMonitor( threads ); + threads.forEach( t -> t.setThreadMonitor( threadMonitor ) ); + + for ( ErrorHandlingEvaluationThread thread : threads ) { + thread.start(); + } + + for ( ErrorHandlingEvaluationThread thread : threads ) { + try { + thread.join(); + this.measuredTimes.addAll( thread.getMeasuredTimes() ); + thread.getMeasuredTimePerQueryType().forEach( ( k, v ) -> { + if ( !this.measuredTimePerQueryType.containsKey( k ) ) { + this.measuredTimePerQueryType.put( k, new ArrayList<>() ); + } + this.measuredTimePerQueryType.get( k ).addAll( v ); + } ); + this.failedQueries += thread.getNumberOfFailedQueries(); + } catch ( InterruptedException e ) { + throw new RuntimeException( "Unexpected interrupt", e ); + } + } + + executeRuntime = System.nanoTime() - startTime; + + for ( EvaluationThread thread : threads ) { + thread.closeExecutor(); + } + + if ( threadMonitor.isAborted() ) { + throw new RuntimeException( "Exception while executing benchmark", threadMonitor.getException() ); + } + + log.info( "run time: {} s", executeRuntime / 1000000000 ); + + return executeRuntime; + } + + @Override + public void analyze( Properties properties, File outputDirectory ) { + super.analyze( properties, outputDirectory ); + properties.put( "numberOfFailedQueries", failedQueries ); + properties.put( "querySuccessRatio", (measuredTimes.size() - failedQueries) / measuredTimes.size()); + } + + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java new file mode 100644 index 0000000..d3b8d05 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java @@ -0,0 +1,274 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 1:28 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Random; +import java.util.Set; +import java.util.Vector; +import lombok.extern.slf4j.Slf4j; +import org.polypheny.simpleclient.QueryMode; +import org.polypheny.simpleclient.executor.Executor; +import org.polypheny.simpleclient.executor.Executor.DatabaseInstance; +import org.polypheny.simpleclient.executor.Executor.ExecutorFactory; +import org.polypheny.simpleclient.executor.ExecutorException; +import org.polypheny.simpleclient.executor.PolyphenyDbJdbcExecutor.PolyphenyDbJdbcExecutorFactory; +import org.polypheny.simpleclient.main.CsvWriter; +import org.polypheny.simpleclient.main.ProgressReporter; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.query.QueryListEntry; +import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker.Mode; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.FullRead; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.RangeRead; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.RangeUpdate; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleDelete; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleInsert; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleRead; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleUpdate; + + +@Slf4j +public class LockingBench extends ErrorHandlingPolyphenyScenario { + + private final LockingBenchConfig config; + private final Map, Set> expectedExceptions; + + + public LockingBench( ExecutorFactory executorFactory, LockingBenchConfig config ) { + super( executorFactory, true, false, QueryMode.TABLE ); + this.config = config; + this.expectedExceptions = initializeExpectedExceptions(); + } + + + public Map, Set> initializeExpectedExceptions() { + return ImmutableMap., Set>builder() + .put( ExecutorException.class, ImmutableSet.of( + "Committing current transaction failed: Rolling back due to MVCC write conflict.", + "encountered a deadlock while acquiring a lock of type" + ) ) + .build(); + } + + + @Override + public void createSchema( DatabaseInstance databaseInstance, boolean includingKeys ) { + log.info( "Creating schema..." ); + if ( !(executorFactory instanceof PolyphenyDbJdbcExecutorFactory) ) { + throw new RuntimeException( "Unsupported executor factory: " + executorFactory.getClass().getName() ); + } + + Executor executor = executorFactory.createExecutorInstance(); + LockingBenchSchema schema = new LockingBenchSchema( config ); + try { + for ( Query createNamespaceQuery : schema.getCrateNamespaceQueries() ) { + executor.executeQuery( createNamespaceQuery ); + } + + for ( Query query : schema.getCrateTableQueries() ) { + executor.executeQuery( query ); + } + } catch ( ExecutorException e ) { + throw new RuntimeException( "Exception while creating schema", e ); + } finally { + commitAndCloseExecutor( executor ); + } + } + + + @Override + public void generateData( DatabaseInstance databaseInstance, ProgressReporter progressReporter ) { + log.info( "Generating data..." ); + Executor executor = executorFactory.createExecutorInstance(); + NumberTracker numberTracker = new NumberTracker( config, Mode.SETUP ); + LockingBenchDataGenerator dataGenerator = new LockingBenchDataGenerator( config, executor, progressReporter, numberTracker ); + LockingBenchSchema schema = new LockingBenchSchema( config ); + + try { + dataGenerator.generateEntries( schema.getEntities() ); + } catch ( ExecutorException e ) { + throw new RuntimeException( "Exception while generating data", e ); + } finally { + commitAndCloseExecutor( executor ); + } + } + + + @Override + public long execute( ProgressReporter progressReporter, CsvWriter csvWriter, File outputDirectory, int numberOfThreads ) { + NumberTracker numberTracker = new NumberTracker( config, Mode.RUN ); + LockingBenchSchema schema = new LockingBenchSchema( config ); + + log.info( "Calculating query type distribution..." ); + Map distribution = distributeQueries( config.numberOfQueries, config.readWriteRatio ); + + log.info( "Preparing query list for the benchmark..." ); + List queryList = new Vector<>(); + addNumberOfTimes( queryList, new SingleRead( schema, numberTracker ), distribution.get( "singleRead" ) ); + addNumberOfTimes( queryList, new RangeRead( schema, numberTracker ), distribution.get( "rangeRead" ) ); + addNumberOfTimes( queryList, new FullRead( schema ), distribution.get( "fullRead" ) ); + addNumberOfTimes( queryList, new SingleUpdate( schema, numberTracker ), distribution.get( "singleUpdate" ) ); + addNumberOfTimes( queryList, new RangeUpdate( schema, numberTracker ), distribution.get( "rangeUpdate" ) ); + addNumberOfTimes( queryList, new SingleDelete( schema, numberTracker ), distribution.get( "singleDelete" ) ); + addNumberOfTimes( queryList, new SingleInsert( schema, numberTracker ), distribution.get( "singleInsert" ) ); + + long executionTime = commonExecuteWithExpectedErrors( + queryList, + progressReporter, + outputDirectory, + config.sessionCount, + Query::getSql, + () -> executorFactory.createExecutorInstance( csvWriter ), + new Random(), + expectedExceptions + ); + + analyzeAndStore( outputDirectory ); + return executionTime; + } + + private void analyzeAndStore(File outputDirectory) { + Properties analysis = new Properties() { + @Override + public synchronized void store( OutputStream out, String comments) throws IOException { + Properties stringOnly = new Properties(); + for (Map.Entry e : this.entrySet()) { + stringOnly.setProperty(e.getKey().toString(), e.getValue().toString()); + } + stringOnly.store(out, comments); + } + }; + + File analysisFile = new File(outputDirectory, "analysis.txt"); + analyze(analysis, analysisFile); + + try (FileOutputStream out = new FileOutputStream(analysisFile)) { + analysis.store(out, "Analysis results"); + } catch (IOException e) { + log.error("Exception while generating analysis", e); + } + } + + + private void addNumberOfTimes( List list, QueryBuilder queryBuilder, int numberOfTimes ) { + int id = queryTypes.size() + 1; + queryTypes.put( id, queryBuilder.getNewQuery().getSql() ); + measuredTimePerQueryType.put( id, Collections.synchronizedList( new LinkedList<>() ) ); + for ( int i = 0; i < numberOfTimes; i++ ) { + list.add( new QueryListEntry( queryBuilder.getNewQuery(), id ) ); + } + } + + + public static Map distributeQueries( int totalQueryCount, double readWriteRatio ) { + int numberOfReads = (int) Math.round( totalQueryCount * readWriteRatio ); + int numberOfWrites = totalQueryCount - numberOfReads; + + Map distribution = new HashMap<>(); + + String[] readTypes = { "singleRead", "rangeRead", "fullRead" }; + int baseReadCount = numberOfReads / readTypes.length; + int remainingReads = numberOfReads % readTypes.length; + + for ( int i = 0; i < readTypes.length; i++ ) { + distribution.put( readTypes[i], baseReadCount + (i < remainingReads ? 1 : 0) ); + } + + String[] writeTypes = { "singleUpdate", "singleInsert", "singleDelete", "rangeUpdate" }; + int baseWriteCount = numberOfWrites / writeTypes.length; + int remainingWrites = numberOfWrites % writeTypes.length; + + for ( int i = 0; i < writeTypes.length; i++ ) { + distribution.put( writeTypes[i], baseWriteCount + (i < remainingWrites ? 1 : 0) ); + } + + return distribution; + } + + + @Override + public void warmUp( ProgressReporter progressReporter ) { + log.info( "Warm-up..." ); + Executor executor = null; + NumberTracker numberTracker = new NumberTracker( config, Mode.WARMUP ); + LockingBenchSchema schema = new LockingBenchSchema( config ); + for ( int i = 0; i < config.numberOfWarmUpIterations; i++ ) { + try { + executor = executorFactory.createExecutorInstance(); + + executor.executeQuery( new SingleRead( schema, numberTracker ).getNewQuery() ); + executor.executeCommit(); + + executor.executeQuery( new SingleInsert( schema, numberTracker ).getNewQuery() ); + executor.executeCommit(); + + executor.executeQuery( new SingleDelete( schema, numberTracker ).getNewQuery() ); + executor.executeCommit(); + + executor.executeQuery( new SingleUpdate( schema, numberTracker ).getNewQuery() ); + executor.executeCommit(); + + executor.executeQuery( new RangeUpdate( schema, numberTracker ).getNewQuery() ); + executor.executeCommit(); + + executor.executeQuery( new RangeRead( schema, numberTracker ).getNewQuery() ); + executor.executeCommit(); + + executor.executeQuery( new FullRead( schema ).getNewQuery() ); + executor.executeCommit(); + + } catch ( Exception e ) { + log.error( "Exception while executing warmup queries", e ); + } finally { + commitAndCloseExecutor( executor ); + } + try { + Thread.sleep( 10000 ); + } catch ( InterruptedException e ) { + throw new RuntimeException( "Unexpected interrupt", e ); + } + + } + } + + + @Override + public int getNumberOfInsertThreads() { + return 1; + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchConfig.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchConfig.java new file mode 100644 index 0000000..4bf0449 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchConfig.java @@ -0,0 +1,60 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 2:02 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench; + +import java.util.Properties; +import org.polypheny.simpleclient.scenario.AbstractConfig; + +public class LockingBenchConfig extends AbstractConfig { + public final int sessionCount; + public final int entityCount; + public final double readWriteRatio; + public final int namespaceCount; + + public int numberOfEntriesPerTable; + public int maxBatchSize; + public int progressReportBase; + public int numberOfQueries; + + public LockingBenchConfig( Properties properties, int sessionCount, int namespaceCount, int entityCount, double readWriteRatio) { + super("scalingBench", "polypheny-jdbc", properties); + this.sessionCount = sessionCount; + this.entityCount = entityCount; + this.readWriteRatio = readWriteRatio; + this.namespaceCount = namespaceCount; + + this.numberOfEntriesPerTable = getIntProperty( properties, "numberOfEntriesPerTable" ); + this.maxBatchSize = getIntProperty( properties, "maxBatchSize" ); + this.progressReportBase = getIntProperty( properties, "progressReportBase" ); + this.numberOfQueries = getIntProperty( properties, "numberOfQueries" ); + } + + + @Override + public boolean usePreparedBatchForDataInsertion() { + return false; + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchDataGenerator.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchDataGenerator.java new file mode 100644 index 0000000..2539639 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchDataGenerator.java @@ -0,0 +1,91 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 2:12 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench; + +import java.util.LinkedList; +import java.util.List; +import org.polypheny.simpleclient.executor.Executor; +import org.polypheny.simpleclient.executor.ExecutorException; +import org.polypheny.simpleclient.main.ProgressReporter; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleInsert; + +public class LockingBenchDataGenerator { + + private final LockingBenchConfig config; + private final Executor executor; + private final ProgressReporter progressReporter; + private final List batchList; + private final NumberTracker numberTracker; + + private boolean aborted; + + public LockingBenchDataGenerator( LockingBenchConfig config, Executor executor, ProgressReporter progressReporter, NumberTracker numberTracker ) { + this.config = config; + this.executor = executor; + this.progressReporter = progressReporter; + this.aborted = false; + this.numberTracker = numberTracker; + this.batchList = new LinkedList<>(); + } + + public void generateEntries( List entities) throws ExecutorException { + int mod = entities.size() / progressReporter.base; + if ( mod == 0 ) { + mod++; // Avoid division by zero + } + for (Entity entity : entities) { + SingleInsert entryBuilder = new SingleInsert( entity.getFullName(), numberTracker ); + for (int i = 0; i < config.numberOfEntriesPerTable; i++) { + if (aborted) { + break; + } + addToInsertList(entryBuilder.getNewQuery()); + } + } + if ( !batchList.isEmpty() ) { + executeInsertList(); + } + } + + private void addToInsertList( BatchableInsert query) throws ExecutorException { + batchList.add(query); + if (batchList.size() >= config.maxBatchSize) { + executeInsertList(); + } + } + + private void executeInsertList() throws ExecutorException { + executor.executeInsertList( batchList, config ); + executor.executeCommit(); + batchList.clear(); + } + + + public void abort() { + aborted = true; + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchSchema.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchSchema.java new file mode 100644 index 0000000..ae11a82 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchSchema.java @@ -0,0 +1,93 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 1:39 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.IntStream; +import lombok.Getter; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.scenario.multimedia.queryBuilder.CreateTable; +import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.CreateNamespace; + +@Getter +public class LockingBenchSchema { + + private final int namespaceCount; + private final int entitiesPerNamespace; + private final List entities; + + + public LockingBenchSchema( LockingBenchConfig config ) { + this.namespaceCount = config.namespaceCount; + this.entitiesPerNamespace = config.entityCount; + this.entities = initializeEntities(); + } + + + private List initializeEntities() { + AtomicInteger entryIndexGenerator = new AtomicInteger( 0 ); + List entities = new LinkedList<>(); + for ( int namespaceIndex = 0; namespaceIndex < namespaceCount; namespaceIndex++ ) { + for ( int j = 0; j < entitiesPerNamespace; j++ ) { + entities.add( new Entity( namespaceIndex, entryIndexGenerator.getAndIncrement() ) ); + } + } + return entities; + } + + public List getCrateNamespaceQueries() { + String createNamespaceTemplate = "CREATE RELATIONAL NAMESPACE %s"; + + return entities.stream() + .map( Entity::getNamespaceName ) + .distinct() + .map( n -> new CreateNamespace( String.format( createNamespaceTemplate, n ) ).getNewQuery() ) + .toList(); + } + + public List getCrateTableQueries() { + String createTableTemplate = """ + CREATE TABLE %s ( + id BIGINT PRIMARY KEY, + category_id INT, + score DECIMAL(10, 2), + is_verified BOOLEAN + ); + """; + + return entities.stream() + .map( Entity::getFullName ) + .map( f -> new CreateTable( String.format( createTableTemplate, f ) ).getNewQuery() ) + .toList(); + } + + + public String getRandomEntityFullName() { + return entities.get( ThreadLocalRandom.current().nextInt( entities.size() ) ).getFullName(); + } +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/NumberTracker.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/NumberTracker.java new file mode 100644 index 0000000..61d3bbe --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/NumberTracker.java @@ -0,0 +1,73 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 7:43 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench; + +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicLong; + +public class NumberTracker { + + public static final int CATEGORY_COUNT = 4; + + private final LockingBenchConfig config; + private final AtomicLong idCounter; + + + public NumberTracker( LockingBenchConfig config, Mode mode ) { + this.config = config; + this.idCounter = switch ( mode ) { + case SETUP -> new AtomicLong(); + case WARMUP -> new AtomicLong( (long) config.namespaceCount * config.entityCount * config.numberOfEntriesPerTable ); + case RUN -> new AtomicLong( ((long) config.namespaceCount * config.entityCount * config.numberOfEntriesPerTable) + config.numberOfWarmUpIterations ); + }; + } + + + public long getNextId() { + return idCounter.incrementAndGet(); + } + + + public long getMaxId() { + return idCounter.get(); + } + + + public long getRandomId() { + return ThreadLocalRandom.current().nextLong( getMaxId() ); + } + + + public int getRandomCategoryId() { + return ThreadLocalRandom.current().nextInt( CATEGORY_COUNT ); + } + + enum Mode { + SETUP, + WARMUP, + RUN + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/CreateNamespace.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/CreateNamespace.java new file mode 100644 index 0000000..3438dbc --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/CreateNamespace.java @@ -0,0 +1,88 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/22/25, 9:36 AM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; + +import java.util.Map; +import kong.unirest.core.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; + +public class CreateNamespace extends QueryBuilder { + + final String sql; + + + public CreateNamespace( String sql ) { + this.sql = sql; + } + + + @Override + public Query getNewQuery() { + return new CreateNamespaceQuery( sql ); + } + + private static class CreateNamespaceQuery extends Query { + private final String sql; + + CreateNamespaceQuery( String sql ) { + super(false); + this.sql = sql; + } + + + @Override + public String getSql() { + return sql; + } + + + @Override + public String getParameterizedSqlQuery() { + return null; + } + + + @Override + public Map> getParameterValues() { + return null; + } + + + @Override + public HttpRequest getRest() { + return null; + } + + + @Override + public String getMongoQl() { + return null; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/FullRead.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/FullRead.java new file mode 100644 index 0000000..491d566 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/FullRead.java @@ -0,0 +1,89 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/22/25, 8:54 AM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; + +import java.util.Map; +import kong.unirest.core.HttpRequest; +import kong.unirest.core.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; + +public class FullRead extends QueryBuilder { + private final LockingBenchSchema schema; + + public FullRead( LockingBenchSchema schema ) { + this.schema = schema; + } + + + @Override + public Query getNewQuery() { + String tableName = schema.getRandomEntityFullName(); + return new FullReadQuery(tableName); + } + + private static class FullReadQuery extends Query { + private final String tableName; + + public FullReadQuery( String tableName ) { + super(true); + this.tableName = tableName; + } + + + @Override + public String getSql() { + return "SELECT * FROM " + tableName; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT * FROM " + tableName; + } + + + @Override + public Map> getParameterValues() { + return Map.of(); + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".find({})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeRead.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeRead.java new file mode 100644 index 0000000..559202f --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeRead.java @@ -0,0 +1,108 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 8:08 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.core.HttpRequest; +import kong.unirest.core.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; + +public class RangeRead extends QueryBuilder { + + private final LockingBenchSchema schema; + private final NumberTracker numberTracker; + + + public RangeRead( LockingBenchSchema schema, NumberTracker numberTracker ) { + this.schema = schema; + this.numberTracker = numberTracker; + } + + + @Override + public Query getNewQuery() { + String tableName = schema.getRandomEntityFullName(); + int categoryId = numberTracker.getRandomCategoryId(); + return new RangeReadQuery( tableName, categoryId ); + } + + + private static class RangeReadQuery extends Query { + + private final String tableName; + private final int categoryId; + + + public RangeReadQuery( String tableName, int categoryId ) { + super( true ); + this.tableName = tableName; + this.categoryId = categoryId; + } + + + @Override + public String getSql() { + return "SELECT COUNT(*) AS cnt FROM " + tableName + + " WHERE category_id = " + categoryId; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT COUNT(*) AS cnt FROM " + tableName + + " WHERE category_id = ?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.INTEGER, categoryId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "_project", "public." + tableName + ".id@num(COUNT)" ) + .queryString( "_where", + "public." + tableName + ".category_id.eq." + categoryId); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".count({ category_id: " + categoryId + "})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeUpdate.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeUpdate.java new file mode 100644 index 0000000..1a2b468 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeUpdate.java @@ -0,0 +1,117 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 8:10 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.core.HttpRequest; +import kong.unirest.core.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; + +public class RangeUpdate extends QueryBuilder { + + private final LockingBenchSchema schema; + private final NumberTracker numberTracker; + + + public RangeUpdate( LockingBenchSchema schema, NumberTracker numberTracker ) { + this.schema = schema; + this.numberTracker = numberTracker; + } + + + @Override + public Query getNewQuery() { + String tableName = schema.getRandomEntityFullName(); + int categoryId = numberTracker.getRandomCategoryId(); + boolean isVerified = ThreadLocalRandom.current().nextBoolean(); + return new RangeUpdateQuery( tableName, categoryId, isVerified ); + } + + + private static class RangeUpdateQuery extends Query { + + private final String tableName; + private final int categoryId; + private final boolean isVerified; + + + public RangeUpdateQuery( String tableName, int categoryId, boolean isVerified ) { + super( false ); // no result expected + this.tableName = tableName; + this.categoryId = categoryId; + this.isVerified = isVerified; + } + + + @Override + public String getSql() { + return "UPDATE " + tableName + + " SET is_verified = " + isVerified + + " WHERE category_id = " + categoryId; + } + + + @Override + public String getParameterizedSqlQuery() { + return "UPDATE " + tableName + + " SET is_verified = ? WHERE category_id = ?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.BOOLEAN, isVerified ) ); + map.put( 2, new ImmutablePair<>( DataTypes.INTEGER, categoryId ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + String whereClause = "public." + tableName + ".category_id.eq." + categoryId; + return Unirest.patch( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "_where", whereClause ) + .header( "Content-Type", "application/json" ) + .body( "{\"public." + tableName + ".is_verified\": " + isVerified + "}" ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + + ".updateMany({ category_id: " + categoryId + + " }, { $set: { is_verified: " + isVerified + " } })"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleDelete.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleDelete.java new file mode 100644 index 0000000..6740cca --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleDelete.java @@ -0,0 +1,104 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 8:10 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.core.HttpRequest; +import kong.unirest.core.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; + +public class SingleDelete extends QueryBuilder { + + private final LockingBenchSchema schema; + private final NumberTracker numberTracker; + + + public SingleDelete( LockingBenchSchema schema, NumberTracker numberTracker ) { + this.schema = schema; + this.numberTracker = numberTracker; + } + + + @Override + public Query getNewQuery() { + String tableName = schema.getRandomEntityFullName(); + long id = numberTracker.getRandomId(); + return new DeleteByIdQuery( tableName, id ); + } + + + private static class DeleteByIdQuery extends Query { + + private final String tableName; + private final long id; + + + public DeleteByIdQuery( String tableName, long id ) { + super( false ); // no result expected + this.tableName = tableName; + this.id = id; + } + + + @Override + public String getSql() { + return "DELETE FROM " + tableName + " WHERE id = " + id; + } + + + @Override + public String getParameterizedSqlQuery() { + return "DELETE FROM " + tableName + " WHERE id = ?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.BIGINT, id ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.delete( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "_where", "public." + tableName + ".id.eq." + id ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".deleteOne({ id: " + id + " })"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java new file mode 100644 index 0000000..7dd0a7f --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java @@ -0,0 +1,183 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 7:37 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; + +import com.devskiller.jfairy.Fairy; +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.core.HttpRequest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.BatchableInsert; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; + +public class SingleInsert extends QueryBuilder { + + private static final boolean EXPECT_RESULT = false; + private final Optional entityName; + private final Optional schema; + private final NumberTracker numberTracker; + + + public SingleInsert( String entityName, NumberTracker numberTracker ) { + this.entityName = Optional.of( entityName ); + this.numberTracker = numberTracker; + this.schema = Optional.empty(); + } + + + public SingleInsert( LockingBenchSchema schema, NumberTracker numberTracker ) { + this.entityName = Optional.empty(); + this.numberTracker = numberTracker; + this.schema = Optional.of( schema ); + } + + + @Override + public BatchableInsert getNewQuery() { + long id = numberTracker.getNextId(); + int categoryId = numberTracker.getRandomCategoryId(); + double score = ThreadLocalRandom.current().nextDouble(); + boolean isVerified = ThreadLocalRandom.current().nextBoolean(); + + + String tableName; + if (this.entityName.isPresent()) { + tableName = this.entityName.get(); + } else if (this.schema.isPresent()) { + tableName = schema.get().getRandomEntityFullName(); + } else { + System.out.println(entityName); + System.out.println(schema); + throw new RuntimeException("WTF"); + } + + return new InsertEntryQuery( + tableName, + id, + categoryId, + score, + isVerified + ); + } + + + static class InsertEntryQuery extends BatchableInsert { + + private static final String SQL = "INSERT INTO %s(id, category_id, score, is_verified) VALUES "; + + private final String tableName; + private final long id; + private final int categoryId; + private final double score; + private final boolean isVerified; + + + public InsertEntryQuery( String tableName, long id, int categoryId, double score, boolean isVerified ) { + super( EXPECT_RESULT ); + this.tableName = tableName; + this.id = id; + this.categoryId = categoryId; + this.score = score; + this.isVerified = isVerified; + } + + + @Override + public String getSql() { + return String.format( SQL, tableName ) + getSqlRowExpression(); + } + + + @Override + public String getSqlRowExpression() { + return "(" + + id + ", " + + categoryId + ", " + + score + ", " + + isVerified + + ")"; + } + + + @Override + public String getParameterizedSqlQuery() { + return String.format( SQL, tableName ) + "(?, ?, ?, ?, ?, ?)"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.BIGINT, id ) ); + map.put( 2, new ImmutablePair<>( DataTypes.INTEGER, categoryId ) ); + map.put( 3, new ImmutablePair<>( DataTypes.DECIMAL, score ) ); + map.put( 6, new ImmutablePair<>( DataTypes.BOOLEAN, isVerified ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return buildRestInsert( tableName, ImmutableList.of( getRestRowExpression() ) ); + } + + + @Override + public JsonObject getRestRowExpression() { + JsonObject row = new JsonObject(); + row.addProperty( tableName + ".id", id ); + row.addProperty( tableName + ".category_id", categoryId ); + row.addProperty( tableName + ".score", score ); + row.addProperty( tableName + ".is_verified", isVerified ); + return row; + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".insert({" + + "\"id\":" + id + ", " + + "\"category_id\":" + categoryId + ", " + + "\"score\":" + score + ", " + + "\"is_verified\":" + isVerified + + "})"; + } + + + @Override + public String getEntity() { + return tableName; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleRead.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleRead.java new file mode 100644 index 0000000..fccc0ed --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleRead.java @@ -0,0 +1,104 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 8:07 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; + +import java.util.HashMap; +import java.util.Map; +import kong.unirest.core.HttpRequest; +import kong.unirest.core.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; + +public class SingleRead extends QueryBuilder { + + private final LockingBenchSchema schema; + private final NumberTracker numberTracker; + + + public SingleRead( LockingBenchSchema schema, NumberTracker numberTracker ) { + this.schema = schema; + this.numberTracker = numberTracker; + } + + + @Override + public Query getNewQuery() { + String tableName = schema.getRandomEntityFullName(); + long id = numberTracker.getRandomId(); + return new SingleReadQuery( tableName, id ); + } + + + private static class SingleReadQuery extends Query { + + private final String tableName; + private final long id; + + + public SingleReadQuery( String tableName, long id ) { + super( true ); // expects result + this.tableName = tableName; + this.id = id; + } + + + @Override + public String getSql() { + return "SELECT * FROM " + tableName + " WHERE id = " + id; + } + + + @Override + public String getParameterizedSqlQuery() { + return "SELECT * FROM " + tableName + " WHERE id = ?"; + } + + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put( 1, new ImmutablePair<>( DataTypes.BIGINT, id ) ); + return map; + } + + + @Override + public HttpRequest getRest() { + return Unirest.get( "{protocol}://{host}:{port}/restapi/v1/res/public." + tableName ) + .queryString( "_where", "public." + tableName + ".id.eq." + id ); + } + + + @Override + public String getMongoQl() { + return "db." + tableName + ".find({\"id\": " + id + "})"; + } + + } + +} diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleUpdate.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleUpdate.java new file mode 100644 index 0000000..8ebe571 --- /dev/null +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleUpdate.java @@ -0,0 +1,107 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019-3/21/25, 8:09 PM The Polypheny Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import kong.unirest.core.HttpRequest; +import kong.unirest.core.Unirest; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.polypheny.simpleclient.query.Query; +import org.polypheny.simpleclient.query.QueryBuilder; +import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; + +public class SingleUpdate extends QueryBuilder { + + private final LockingBenchSchema schema; + private final NumberTracker numberTracker; + + public SingleUpdate( LockingBenchSchema schema, NumberTracker numberTracker ) { + this.schema = schema; + this.numberTracker = numberTracker; + } + + @Override + public Query getNewQuery() { + String tableName = schema.getRandomEntityFullName(); + long id = numberTracker.getRandomId(); + double newScore = ThreadLocalRandom.current().nextDouble(); + boolean newVerified = ThreadLocalRandom.current().nextBoolean(); + + return new SingleUpdateQuery(tableName, id, newScore, newVerified); + } + + private static class SingleUpdateQuery extends Query { + + private final String tableName; + private final long id; + private final double newScore; + private final boolean newVerified; + + public SingleUpdateQuery(String tableName, long id, double newScore, boolean newVerified) { + super(false); // no result expected + this.tableName = tableName; + this.id = id; + this.newScore = newScore; + this.newVerified = newVerified; + } + + @Override + public String getSql() { + return "UPDATE " + tableName + " SET score = " + newScore + ", is_verified = " + newVerified + " WHERE id = " + id; + } + + @Override + public String getParameterizedSqlQuery() { + return "UPDATE " + tableName + " SET score = ?, is_verified = ? WHERE id = ?"; + } + + @Override + public Map> getParameterValues() { + Map> map = new HashMap<>(); + map.put(1, new ImmutablePair<>(DataTypes.DECIMAL, newScore)); + map.put(2, new ImmutablePair<>(DataTypes.BOOLEAN, newVerified)); + map.put(3, new ImmutablePair<>(DataTypes.BIGINT, id)); + return map; + } + + @Override + public HttpRequest getRest() { + return Unirest.patch("{protocol}://{host}:{port}/restapi/v1/res/public." + tableName) + .queryString("_where", "public." + tableName + ".id.eq." + id) + .header("Content-Type", "application/json") + .body("{\"public." + tableName + ".score\": " + newScore + + ", \"public." + tableName + ".is_verified\": " + newVerified + "}"); + } + + @Override + public String getMongoQl() { + return "db." + tableName + ".updateOne({ \"id\": " + id + " }, { $set: { \"score\": " + newScore + + ", \"is_verified\": " + newVerified + " } })"; + } + } +} diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties b/src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties new file mode 100644 index 0000000..37ff3d6 --- /dev/null +++ b/src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties @@ -0,0 +1,31 @@ +# +# The MIT License (MIT) +# +# Copyright (c) 2019-3/21/25, 2:07?PM The Polypheny Project +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +numberOfEntriesPerTable = 100 +maxBatchSize = 100 + +progressReportBase = 100 +numberOfWarmUpIterations = 4 +numberOfQueries = 1000 + From f451f5702f6f384e7873de96c5fdb4350ae9fa8f Mon Sep 17 00:00:00 2001 From: Tobias Hafner Date: Sun, 23 Mar 2025 07:39:12 +0100 Subject: [PATCH 2/6] Improve analysis --- .../scenario/EvaluationThread.java | 57 +++++++++---------- .../simpleclient/scenario/Scenario.java | 18 +++--- .../ErrorHandlingEvaluationThread.java | 13 ++++- .../ErrorHandlingPolyphenyScenario.java | 13 ++++- .../scenario/scalingBench/LockingBench.java | 15 ++++- .../scalingbench/scalingbench.properties | 2 +- 6 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThread.java b/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThread.java index bec338a..b6132f6 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThread.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/EvaluationThread.java @@ -67,16 +67,15 @@ public EvaluationThread( Queue queryList, Executor executor, Set @Override public void run() { - while (!queries.isEmpty() && !abort) { + while ( !queries.isEmpty() && !abort ) { QueryListEntry queryListEntry = queries.poll(); - if (queryListEntry == null) { + if ( queryListEntry == null ) { break; } - long measuredTime = executeAndMeasure(queryListEntry); - recordMeasuredTime(queryListEntry, measuredTime); + executeAndMeasure( queryListEntry ); - if (commitAfterEveryQuery) { + if ( commitAfterEveryQuery ) { commitSafely(); } } @@ -85,45 +84,45 @@ public void run() { executor.flushCsvWriter(); } - protected long executeAndMeasure(QueryListEntry queryListEntry) { + + protected void executeAndMeasure( QueryListEntry queryListEntry ) { long startTime = System.nanoTime(); try { - executor.executeQuery(queryListEntry.query); - } catch (ExecutorException e) { - log.error("Caught exception while executing queries", e); - threadMonitor.notifyAboutError(e); - rollbackSafely(e); - throw new RuntimeException(e); + executor.executeQuery( queryListEntry.query ); + } catch ( ExecutorException e ) { + log.error( "Caught exception while executing queries", e ); + threadMonitor.notifyAboutError( e ); + rollbackSafely( e ); + throw new RuntimeException( e ); } - return System.nanoTime() - startTime; - } - - protected void recordMeasuredTime(QueryListEntry entry, long measuredTime) { - measuredTimes.add(measuredTime); - measuredTimePerQueryType.get(entry.templateId).add(measuredTime); - for (Integer id : entry.templateIds) { - if (!id.equals(entry.templateId)) { - measuredTimePerQueryType.get(id).add(measuredTime); + long measuredTime = System.nanoTime() - startTime; + measuredTimes.add( measuredTime ); + measuredTimePerQueryType.get( queryListEntry.templateId ).add( measuredTime ); + for ( Integer id : queryListEntry.templateIds ) { + if ( !id.equals( queryListEntry.templateId ) ) { + measuredTimePerQueryType.get( id ).add( measuredTime ); } } } + protected void commitSafely() { try { executor.executeCommit(); - } catch (ExecutorException e) { - log.error("Caught exception while committing", e); - threadMonitor.notifyAboutError(e); - rollbackSafely(e); - throw new RuntimeException(e); + } catch ( ExecutorException e ) { + log.error( "Caught exception while committing", e ); + threadMonitor.notifyAboutError( e ); + rollbackSafely( e ); + throw new RuntimeException( e ); } } - protected void rollbackSafely(Exception originalException) { + + protected void rollbackSafely( Exception originalException ) { try { executor.executeRollback(); - } catch (ExecutorException rollbackException) { - log.error("Error while rollback", originalException); + } catch ( ExecutorException rollbackException ) { + log.error( "Error while rollback", originalException ); } } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/Scenario.java b/src/main/java/org/polypheny/simpleclient/scenario/Scenario.java index e7614f8..ca89546 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/Scenario.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/Scenario.java @@ -81,18 +81,18 @@ protected void calculateResults( Map queryTypes, Properties pro long min = summaryStatistics.getMin(); double stddev = calculateSampleStandardDeviation( time, mean ); - properties.put( "queryTypes_" + templateId + "_mean", processDoubleValue( mean ) ); + properties.put( "queryTypes_" + templateId + "_mean [ms]", processDoubleValue( mean ) ); if ( ChronosAgent.STORE_INDIVIDUAL_QUERY_TIMES ) { - properties.put( "queryTypes_" + templateId + "_all", Joiner.on( ',' ).join( time ) ); + properties.put( "queryTypes_" + templateId + "_all [ms]", Joiner.on( ',' ).join( time ) ); } - properties.put( "queryTypes_" + templateId + "_stddev", processDoubleValue( stddev ) ); - properties.put( "queryTypes_" + templateId + "_min", min / 1_000_000L ); - properties.put( "queryTypes_" + templateId + "_max", max / 1_000_000L ); + properties.put( "queryTypes_" + templateId + "_stddev [ms]", processDoubleValue( stddev ) ); + properties.put( "queryTypes_" + templateId + "_min [ms]", min / 1_000_000L ); + properties.put( "queryTypes_" + templateId + "_max [ms]", max / 1_000_000L ); } else { - properties.put( "queryTypes_" + templateId + "_mean", 0 ); - properties.put( "queryTypes_" + templateId + "_stddev", 0 ); - properties.put( "queryTypes_" + templateId + "_min", 0 ); - properties.put( "queryTypes_" + templateId + "_max", 0 ); + properties.put( "queryTypes_" + templateId + "_mean [ms]", 0 ); + properties.put( "queryTypes_" + templateId + "_stddev [ms]", 0 ); + properties.put( "queryTypes_" + templateId + "_min [ms]", 0 ); + properties.put( "queryTypes_" + templateId + "_max [ms]", 0 ); } properties.put( "queryTypes_" + templateId + "_example", queryTypes.get( templateId ) ); } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java index ecd71ae..90cc428 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java @@ -59,14 +59,23 @@ public boolean isExpectedException( Throwable e ) { @Override - protected long executeAndMeasure( QueryListEntry queryListEntry ) { + protected void executeAndMeasure( QueryListEntry queryListEntry ) { long startTime = System.nanoTime(); try { executor.executeQuery( queryListEntry.query ); + + long measuredTime = System.nanoTime() - startTime; + measuredTimes.add( measuredTime ); + measuredTimePerQueryType.get( queryListEntry.templateId ).add( measuredTime ); + for ( Integer id : queryListEntry.templateIds ) { + if ( !id.equals( queryListEntry.templateId ) ) { + measuredTimePerQueryType.get( id ).add( measuredTime ); + } + } } catch ( ExecutorException e ) { throwIfUnexpected( e, "executing queries", queryListEntry.query.getSql() ); } - return System.nanoTime() - startTime; + } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java index fe6554f..2608a04 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java @@ -113,9 +113,18 @@ protected long commonExecuteWithExpectedErrors( List queries, Pr @Override public void analyze( Properties properties, File outputDirectory ) { - super.analyze( properties, outputDirectory ); + properties.put( "executeRuntime [s]", executeRuntime / 1000000000.0 ); + properties.put( "measuredTime [ns]", calculateMean( measuredTimes ) ); + + properties.put( "numberOfQueries", measuredTimes.size() + failedQueries ); + properties.put( "numberOfSuccessfulQueries", measuredTimes.size() ); properties.put( "numberOfFailedQueries", failedQueries ); - properties.put( "querySuccessRatio", (measuredTimes.size() - failedQueries) / measuredTimes.size()); + + properties.put( "throughput [succ.q/s]", measuredTimes.size() / (executeRuntime / 1000000000.0) ); + properties.put( "querySuccessRatio", measuredTimes.size() / (measuredTimes.size() + failedQueries)); + + measuredTimePerQueryType.forEach( ( templateId, time ) -> calculateResults( queryTypes, properties, templateId, time ) ); + properties.put( "queryTypes_maxId", queryTypes.size() ); } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java index d3b8d05..a56d31c 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java @@ -173,9 +173,22 @@ public synchronized void store( OutputStream out, String comments) throws IOExce } }; - File analysisFile = new File(outputDirectory, "analysis.txt"); + String fileName = String.format( + "analysis_S%d_N%d_E%d_R%f.txt", + config.sessionCount, + config.namespaceCount, + config.entityCount, + config.readWriteRatio); + + File analysisFile = new File(outputDirectory, fileName); analyze(analysis, analysisFile); + analysis.put( "number_of_sessions", config.sessionCount ); + analysis.put( "number_of_namespaces", config.namespaceCount ); + analysis.put("number_of_entities_per_namespace", config.entityCount ); + analysis.put( "number_of_queries", config.numberOfQueries ); + analysis.put( "read_write_ratio", config.readWriteRatio ); + try (FileOutputStream out = new FileOutputStream(analysisFile)) { analysis.store(out, "Analysis results"); } catch (IOException e) { diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties b/src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties index 37ff3d6..39d45c7 100644 --- a/src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties +++ b/src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties @@ -27,5 +27,5 @@ maxBatchSize = 100 progressReportBase = 100 numberOfWarmUpIterations = 4 -numberOfQueries = 1000 +numberOfQueries = 10000 From 0b979ca7c9f772a628450ad7766b5d151701ad26 Mon Sep 17 00:00:00 2001 From: Tobias Hafner Date: Mon, 24 Mar 2025 08:20:59 +0100 Subject: [PATCH 3/6] Fix parameter count --- .../scenario/scalingBench/queryBuilder/SingleInsert.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java index 7dd0a7f..5dee838 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java @@ -130,7 +130,7 @@ public String getSqlRowExpression() { @Override public String getParameterizedSqlQuery() { - return String.format( SQL, tableName ) + "(?, ?, ?, ?, ?, ?)"; + return String.format( SQL, tableName ) + "(?, ?, ?, ?)"; } From adc7cb3fb436c9d20133d2421739f49c1695524b Mon Sep 17 00:00:00 2001 From: Tobias Hafner Date: Mon, 24 Mar 2025 09:45:40 +0100 Subject: [PATCH 4/6] Fix analysis report --- .../scalingBench/ErrorHandlingEvaluationThread.java | 1 + .../ErrorHandlingPolyphenyScenario.java | 13 +++++++++---- .../scenario/scalingBench/LockingBench.java | 9 ++++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java index 90cc428..accb64d 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java @@ -65,6 +65,7 @@ protected void executeAndMeasure( QueryListEntry queryListEntry ) { executor.executeQuery( queryListEntry.query ); long measuredTime = System.nanoTime() - startTime; + measuredTimes.add( measuredTime ); measuredTimePerQueryType.get( queryListEntry.templateId ).add( measuredTime ); for ( Integer id : queryListEntry.templateIds ) { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java index 2608a04..758237e 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java @@ -114,18 +114,23 @@ protected long commonExecuteWithExpectedErrors( List queries, Pr @Override public void analyze( Properties properties, File outputDirectory ) { properties.put( "executeRuntime [s]", executeRuntime / 1000000000.0 ); - properties.put( "measuredTime [ns]", calculateMean( measuredTimes ) ); + properties.put( "measuredTime [ms]", calculateMean( measuredTimes ) ); - properties.put( "numberOfQueries", measuredTimes.size() + failedQueries ); - properties.put( "numberOfSuccessfulQueries", measuredTimes.size() ); + properties.put( "numberOfQueries", measuredTimes.size()); + properties.put( "numberOfSuccessfulQueries", measuredTimes.size() - failedQueries); properties.put( "numberOfFailedQueries", failedQueries ); + properties.put("successRatio", calculateSuccessRatio() ); properties.put( "throughput [succ.q/s]", measuredTimes.size() / (executeRuntime / 1000000000.0) ); - properties.put( "querySuccessRatio", measuredTimes.size() / (measuredTimes.size() + failedQueries)); measuredTimePerQueryType.forEach( ( templateId, time ) -> calculateResults( queryTypes, properties, templateId, time ) ); properties.put( "queryTypes_maxId", queryTypes.size() ); } + private double calculateSuccessRatio() { + double unroundedRatio = (1.0 * measuredTimes.size() - failedQueries) / measuredTimes.size(); + return Math.round( unroundedRatio * 100.0 ) / 100.0; + } + } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java index a56d31c..96cc6d2 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java @@ -183,11 +183,10 @@ public synchronized void store( OutputStream out, String comments) throws IOExce File analysisFile = new File(outputDirectory, fileName); analyze(analysis, analysisFile); - analysis.put( "number_of_sessions", config.sessionCount ); - analysis.put( "number_of_namespaces", config.namespaceCount ); - analysis.put("number_of_entities_per_namespace", config.entityCount ); - analysis.put( "number_of_queries", config.numberOfQueries ); - analysis.put( "read_write_ratio", config.readWriteRatio ); + analysis.put( "numberOfSessions", config.sessionCount ); + analysis.put( "numberOfNamespaces", config.namespaceCount ); + analysis.put("numberOfEntitiesPerNamespace", config.entityCount ); + analysis.put( "readWriteRatio", config.readWriteRatio ); try (FileOutputStream out = new FileOutputStream(analysisFile)) { analysis.store(out, "Analysis results"); From e67e155d8d7193480ecc177106906ec36377aa8a Mon Sep 17 00:00:00 2001 From: Tobias Hafner Date: Mon, 24 Mar 2025 09:52:41 +0100 Subject: [PATCH 5/6] Refactor package name --- .../main/LockingBenchScenario.java | 6 +++--- .../{scalingBench => lockingBench}/Entity.java | 2 +- .../ErrorHandlingEvaluationThread.java | 2 +- .../ErrorHandlingPolyphenyScenario.java | 2 +- .../LockingBench.java | 18 +++++++++--------- .../LockingBenchConfig.java | 2 +- .../LockingBenchDataGenerator.java | 4 ++-- .../LockingBenchSchema.java | 5 ++--- .../NumberTracker.java | 2 +- .../queryBuilder/CreateNamespace.java | 2 +- .../queryBuilder/FullRead.java | 4 ++-- .../queryBuilder/RangeRead.java | 6 +++--- .../queryBuilder/RangeUpdate.java | 6 +++--- .../queryBuilder/SingleDelete.java | 6 +++--- .../queryBuilder/SingleInsert.java | 8 +++----- .../queryBuilder/SingleRead.java | 6 +++--- .../queryBuilder/SingleUpdate.java | 6 +++--- .../lockingbench.properties} | 0 18 files changed, 42 insertions(+), 45 deletions(-) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/Entity.java (96%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/ErrorHandlingEvaluationThread.java (98%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/ErrorHandlingPolyphenyScenario.java (99%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/LockingBench.java (95%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/LockingBenchConfig.java (97%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/LockingBenchDataGenerator.java (96%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/LockingBenchSchema.java (95%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/NumberTracker.java (97%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/queryBuilder/CreateNamespace.java (97%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/queryBuilder/FullRead.java (95%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/queryBuilder/RangeRead.java (94%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/queryBuilder/RangeUpdate.java (95%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/queryBuilder/SingleDelete.java (94%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/queryBuilder/SingleInsert.java (95%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/queryBuilder/SingleRead.java (94%) rename src/main/java/org/polypheny/simpleclient/scenario/{scalingBench => lockingBench}/queryBuilder/SingleUpdate.java (95%) rename src/main/resources/org/polypheny/simpleclient/scenario/{scalingbench/scalingbench.properties => lockingBench/lockingbench.properties} (100%) diff --git a/src/main/java/org/polypheny/simpleclient/main/LockingBenchScenario.java b/src/main/java/org/polypheny/simpleclient/main/LockingBenchScenario.java index 70201fc..a83af3c 100644 --- a/src/main/java/org/polypheny/simpleclient/main/LockingBenchScenario.java +++ b/src/main/java/org/polypheny/simpleclient/main/LockingBenchScenario.java @@ -30,8 +30,8 @@ import java.util.Properties; import lombok.extern.slf4j.Slf4j; import org.polypheny.simpleclient.executor.Executor.ExecutorFactory; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBench; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchConfig; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBench; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBenchConfig; @Slf4j public class LockingBenchScenario { @@ -71,7 +71,7 @@ public static void workload( ExecutorFactory executorFactory, int sessionCount, private static Properties getProperties(int sessionCount) { Properties props = new Properties(); try { - props.load( Objects.requireNonNull( ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties" ) ) ); + props.load( Objects.requireNonNull( ClassLoader.getSystemResourceAsStream( "org/polypheny/simpleclient/scenario/lockingBench/lockingbench.properties" ) ) ); props.put("numberOfThreads", String.valueOf( sessionCount ) ); } catch ( IOException e ) { log.error( "Exception while reading properties file", e ); diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/Entity.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/Entity.java similarity index 96% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/Entity.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/Entity.java index fa49903..bea5aee 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/Entity.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/Entity.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench; +package org.polypheny.simpleclient.scenario.lockingBench; import lombok.Getter; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingEvaluationThread.java similarity index 98% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingEvaluationThread.java index accb64d..1515b57 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingEvaluationThread.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingEvaluationThread.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench; +package org.polypheny.simpleclient.scenario.lockingBench; import java.util.Map; import java.util.Queue; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingPolyphenyScenario.java similarity index 99% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingPolyphenyScenario.java index 758237e..f303c84 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/ErrorHandlingPolyphenyScenario.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingPolyphenyScenario.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench; +package org.polypheny.simpleclient.scenario.lockingBench; import java.io.File; import java.util.ArrayList; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBench.java similarity index 95% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBench.java index 96cc6d2..d627db5 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBench.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBench.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench; +package org.polypheny.simpleclient.scenario.lockingBench; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -51,14 +51,14 @@ import org.polypheny.simpleclient.query.Query; import org.polypheny.simpleclient.query.QueryBuilder; import org.polypheny.simpleclient.query.QueryListEntry; -import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker.Mode; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.FullRead; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.RangeRead; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.RangeUpdate; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleDelete; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleInsert; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleRead; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleUpdate; +import org.polypheny.simpleclient.scenario.lockingBench.NumberTracker.Mode; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.FullRead; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.RangeRead; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.RangeUpdate; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.SingleDelete; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.SingleInsert; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.SingleRead; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.SingleUpdate; @Slf4j diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchConfig.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchConfig.java similarity index 97% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchConfig.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchConfig.java index 4bf0449..d70fb27 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchConfig.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchConfig.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench; +package org.polypheny.simpleclient.scenario.lockingBench; import java.util.Properties; import org.polypheny.simpleclient.scenario.AbstractConfig; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchDataGenerator.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchDataGenerator.java similarity index 96% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchDataGenerator.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchDataGenerator.java index 2539639..abc7cb2 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchDataGenerator.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchDataGenerator.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench; +package org.polypheny.simpleclient.scenario.lockingBench; import java.util.LinkedList; import java.util.List; @@ -30,7 +30,7 @@ import org.polypheny.simpleclient.executor.ExecutorException; import org.polypheny.simpleclient.main.ProgressReporter; import org.polypheny.simpleclient.query.BatchableInsert; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.SingleInsert; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.SingleInsert; public class LockingBenchDataGenerator { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchSchema.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchSchema.java similarity index 95% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchSchema.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchSchema.java index ae11a82..3426a73 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/LockingBenchSchema.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBenchSchema.java @@ -22,17 +22,16 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench; +package org.polypheny.simpleclient.scenario.lockingBench; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.IntStream; import lombok.Getter; import org.polypheny.simpleclient.query.Query; import org.polypheny.simpleclient.scenario.multimedia.queryBuilder.CreateTable; -import org.polypheny.simpleclient.scenario.scalingBench.queryBuilder.CreateNamespace; +import org.polypheny.simpleclient.scenario.lockingBench.queryBuilder.CreateNamespace; @Getter public class LockingBenchSchema { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/NumberTracker.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/NumberTracker.java similarity index 97% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/NumberTracker.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/NumberTracker.java index 61d3bbe..86f17f2 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/NumberTracker.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/NumberTracker.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench; +package org.polypheny.simpleclient.scenario.lockingBench; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicLong; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/CreateNamespace.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/CreateNamespace.java similarity index 97% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/CreateNamespace.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/CreateNamespace.java index 3438dbc..32160af 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/CreateNamespace.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/CreateNamespace.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; +package org.polypheny.simpleclient.scenario.lockingBench.queryBuilder; import java.util.Map; import kong.unirest.core.HttpRequest; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/FullRead.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/FullRead.java similarity index 95% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/FullRead.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/FullRead.java index 491d566..ed69f37 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/FullRead.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/FullRead.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; +package org.polypheny.simpleclient.scenario.lockingBench.queryBuilder; import java.util.Map; import kong.unirest.core.HttpRequest; @@ -30,7 +30,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.polypheny.simpleclient.query.Query; import org.polypheny.simpleclient.query.QueryBuilder; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBenchSchema; public class FullRead extends QueryBuilder { private final LockingBenchSchema schema; diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeRead.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/RangeRead.java similarity index 94% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeRead.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/RangeRead.java index 559202f..70df620 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeRead.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/RangeRead.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; +package org.polypheny.simpleclient.scenario.lockingBench.queryBuilder; import java.util.HashMap; import java.util.Map; @@ -31,8 +31,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.polypheny.simpleclient.query.Query; import org.polypheny.simpleclient.query.QueryBuilder; -import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; +import org.polypheny.simpleclient.scenario.lockingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBenchSchema; public class RangeRead extends QueryBuilder { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeUpdate.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/RangeUpdate.java similarity index 95% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeUpdate.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/RangeUpdate.java index 1a2b468..3a812ba 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/RangeUpdate.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/RangeUpdate.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; +package org.polypheny.simpleclient.scenario.lockingBench.queryBuilder; import java.util.HashMap; import java.util.Map; @@ -32,8 +32,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.polypheny.simpleclient.query.Query; import org.polypheny.simpleclient.query.QueryBuilder; -import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; +import org.polypheny.simpleclient.scenario.lockingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBenchSchema; public class RangeUpdate extends QueryBuilder { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleDelete.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleDelete.java similarity index 94% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleDelete.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleDelete.java index 6740cca..6c38322 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleDelete.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleDelete.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; +package org.polypheny.simpleclient.scenario.lockingBench.queryBuilder; import java.util.HashMap; import java.util.Map; @@ -31,8 +31,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.polypheny.simpleclient.query.Query; import org.polypheny.simpleclient.query.QueryBuilder; -import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; +import org.polypheny.simpleclient.scenario.lockingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBenchSchema; public class SingleDelete extends QueryBuilder { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleInsert.java similarity index 95% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleInsert.java index 5dee838..243f2f3 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleInsert.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleInsert.java @@ -22,13 +22,11 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; +package org.polypheny.simpleclient.scenario.lockingBench.queryBuilder; -import com.devskiller.jfairy.Fairy; import com.google.common.collect.ImmutableList; import com.google.gson.JsonObject; import java.util.HashMap; -import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; @@ -36,8 +34,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.polypheny.simpleclient.query.BatchableInsert; import org.polypheny.simpleclient.query.QueryBuilder; -import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; +import org.polypheny.simpleclient.scenario.lockingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBenchSchema; public class SingleInsert extends QueryBuilder { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleRead.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleRead.java similarity index 94% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleRead.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleRead.java index fccc0ed..8c005df 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleRead.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleRead.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; +package org.polypheny.simpleclient.scenario.lockingBench.queryBuilder; import java.util.HashMap; import java.util.Map; @@ -31,8 +31,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.polypheny.simpleclient.query.Query; import org.polypheny.simpleclient.query.QueryBuilder; -import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; +import org.polypheny.simpleclient.scenario.lockingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBenchSchema; public class SingleRead extends QueryBuilder { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleUpdate.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleUpdate.java similarity index 95% rename from src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleUpdate.java rename to src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleUpdate.java index 8ebe571..f6849e9 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/scalingBench/queryBuilder/SingleUpdate.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/queryBuilder/SingleUpdate.java @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.polypheny.simpleclient.scenario.scalingBench.queryBuilder; +package org.polypheny.simpleclient.scenario.lockingBench.queryBuilder; import java.util.HashMap; import java.util.Map; @@ -32,8 +32,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.polypheny.simpleclient.query.Query; import org.polypheny.simpleclient.query.QueryBuilder; -import org.polypheny.simpleclient.scenario.scalingBench.NumberTracker; -import org.polypheny.simpleclient.scenario.scalingBench.LockingBenchSchema; +import org.polypheny.simpleclient.scenario.lockingBench.NumberTracker; +import org.polypheny.simpleclient.scenario.lockingBench.LockingBenchSchema; public class SingleUpdate extends QueryBuilder { diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties b/src/main/resources/org/polypheny/simpleclient/scenario/lockingBench/lockingbench.properties similarity index 100% rename from src/main/resources/org/polypheny/simpleclient/scenario/scalingbench/scalingbench.properties rename to src/main/resources/org/polypheny/simpleclient/scenario/lockingBench/lockingbench.properties From 5eb0b93484c866be71b6bd921155ad18c95774ff Mon Sep 17 00:00:00 2001 From: Tobias Hafner Date: Sun, 11 May 2025 14:51:45 +0200 Subject: [PATCH 6/6] adjust parameters --- build.gradle | 2 ++ .../ErrorHandlingPolyphenyScenario.java | 22 +++++++++++++++++++ .../scenario/lockingBench/LockingBench.java | 7 ++++-- .../lockingBench/lockingbench.properties | 2 +- .../scenario/oltpbench/tpcc.properties | 4 ++-- .../scenario/oltpbench/tpch.properties | 4 ++-- .../scenario/oltpbench/ycsb.properties | 4 ++-- 7 files changed, 36 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index cb4f0a0..c7c067d 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ buildscript { url = uri("https://plugins.gradle.org/m2/") } } + dependencies { // Shadowing; used to make a fat jar (https://github.com/johnrengelman/shadow) classpath group: "com.github.johnrengelman", name: "shadow", version: "8.1.1" @@ -192,6 +193,7 @@ shadowJar { mergeServiceFiles { setPath("META-INF/services") include("io.grpc.*") + include("java.sql.Driver") } // Include everything from 'libs' but rename JARs to another extension to trick the plugin from('libs') { diff --git a/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingPolyphenyScenario.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingPolyphenyScenario.java index f303c84..2094bd0 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingPolyphenyScenario.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/ErrorHandlingPolyphenyScenario.java @@ -24,7 +24,10 @@ package org.polypheny.simpleclient.scenario.lockingBench; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -132,5 +135,24 @@ private double calculateSuccessRatio() { return Math.round( unroundedRatio * 100.0 ) / 100.0; } + public void storeIndividualExecutionTimes(File outputDirectory, String baseFileName) { + if (!outputDirectory.exists()) { + outputDirectory.mkdirs(); + } + + measuredTimePerQueryType.forEach((templateId, times) -> { + File outputFile = new File(outputDirectory, baseFileName + "_template" + templateId + ".txt"); + + try ( BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) { + for (Long time : times) { + writer.write(time.toString()); + writer.newLine(); + } + } catch ( IOException e) { + throw new RuntimeException( "Exception while exporting individual execution times.", e ); + } + }); + } + } diff --git a/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBench.java b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBench.java index d627db5..5217382 100644 --- a/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBench.java +++ b/src/main/java/org/polypheny/simpleclient/scenario/lockingBench/LockingBench.java @@ -173,13 +173,15 @@ public synchronized void store( OutputStream out, String comments) throws IOExce } }; - String fileName = String.format( - "analysis_S%d_N%d_E%d_R%f.txt", + String baseFileName = String.format( + "analysis_S%d_N%d_E%d_R%f", config.sessionCount, config.namespaceCount, config.entityCount, config.readWriteRatio); + String fileName = baseFileName + ".txt"; + File analysisFile = new File(outputDirectory, fileName); analyze(analysis, analysisFile); @@ -193,6 +195,7 @@ public synchronized void store( OutputStream out, String comments) throws IOExce } catch (IOException e) { log.error("Exception while generating analysis", e); } + storeIndividualExecutionTimes( outputDirectory, baseFileName ); } diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/lockingBench/lockingbench.properties b/src/main/resources/org/polypheny/simpleclient/scenario/lockingBench/lockingbench.properties index 39d45c7..fd13e43 100644 --- a/src/main/resources/org/polypheny/simpleclient/scenario/lockingBench/lockingbench.properties +++ b/src/main/resources/org/polypheny/simpleclient/scenario/lockingBench/lockingbench.properties @@ -22,7 +22,7 @@ # SOFTWARE. # -numberOfEntriesPerTable = 100 +numberOfEntriesPerTable = 1000 maxBatchSize = 100 progressReportBase = 100 diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/tpcc.properties b/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/tpcc.properties index 8741801..94b0ab8 100644 --- a/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/tpcc.properties +++ b/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/tpcc.properties @@ -1,4 +1,4 @@ -numberOfThreads = 1 +numberOfThreads = 16 progressReportBase = 100 workloadMonitoringExecutingWorkload = true workloadMonitoringLoadingData = true @@ -14,4 +14,4 @@ newOrderWeight = 45 paymentWeight = 43 orderStatusWeight = 4 deliveryWeight = 4 -stockLevelWeight = 4 \ No newline at end of file +stockLevelWeight = 4 diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/tpch.properties b/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/tpch.properties index 517ed59..4ec4f9b 100644 --- a/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/tpch.properties +++ b/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/tpch.properties @@ -1,4 +1,4 @@ -numberOfThreads = 1 +numberOfThreads = 16 progressReportBase = 100 workloadMonitoringExecutingWorkload = true workloadMonitoringLoadingData = true @@ -10,4 +10,4 @@ numberOfWarmUpIterations = 0 transactionTypes = Q1,Q3,Q4,Q6,Q9,Q12,Q13,Q14,Q16,Q17 -partitionItemTable = false \ No newline at end of file +partitionItemTable = false diff --git a/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/ycsb.properties b/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/ycsb.properties index 7958c5a..d016161 100644 --- a/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/ycsb.properties +++ b/src/main/resources/org/polypheny/simpleclient/scenario/oltpbench/ycsb.properties @@ -1,4 +1,4 @@ -numberOfThreads = 1 +numberOfThreads = 16 progressReportBase = 100 workloadMonitoringExecutingWorkload = true workloadMonitoringLoadingData = true @@ -16,4 +16,4 @@ updateRecordWeight = 10 deleteRecordWeight = 10 readModifyWriteRecordWeight = 10 -partitionTable = false \ No newline at end of file +partitionTable = false