From 3b36502ee17048924acd8764b012d1125cf024fb Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 21 Jul 2024 13:17:41 +0900 Subject: [PATCH 01/57] Replace package to connector --- .../src/main/scala/benchmark/{ => connector}/jdbc/Insert.scala | 2 +- .../src/main/scala/benchmark/{ => connector}/jdbc/Select.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename benchmark/src/main/scala/benchmark/{ => connector}/jdbc/Insert.scala (98%) rename benchmark/src/main/scala/benchmark/{ => connector}/jdbc/Select.scala (98%) diff --git a/benchmark/src/main/scala/benchmark/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala similarity index 98% rename from benchmark/src/main/scala/benchmark/jdbc/Insert.scala rename to benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index 8e31a1309..bf4401835 100644 --- a/benchmark/src/main/scala/benchmark/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -4,7 +4,7 @@ * For more information see LICENSE or https://opensource.org/licenses/MIT */ -package benchmark.jdbc +package benchmark.connector.jdbc import java.util.concurrent.TimeUnit diff --git a/benchmark/src/main/scala/benchmark/jdbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala similarity index 98% rename from benchmark/src/main/scala/benchmark/jdbc/Select.scala rename to benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala index a723a141d..a3b237257 100644 --- a/benchmark/src/main/scala/benchmark/jdbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala @@ -4,7 +4,7 @@ * For more information see LICENSE or https://opensource.org/licenses/MIT */ -package benchmark.jdbc +package benchmark.connector.jdbc import java.util.concurrent.TimeUnit From 8a91fde54e9617d31e60f2aece3deb806812df5f Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 21 Jul 2024 13:43:12 +0900 Subject: [PATCH 02/57] Added connector dependsOn --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f9900b1be..a4021e77e 100644 --- a/build.sbt +++ b/build.sbt @@ -202,7 +202,7 @@ lazy val benchmark = (project in file("benchmark")) slick ) ) - .dependsOn(jdbcConnector.jvm, schema.jvm) + .dependsOn(jdbcConnector.jvm, connector.jvm, schema.jvm) .enablePlugins(JmhPlugin, AutomateHeaderPlugin, NoPublishPlugin) lazy val docs = (project in file("docs")) From a384290480c32fe22a7b9d48e3f03916af71e6aa Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 21 Jul 2024 13:47:43 +0900 Subject: [PATCH 03/57] Create benchmark sql --- database/benchmark.sql | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 database/benchmark.sql diff --git a/database/benchmark.sql b/database/benchmark.sql new file mode 100644 index 000000000..1b6ed8f31 --- /dev/null +++ b/database/benchmark.sql @@ -0,0 +1,8 @@ +CREATE DATABASE `benchmark` DEFAULT CHARACTER SET utf8mb4; + +USE `benchmark`; + +CREATE TABLE `insert_test` ( + `c1` INT NOT NULL, + `c2` VARCHAR(255) NOT NULL +); From 1542c806b743bba1622ce93150e5aa9cf18fc345 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 21 Jul 2024 22:11:11 +0900 Subject: [PATCH 04/57] Change use Cats Effect Resorce --- .../benchmark/connector/jdbc/Insert.scala | 84 ++++++++++--------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index bf4401835..f0bd1ab25 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -8,20 +8,24 @@ package benchmark.connector.jdbc import java.util.concurrent.TimeUnit -import scala.util.Using import scala.compiletime.uninitialized import com.mysql.cj.jdbc.MysqlDataSource import org.openjdk.jmh.annotations.* +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import ldbc.sql.Connection + @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) class Insert: @volatile - var dataSource: MysqlDataSource = uninitialized + var connection: Resource[IO, Connection[IO]] = uninitialized @volatile var values: String = uninitialized @@ -31,12 +35,16 @@ class Insert: @Setup def setupDataSource(): Unit = - dataSource = new MysqlDataSource() - dataSource.setServerName("127.0.0.1") - dataSource.setPortNumber(13306) - dataSource.setDatabaseName("world") - dataSource.setUser("ldbc") - dataSource.setPassword("password") + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("benchmark") + ds.setUser("ldbc") + ds.setPassword("password") + + val datasource = jdbc.connector.MysqlDataSource[IO](ds) + + connection = Resource.make(datasource.getConnection)(_.close()) values = (1 to len).map(_ => "(?, ?)").mkString(",") @@ -46,36 +54,34 @@ class Insert: var len: Int = uninitialized @Benchmark - def insertN: Unit = - Using - .Manager { use => - val connection = use(dataSource.getConnection) - connection.setAutoCommit(false) - val statement = use(connection.prepareStatement(s"INSERT INTO test (c1, c2) VALUES $values")) - records.zipWithIndex.foreach { - case ((id, value), index) => - statement.setInt(index * 2 + 1, id) - statement.setString(index * 2 + 2, value) + def insertN(): Unit = + connection.use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES $values") + _ <- records.zipWithIndex.foldLeft(IO.unit) { + case (acc, ((id, value), index)) => + acc *> + statement.setInt(index * 2 + 1, id) *> + statement.setString(index * 2 + 2, value) } - statement.executeUpdate() - connection.rollback() - } - .getOrElse(throw new RuntimeException("Error during database operation")) + _ <- statement.executeUpdate() + yield () + }.unsafeRunSync() - @Benchmark - def batchN: Unit = - Using - .Manager { use => - val connection = use(dataSource.getConnection) - connection.setAutoCommit(false) - val statement = use(connection.prepareStatement("INSERT INTO test (c1, c2) VALUES (?, ?)")) - records.foreach { - case (id, value) => - statement.setInt(1, id) - statement.setString(2, value) - statement.addBatch() - } - statement.executeBatch() - connection.rollback() - } - .getOrElse(throw new RuntimeException("Error during database operation")) + //@Benchmark + //def batchN: Unit = + // Using + // .Manager { use => + // val connection = use(dataSource.getConnection) + // connection.setAutoCommit(false) + // val statement = use(connection.prepareStatement("INSERT INTO insert_test (c1, c2) VALUES (?, ?)")) + // records.foreach { + // case (id, value) => + // statement.setInt(1, id) + // statement.setString(2, value) + // statement.addBatch() + // } + // statement.executeBatch() + // connection.rollback() + // } + // .getOrElse(throw new RuntimeException("Error during database operation")) From a577ea8603757e5b4b2d3d4f6a4b0148c0b7f94d Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 21 Jul 2024 22:11:23 +0900 Subject: [PATCH 05/57] Create my.conf settings --- database/my.cnf | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 database/my.cnf diff --git a/database/my.cnf b/database/my.cnf new file mode 100644 index 000000000..00db656fb --- /dev/null +++ b/database/my.cnf @@ -0,0 +1,2 @@ +[mysqld] +mysql_native_password=on From 22ed7a63c1ce212108d1aec404119db5d658069d Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 21 Jul 2024 22:11:38 +0900 Subject: [PATCH 06/57] Update MySQL version --- docker-compose.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 14e7d6635..b0d3f19a0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,8 @@ services: mysql: - image: mysql:8.0.33 + image: mysql:8.4.0 container_name: ldbc + platform: linux/amd64 environment: MYSQL_USER: 'ldbc' MYSQL_PASSWORD: 'password' @@ -10,6 +11,7 @@ services: - 13306:3306 volumes: - ./database:/docker-entrypoint-initdb.d + - ./database/my.cnf:/etc/mysql/conf.d/my.cnf healthcheck: test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ] timeout: 20s From 08294b82615e1b77880d5d58f334deb7e605b763 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 21 Jul 2024 22:11:56 +0900 Subject: [PATCH 07/57] Create ldbc Insert benchmark --- .../benchmark/connector/ldbc/Insert.scala | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala new file mode 100644 index 000000000..47e264bdb --- /dev/null +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.connector.ldbc + +import java.util.concurrent.TimeUnit + +import scala.compiletime.uninitialized + +import org.openjdk.jmh.annotations.* + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import org.typelevel.otel4s.trace.Tracer + +import ldbc.connector.* + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Insert: + + given Tracer[IO] = Tracer.noop[IO] + + @volatile + var connection: Resource[IO, LdbcConnection[IO]] = uninitialized + + @volatile + var values: String = uninitialized + + @volatile + var records: List[(Int, String)] = List.empty + + @Setup + def setup(): Unit = + connection = Connection[IO]( + host = "127.0.0.1", + port = 13306, + user = "ldbc", + password = Some("password"), + database = Some("benchmark"), + ssl = SSL.Trusted + ) + + values = (1 to len).map(_ => "(?, ?)").mkString(",") + + records = (1 to len).map(num => (num, s"record$num")).toList + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @Benchmark + def insertN(): Unit = + connection.use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES $values") + _ <- records.zipWithIndex.foldLeft(IO.unit) { + case (acc, ((id, value), index)) => + acc *> + statement.setInt(index * 2 + 1, id) *> + statement.setString(index * 2 + 2, value) + } + _ <- statement.executeUpdate() + yield () + }.unsafeRunSync() From 2467d7f24fb90aa3c2f053edde4f0e38c2195fba Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 00:29:53 +0900 Subject: [PATCH 08/57] Fixed batchN Benchmark --- .../benchmark/connector/jdbc/Insert.scala | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index f0bd1ab25..5107c94d6 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -68,20 +68,18 @@ class Insert: yield () }.unsafeRunSync() - //@Benchmark - //def batchN: Unit = - // Using - // .Manager { use => - // val connection = use(dataSource.getConnection) - // connection.setAutoCommit(false) - // val statement = use(connection.prepareStatement("INSERT INTO insert_test (c1, c2) VALUES (?, ?)")) - // records.foreach { - // case (id, value) => - // statement.setInt(1, id) - // statement.setString(2, value) - // statement.addBatch() - // } - // statement.executeBatch() - // connection.rollback() - // } - // .getOrElse(throw new RuntimeException("Error during database operation")) + @Benchmark + def batchN(): Unit = + connection.use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES (?, ?)") + _ <- records.foldLeft(IO.unit) { + case (acc, (id, value)) => + acc *> + statement.setInt(1, id) *> + statement.setString(2, value) *> + statement.addBatch() + } + _ <- statement.executeBatch() + yield () + }.unsafeRunSync() From 128a22f6a222bffa8d9bc09fe3437807c81e62bd Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 00:30:42 +0900 Subject: [PATCH 09/57] Action sbt scalafmtAll --- .../benchmark/connector/jdbc/Insert.scala | 54 ++++++++++--------- .../benchmark/connector/ldbc/Insert.scala | 34 ++++++------ 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index 5107c94d6..b6efbf6e8 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -55,31 +55,35 @@ class Insert: @Benchmark def insertN(): Unit = - connection.use { conn => - for - statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES $values") - _ <- records.zipWithIndex.foldLeft(IO.unit) { - case (acc, ((id, value), index)) => - acc *> - statement.setInt(index * 2 + 1, id) *> - statement.setString(index * 2 + 2, value) - } - _ <- statement.executeUpdate() - yield () - }.unsafeRunSync() + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES $values") + _ <- records.zipWithIndex.foldLeft(IO.unit) { + case (acc, ((id, value), index)) => + acc *> + statement.setInt(index * 2 + 1, id) *> + statement.setString(index * 2 + 2, value) + } + _ <- statement.executeUpdate() + yield () + } + .unsafeRunSync() @Benchmark def batchN(): Unit = - connection.use { conn => - for - statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES (?, ?)") - _ <- records.foldLeft(IO.unit) { - case (acc, (id, value)) => - acc *> - statement.setInt(1, id) *> - statement.setString(2, value) *> - statement.addBatch() - } - _ <- statement.executeBatch() - yield () - }.unsafeRunSync() + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES (?, ?)") + _ <- records.foldLeft(IO.unit) { + case (acc, (id, value)) => + acc *> + statement.setInt(1, id) *> + statement.setString(2, value) *> + statement.addBatch() + } + _ <- statement.executeBatch() + yield () + } + .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala index 47e264bdb..e7280777d 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala @@ -38,12 +38,12 @@ class Insert: @Setup def setup(): Unit = connection = Connection[IO]( - host = "127.0.0.1", - port = 13306, - user = "ldbc", + host = "127.0.0.1", + port = 13306, + user = "ldbc", password = Some("password"), database = Some("benchmark"), - ssl = SSL.Trusted + ssl = SSL.Trusted ) values = (1 to len).map(_ => "(?, ?)").mkString(",") @@ -55,15 +55,17 @@ class Insert: @Benchmark def insertN(): Unit = - connection.use { conn => - for - statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES $values") - _ <- records.zipWithIndex.foldLeft(IO.unit) { - case (acc, ((id, value), index)) => - acc *> - statement.setInt(index * 2 + 1, id) *> - statement.setString(index * 2 + 2, value) - } - _ <- statement.executeUpdate() - yield () - }.unsafeRunSync() + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES $values") + _ <- records.zipWithIndex.foldLeft(IO.unit) { + case (acc, ((id, value), index)) => + acc *> + statement.setInt(index * 2 + 1, id) *> + statement.setString(index * 2 + 2, value) + } + _ <- statement.executeUpdate() + yield () + } + .unsafeRunSync() From 1e84e0a218ea22ac89c947b6e60e933015a1fae9 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 00:31:46 +0900 Subject: [PATCH 10/57] Added batchN benchmark test for ldbc --- .../benchmark/connector/ldbc/Insert.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala index e7280777d..fec8c7e1a 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala @@ -69,3 +69,21 @@ class Insert: yield () } .unsafeRunSync() + + @Benchmark + def batchN(): Unit = + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES (?, ?)") + _ <- records.foldLeft(IO.unit) { + case (acc, (id, value)) => + acc *> + statement.setInt(1, id) *> + statement.setString(2, value) *> + statement.addBatch() + } + _ <- statement.executeBatch() + yield () + } + .unsafeRunSync() From ad791e223824440a11562eba0872350c559a3eb6 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 01:23:59 +0900 Subject: [PATCH 11/57] Fixed test --- .../src/test/scala/ldbc/connector/CallableStatementTest.scala | 4 ++-- .../shared/src/test/scala/ldbc/connector/ConnectionTest.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/CallableStatementTest.scala b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/CallableStatementTest.scala index 1656d514e..00260dc90 100644 --- a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/CallableStatementTest.scala +++ b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/CallableStatementTest.scala @@ -38,7 +38,7 @@ class CallableStatementTest extends CatsEffectSuite: value <- resultSet.getString(1) yield Option(value) }, - Some("8.0.33") + Some("8.4.0") ) } @@ -53,7 +53,7 @@ class CallableStatementTest extends CatsEffectSuite: case None => IO.raiseError(new Exception("No result set")) yield Option(value) }, - Some("8.0.33") + Some("8.4.0") ) } diff --git a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala index 556ce4965..4a9b036e7 100644 --- a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala +++ b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala @@ -593,7 +593,7 @@ class ConnectionTest extends CatsEffectSuite: assertIO( connection.use(_.getMetaData().map(_.getDatabaseProductVersion())), - "8.0.33" + "8.4.0" ) } From 642c486c5df8ba54a72716e0371d923cd2e0fb73 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 01:39:32 +0900 Subject: [PATCH 12/57] Correction of version differences --- .../shared/src/test/scala/ldbc/connector/ConnectionTest.scala | 3 ++- .../main/scala/ldbc/schemaspy/builder/DbmsMetaBuilder.scala | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala index 4a9b036e7..3d4d4068b 100644 --- a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala +++ b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala @@ -787,7 +787,7 @@ class ConnectionTest extends CatsEffectSuite: assertIO( connection.use(_.getMetaData().flatMap(_.getSQLKeywords())), - "ACCESSIBLE,ADD,ANALYZE,ASC,BEFORE,CASCADE,CHANGE,CONTINUE,DATABASE,DATABASES,DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DESC,DISTINCTROW,DIV,DUAL,ELSEIF,EMPTY,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FIRST_VALUE,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERATED,GROUPS,HIGH_PRIORITY,HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,INDEX,INFILE,INT1,INT2,INT3,INT4,INT8,IO_AFTER_GTIDS,IO_BEFORE_GTIDS,ITERATE,JSON_TABLE,KEY,KEYS,KILL,LAG,LAST_VALUE,LEAD,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCK,LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MASTER_BIND,MASTER_SSL_VERIFY_SERVER_CERT,MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,NO_WRITE_TO_BINLOG,NTH_VALUE,NTILE,OPTIMIZE,OPTIMIZER_COSTS,OPTION,OPTIONALLY,OUTFILE,PURGE,READ,READ_WRITE,REGEXP,RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RLIKE,SCHEMA,SCHEMAS,SECOND_MICROSECOND,SEPARATOR,SHOW,SIGNAL,SPATIAL,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT,SSL,STARTING,STORED,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,UNDO,UNLOCK,UNSIGNED,USAGE,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,VIRTUAL,WHILE,WRITE,XOR,YEAR_MONTH,ZEROFILL" + "ACCESSIBLE,ADD,ANALYZE,ASC,BEFORE,CASCADE,CHANGE,CONTINUE,DATABASE,DATABASES,DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DESC,DISTINCTROW,DIV,DUAL,ELSEIF,EMPTY,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FIRST_VALUE,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERATED,GROUPS,HIGH_PRIORITY,HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,INDEX,INFILE,INT1,INT2,INT3,INT4,INT8,IO_AFTER_GTIDS,IO_BEFORE_GTIDS,ITERATE,JSON_TABLE,KEY,KEYS,KILL,LAG,LAST_VALUE,LEAD,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCK,LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,NO_WRITE_TO_BINLOG,NTH_VALUE,NTILE,OPTIMIZE,OPTIMIZER_COSTS,OPTION,OPTIONALLY,OUTFILE,PURGE,READ,READ_WRITE,REGEXP,RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RLIKE,SCHEMA,SCHEMAS,SECOND_MICROSECOND,SEPARATOR,SHOW,SIGNAL,SPATIAL,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT,SSL,STARTING,STORED,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,UNDO,UNLOCK,UNSIGNED,USAGE,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,VIRTUAL,WHILE,WRITE,XOR,YEAR_MONTH,ZEROFILL" ) } @@ -1019,6 +1019,7 @@ class ConnectionTest extends CatsEffectSuite: yield values }, Vector( + "Table Catalog: def, Table Schema: benchmark", "Table Catalog: def, Table Schema: connector_test", "Table Catalog: def, Table Schema: information_schema", "Table Catalog: def, Table Schema: mysql", diff --git a/module/ldbc-schemaspy/src/main/scala/ldbc/schemaspy/builder/DbmsMetaBuilder.scala b/module/ldbc-schemaspy/src/main/scala/ldbc/schemaspy/builder/DbmsMetaBuilder.scala index 5644b0e4d..3ac2ac7bc 100644 --- a/module/ldbc-schemaspy/src/main/scala/ldbc/schemaspy/builder/DbmsMetaBuilder.scala +++ b/module/ldbc-schemaspy/src/main/scala/ldbc/schemaspy/builder/DbmsMetaBuilder.scala @@ -45,7 +45,7 @@ class DbmsMetaBuilder(database: Database): object DbmsMetaBuilder: private[ldbc] val sqlKeywords: Set[String] = - "ACCESSIBLE,ADD,ANALYZE,ASC,BEFORE,CASCADE,CHANGE,CONTINUE,DATABASE,DATABASES,DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DESC,DISTINCTROW,DIV,DUAL,ELSEIF,EMPTY,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FIRST_VALUE,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERATED,GROUPS,HIGH_PRIORITY,HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,INDEX,INFILE,INT1,INT2,INT3,INT4,INT8,IO_AFTER_GTIDS,IO_BEFORE_GTIDS,ITERATE,JSON_TABLE,KEY,KEYS,KILL,LAG,LAST_VALUE,LEAD,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCK,LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MASTER_BIND,MASTER_SSL_VERIFY_SERVER_CERT,MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,NO_WRITE_TO_BINLOG,NTH_VALUE,NTILE,OPTIMIZE,OPTIMIZER_COSTS,OPTION,OPTIONALLY,OUTFILE,PERSIST,PERSIST_ONLY,PURGE,READ,READ_WRITE,REGEXP,RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RLIKE,SCHEMA,SCHEMAS,SECOND_MICROSECOND,SEPARATOR,SHOW,SIGNAL,SPATIAL,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT,SSL,STARTING,STORED,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,UNDO,UNLOCK,UNSIGNED,USAGE,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,VIRTUAL,WHILE,WRITE,XOR,YEAR_MONTH,ZEROFILL" + "ACCESSIBLE,ADD,ANALYZE,ASC,BEFORE,CASCADE,CHANGE,CONTINUE,DATABASE,DATABASES,DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DESC,DISTINCTROW,DIV,DUAL,ELSEIF,EMPTY,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FIRST_VALUE,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERATED,GROUPS,HIGH_PRIORITY,HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,INDEX,INFILE,INT1,INT2,INT3,INT4,INT8,IO_AFTER_GTIDS,IO_BEFORE_GTIDS,ITERATE,JSON_TABLE,KEY,KEYS,KILL,LAG,LAST_VALUE,LEAD,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCK,LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,NO_WRITE_TO_BINLOG,NTH_VALUE,NTILE,OPTIMIZE,OPTIMIZER_COSTS,OPTION,OPTIONALLY,OUTFILE,PURGE,READ,READ_WRITE,REGEXP,RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RLIKE,SCHEMA,SCHEMAS,SECOND_MICROSECOND,SEPARATOR,SHOW,SIGNAL,SPATIAL,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT,SSL,STARTING,STORED,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,UNDO,UNLOCK,UNSIGNED,USAGE,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,VIRTUAL,WHILE,WRITE,XOR,YEAR_MONTH,ZEROFILL" .split(",") .toSet From 61c34801c2bd0d3c578583613871d069ef68b5b5 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 07:57:01 +0900 Subject: [PATCH 13/57] Fixed test --- .../shared/src/test/scala/ldbc/connector/ConnectionTest.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala index 3d4d4068b..5fb9b6cd3 100644 --- a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala +++ b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala @@ -1053,6 +1053,7 @@ class ConnectionTest extends CatsEffectSuite: yield values }, Vector( + "Table Catalog: benchmark", "Table Catalog: connector_test", "Table Catalog: information_schema", "Table Catalog: mysql", From 8e6b1f2f6604001ab31f0e99e6ba9a8ba5a934f5 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 09:10:43 +0900 Subject: [PATCH 14/57] Fixed jdbc Select benchmark --- .../benchmark/connector/jdbc/Select.scala | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala index a3b237257..5f40f5f22 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala @@ -8,48 +8,57 @@ package benchmark.connector.jdbc import java.util.concurrent.TimeUnit -import scala.util.Using import scala.compiletime.uninitialized import com.mysql.cj.jdbc.MysqlDataSource import org.openjdk.jmh.annotations.* +import cats.* + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import ldbc.sql.Connection + @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) class Select: @volatile - var dataSource: MysqlDataSource = uninitialized + var connection: Resource[IO, Connection[IO]] = uninitialized @Setup def setupDataSource(): Unit = - dataSource = new MysqlDataSource() - dataSource.setServerName("127.0.0.1") - dataSource.setPortNumber(13306) - dataSource.setDatabaseName("world") - dataSource.setUser("ldbc") - dataSource.setPassword("password") + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("benchmark") + ds.setUser("ldbc") + ds.setPassword("password") + + val datasource = jdbc.connector.MysqlDataSource[IO](ds) + + connection = Resource.make(datasource.getConnection)(_.close()) @Param(Array("10", "100", "1000", "2000", "4000")) var len: Int = uninitialized @Benchmark - def selectN: List[(Int, String, String)] = - Using - .Manager { use => - val connection = use(dataSource.getConnection) - val statement = use(connection.prepareStatement("SELECT ID, Name, CountryCode FROM city LIMIT ?")) - statement.setInt(1, len) - val resultSet = use(statement.executeQuery()) - val records = List.newBuilder[(Int, String, String)] - while resultSet.next() do { - val code = resultSet.getInt(1) - val name = resultSet.getString(2) - val region = resultSet.getString(3) - records += ((code, name, region)) + def selectN: List[(Long, String)] = + connection + .use { conn => + for + statement <- conn.prepareStatement("SELECT * FROM insert_test LIMIT ?") + _ <- statement.setInt(1, len) + resultSet <- statement.executeQuery() + records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { + for + c1 <- resultSet.getLong(1) + c2 <- resultSet.getString(2) + yield (c1, c2) + } + yield records } - records.result() - } - .getOrElse(throw new RuntimeException("Error during database operation")) + .unsafeRunSync() From a9ca0a7cf1d7a953f3440ef43cf16461225dec66 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 09:24:24 +0900 Subject: [PATCH 15/57] Create Select benchmark for ldbc --- .../benchmark/connector/ldbc/Select.scala | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala new file mode 100644 index 000000000..f542a3175 --- /dev/null +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.connector.ldbc + +import java.util.concurrent.TimeUnit + +import scala.compiletime.uninitialized + +import org.openjdk.jmh.annotations.* + +import cats.* + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import org.typelevel.otel4s.trace.Tracer + +import ldbc.connector.* + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Select: + + given Tracer[IO] = Tracer.noop[IO] + + @volatile + var connection: Resource[IO, LdbcConnection[IO]] = uninitialized + + @Setup + def setupDataSource(): Unit = + connection = Connection[IO]( + host = "127.0.0.1", + port = 13306, + user = "ldbc", + password = Some("password"), + database = Some("benchmark"), + ssl = SSL.Trusted + ) + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @Benchmark + def selectN: List[(Long, String)] = + connection + .use { conn => + for + statement <- conn.prepareStatement("SELECT * FROM insert_test LIMIT ?") + _ <- statement.setInt(1, len) + resultSet <- statement.executeQuery() + records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { + for + c1 <- resultSet.getLong(1) + c2 <- resultSet.getString(2) + yield (c1, c2) + } + yield records + } + .unsafeRunSync() From 27032e2b15008493c26d2c0558bfb9bafcc7c1bb Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 23 Jul 2024 09:25:01 +0900 Subject: [PATCH 16/57] Action sbt scalafmtAll --- .../benchmark/connector/jdbc/Select.scala | 24 +++++++++---------- .../benchmark/connector/ldbc/Select.scala | 20 ++++++++-------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala index 5f40f5f22..2b3870f46 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala @@ -49,16 +49,16 @@ class Select: def selectN: List[(Long, String)] = connection .use { conn => - for - statement <- conn.prepareStatement("SELECT * FROM insert_test LIMIT ?") - _ <- statement.setInt(1, len) - resultSet <- statement.executeQuery() - records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { - for - c1 <- resultSet.getLong(1) - c2 <- resultSet.getString(2) - yield (c1, c2) - } - yield records - } + for + statement <- conn.prepareStatement("SELECT * FROM insert_test LIMIT ?") + _ <- statement.setInt(1, len) + resultSet <- statement.executeQuery() + records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { + for + c1 <- resultSet.getLong(1) + c2 <- resultSet.getString(2) + yield (c1, c2) + } + yield records + } .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala index f542a3175..fc6a02aad 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala @@ -34,12 +34,12 @@ class Select: @Setup def setupDataSource(): Unit = connection = Connection[IO]( - host = "127.0.0.1", - port = 13306, - user = "ldbc", + host = "127.0.0.1", + port = 13306, + user = "ldbc", password = Some("password"), database = Some("benchmark"), - ssl = SSL.Trusted + ssl = SSL.Trusted ) @Param(Array("10", "100", "1000", "2000", "4000")) @@ -51,14 +51,14 @@ class Select: .use { conn => for statement <- conn.prepareStatement("SELECT * FROM insert_test LIMIT ?") - _ <- statement.setInt(1, len) + _ <- statement.setInt(1, len) resultSet <- statement.executeQuery() records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { - for - c1 <- resultSet.getLong(1) - c2 <- resultSet.getString(2) - yield (c1, c2) - } + for + c1 <- resultSet.getLong(1) + c2 <- resultSet.getString(2) + yield (c1, c2) + } yield records } .unsafeRunSync() From 1efb9b75fe90cad1925ac2deb0d5d3b692e52709 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Thu, 25 Jul 2024 23:28:36 +0900 Subject: [PATCH 17/57] Added setRewriteBatchedStatements --- benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index b6efbf6e8..033afbfe7 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -41,6 +41,7 @@ class Insert: ds.setDatabaseName("benchmark") ds.setUser("ldbc") ds.setPassword("password") + ds.setRewriteBatchedStatements(true) val datasource = jdbc.connector.MysqlDataSource[IO](ds) From a1dcb975e83f07b1eaf3aafb66a5c5a909534bb0 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Thu, 25 Jul 2024 23:31:54 +0900 Subject: [PATCH 18/57] Added .gitignore target file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4c81c834f..e7ca2e3eb 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ target/ .vscode/ metals.sbt +benchmark/*.json From 5ac3133dc7b8c830109ac2dff67cf0c6c8abd215 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Thu, 25 Jul 2024 23:33:41 +0900 Subject: [PATCH 19/57] Create requirements.txt --- script/requirements.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 script/requirements.txt diff --git a/script/requirements.txt b/script/requirements.txt new file mode 100644 index 000000000..8eb20a414 --- /dev/null +++ b/script/requirements.txt @@ -0,0 +1,3 @@ +pandas +seaborn +matplotlib \ No newline at end of file From a3514bcfbaa0f550a785a294d22553b49dd6795d Mon Sep 17 00:00:00 2001 From: takapi327 Date: Thu, 25 Jul 2024 23:34:19 +0900 Subject: [PATCH 20/57] Create plot_benchmark.py --- script/plot_benchmark.py | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 script/plot_benchmark.py diff --git a/script/plot_benchmark.py b/script/plot_benchmark.py new file mode 100644 index 000000000..2c45a29df --- /dev/null +++ b/script/plot_benchmark.py @@ -0,0 +1,50 @@ +import sys +import seaborn as sns +import matplotlib.pyplot as plt +import pandas as pd +import json +import glob + +def process_jmh_results(file_paths): + data = [] + for file_path in file_paths: + with open(file_path, 'r') as f: + results = json.load(f) + for result in results: + benchmark = result['benchmark'].split('.')[-1] + params = result['params'] + score = result['primaryMetric']['score'] + # パラメータを個別の列として追加 + for param, value in params.items(): + data.append({ + 'benchmark': benchmark, + 'param': param, + 'value': int(value), + 'score': score + }) + return pd.DataFrame(data) + +def plot_results(df, output): + sns.set_theme() + g = sns.relplot( + data=df, + kind="line", + x="value", + y="score", + hue="benchmark", + style="benchmark", + dashes=False, + markers=True + ) + g.set_axis_labels("Record size", "Throughput (ops/s)") + g.legend.set(title=None) + g.tight_layout() + g.savefig(output, format='svg') + +if __name__ == "__main__": + input_pattern = sys.argv[1] + output = sys.argv[2] + + file_paths = glob.glob(input_pattern) + df = process_jmh_results(file_paths) + plot_results(df, output) From d4745f70afb01c3efe74ca461b11331d78d0b3bd Mon Sep 17 00:00:00 2001 From: takapi327 Date: Thu, 25 Jul 2024 23:34:27 +0900 Subject: [PATCH 21/57] Create Dockerfile --- script/Dockerfile | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 script/Dockerfile diff --git a/script/Dockerfile b/script/Dockerfile new file mode 100644 index 000000000..08f60e986 --- /dev/null +++ b/script/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.9 + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY plot_benchmark.py . + +ENTRYPOINT ["python", "plot_benchmark.py"] From f75cfda0177584e3a0cac4a2b936d6f247d8e5a9 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:12:31 +0900 Subject: [PATCH 22/57] Fixed benchmark table --- database/benchmark.sql | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/database/benchmark.sql b/database/benchmark.sql index 1b6ed8f31..2fe7092a5 100644 --- a/database/benchmark.sql +++ b/database/benchmark.sql @@ -2,7 +2,12 @@ CREATE DATABASE `benchmark` DEFAULT CHARACTER SET utf8mb4; USE `benchmark`; -CREATE TABLE `insert_test` ( +CREATE TABLE `jdbc_test` ( + `c1` INT NOT NULL, + `c2` VARCHAR(255) NOT NULL +); + +CREATE TABLE `ldbc_test` ( `c1` INT NOT NULL, `c2` VARCHAR(255) NOT NULL ); From 7be4f152389beec7638db3859c720a1fa4429ecb Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:13:06 +0900 Subject: [PATCH 23/57] Added .gitignore target file --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e7ca2e3eb..e885d84e7 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ target/ .vscode/ metals.sbt -benchmark/*.json +**/benchmark/*.json +**/benchmark/*.svg From ca73999b8e4f1f3dd540eb376c3a99bf3b01cfd3 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:13:24 +0900 Subject: [PATCH 24/57] Fixed Dockerfile --- script/Dockerfile | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/script/Dockerfile b/script/Dockerfile index 08f60e986..5e66a5e85 100644 --- a/script/Dockerfile +++ b/script/Dockerfile @@ -1,10 +1,16 @@ -FROM python:3.9 +FROM continuumio/miniconda3 -WORKDIR /app +RUN mkdir -p /opt/workspace && \ + conda install -y --quiet \ + numpy \ + pandas \ + matplotlib \ + seaborn \ + jupyter && \ + conda clean -i -t -y -COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +WORKDIR /opt/workspace -COPY plot_benchmark.py . +EXPOSE 8888 -ENTRYPOINT ["python", "plot_benchmark.py"] +CMD [ "jupyter", "notebook", "--notebook-dir=/opt/workspace", "--ip=*", "--port=8888", "--no-browser" ] From cddff524b9f98616dd0e242491dbc4fe0b8edb35 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:14:00 +0900 Subject: [PATCH 25/57] Create docker-build-python.sh --- script/docker-build-python.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 script/docker-build-python.sh diff --git a/script/docker-build-python.sh b/script/docker-build-python.sh new file mode 100755 index 000000000..b5561b0f1 --- /dev/null +++ b/script/docker-build-python.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +ROOT="$(cd $(dirname "$0")/..; pwd)" +cd "$ROOT" + +docker build "$@" -t 'ldbc/python' script/ From a5a2463903d5326d7194767802b85370cde64c99 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:14:23 +0900 Subject: [PATCH 26/57] Create visualize.py --- script/python/visualize.py | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 script/python/visualize.py diff --git a/script/python/visualize.py b/script/python/visualize.py new file mode 100644 index 000000000..cc806b93d --- /dev/null +++ b/script/python/visualize.py @@ -0,0 +1,65 @@ +import sys +import seaborn as sns +import matplotlib.pyplot as plt +import pandas as pd +import numpy as np + +feature = sys.argv[1] +data_file = sys.argv[2] +output = sys.argv[3] + +target_names = { + 'ldbc': 'Insert (ldbc)', + 'jdbc': 'Insert (jdbc)', +} + +plot_config = { + 'Insert': { + 'xlabel': 'Record size', + 'ylabel': 'Throughput (ops/s)', + 'xmin': 0, + 'ymin': 20, + 'xstep': 1000, + 'ystep': 10, + }, +} + +def ticks(min, max, step): + min = int(min * 10) + max = int(max * 10) + step = int(step * 10) + return list(map(lambda n: n / 10, range(min, int(max / step) * step + 1, step))) + +conf = plot_config[feature] + +df = pd.read_json(data_file) +df['target'] = df['target'].map(target_names) + +x = 'index' +y = 'score' +xmax = df[x].max() +ymax = df[y].max() +xmin, xstep = conf['xmin'], conf['xstep'] +ymin, ystep = conf['ymin'], conf['ystep'] + +xticks = ticks(xmin, xmax, xstep) +yticks = ticks(ymin, ymax, ystep) + +sns.set_theme() +g = sns.relplot( + data=df, + estimator=conf.get('estimator', "average"), + kind="line", + x=x, + y=y, + hue="target", + style="target", + dashes=False, + markers=True +) +g.set_axis_labels(conf['xlabel'], conf['ylabel']) +g.ax.set_xticks(xticks) +g.ax.set_yticks(yticks) +g.legend.set(title=None) +g.tight_layout() +g.savefig(output, format='svg') From d33515f781173070fdcc6cc36f7421c1a110f62b Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:14:29 +0900 Subject: [PATCH 27/57] Create visualize.sh --- script/python/visualize.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 script/python/visualize.sh diff --git a/script/python/visualize.sh b/script/python/visualize.sh new file mode 100755 index 000000000..8beb8330c --- /dev/null +++ b/script/python/visualize.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +set -xe + +ROOT="$(cd $(dirname "$0")/../..; pwd)" +cd "$ROOT" + +script/docker-build-python.sh +docker run --rm -i -t \ + -u `id -u`:`id -g` \ + -v "$(pwd)":/opt/workspace \ + ldbc/python \ + python script/python/visualize.py "$@" From 225174b987c1bf5522b5311adb652e94bb818efe Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:14:56 +0900 Subject: [PATCH 28/57] Create connector benchmark test --- .../benchmark/connector/jdbc/Batch.scala | 73 +++++++++++++++++++ .../benchmark/connector/jdbc/Insert.scala | 21 +----- .../benchmark/connector/jdbc/Select.scala | 2 +- .../benchmark/connector/ldbc/Batch.scala | 72 ++++++++++++++++++ .../benchmark/connector/ldbc/Insert.scala | 20 +---- .../benchmark/connector/ldbc/Select.scala | 2 +- 6 files changed, 149 insertions(+), 41 deletions(-) create mode 100644 benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala create mode 100644 benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala new file mode 100644 index 000000000..73ff5a23b --- /dev/null +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.connector.jdbc + +import java.util.concurrent.TimeUnit + +import scala.compiletime.uninitialized + +import com.mysql.cj.jdbc.MysqlDataSource + +import org.openjdk.jmh.annotations.* + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import ldbc.sql.Connection + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Batch: + + @volatile + var connection: Resource[IO, Connection[IO]] = uninitialized + + @volatile + var values: String = uninitialized + + @volatile + var records: List[(Int, String)] = List.empty + + @Setup + def setupDataSource(): Unit = + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("benchmark") + ds.setUser("ldbc") + ds.setPassword("password") + ds.setRewriteBatchedStatements(true) + + val datasource = jdbc.connector.MysqlDataSource[IO](ds) + + connection = Resource.make(datasource.getConnection)(_.close()) + + values = (1 to len).map(_ => "(?, ?)").mkString(",") + + records = (1 to len).map(num => (num, s"record$num")).toList + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @Benchmark + def batchN(): Unit = + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO jdbc_test (c1, c2) VALUES (?, ?)") + _ <- records.foldLeft(IO.unit) { + case (acc, (id, value)) => + acc *> + statement.setInt(1, id) *> + statement.setString(2, value) *> + statement.addBatch() + } + _ <- statement.executeBatch() + yield () + } + .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index 033afbfe7..1a6c8f11b 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -41,7 +41,6 @@ class Insert: ds.setDatabaseName("benchmark") ds.setUser("ldbc") ds.setPassword("password") - ds.setRewriteBatchedStatements(true) val datasource = jdbc.connector.MysqlDataSource[IO](ds) @@ -59,7 +58,7 @@ class Insert: connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES $values") + statement <- conn.prepareStatement(s"INSERT INTO jdbc_test (c1, c2) VALUES $values") _ <- records.zipWithIndex.foldLeft(IO.unit) { case (acc, ((id, value), index)) => acc *> @@ -70,21 +69,3 @@ class Insert: yield () } .unsafeRunSync() - - @Benchmark - def batchN(): Unit = - connection - .use { conn => - for - statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES (?, ?)") - _ <- records.foldLeft(IO.unit) { - case (acc, (id, value)) => - acc *> - statement.setInt(1, id) *> - statement.setString(2, value) *> - statement.addBatch() - } - _ <- statement.executeBatch() - yield () - } - .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala index 2b3870f46..59623150a 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala @@ -50,7 +50,7 @@ class Select: connection .use { conn => for - statement <- conn.prepareStatement("SELECT * FROM insert_test LIMIT ?") + statement <- conn.prepareStatement("SELECT * FROM jdbc_test LIMIT ?") _ <- statement.setInt(1, len) resultSet <- statement.executeQuery() records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala new file mode 100644 index 000000000..60b9186e3 --- /dev/null +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.connector.ldbc + +import java.util.concurrent.TimeUnit + +import scala.compiletime.uninitialized + +import org.openjdk.jmh.annotations.* + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import org.typelevel.otel4s.trace.Tracer + +import ldbc.connector.* + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Batch: + + given Tracer[IO] = Tracer.noop[IO] + + @volatile + var connection: Resource[IO, LdbcConnection[IO]] = uninitialized + + @volatile + var values: String = uninitialized + + @volatile + var records: List[(Int, String)] = List.empty + + @Setup + def setup(): Unit = + connection = Connection[IO]( + host = "127.0.0.1", + port = 13306, + user = "ldbc", + password = Some("password"), + database = Some("benchmark"), + ssl = SSL.Trusted + ) + + values = (1 to len).map(_ => "(?, ?)").mkString(",") + + records = (1 to len).map(num => (num, s"record$num")).toList + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @Benchmark + def batchN(): Unit = + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO ldbc_test (c1, c2) VALUES (?, ?)") + _ <- records.foldLeft(IO.unit) { + case (acc, (id, value)) => + acc *> + statement.setInt(1, id) *> + statement.setString(2, value) *> + statement.addBatch() + } + _ <- statement.executeBatch() + yield () + } + .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala index fec8c7e1a..c2ee5be8b 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala @@ -58,7 +58,7 @@ class Insert: connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES $values") + statement <- conn.prepareStatement(s"INSERT INTO ldbc_test (c1, c2) VALUES $values") _ <- records.zipWithIndex.foldLeft(IO.unit) { case (acc, ((id, value), index)) => acc *> @@ -69,21 +69,3 @@ class Insert: yield () } .unsafeRunSync() - - @Benchmark - def batchN(): Unit = - connection - .use { conn => - for - statement <- conn.prepareStatement(s"INSERT INTO insert_test (c1, c2) VALUES (?, ?)") - _ <- records.foldLeft(IO.unit) { - case (acc, (id, value)) => - acc *> - statement.setInt(1, id) *> - statement.setString(2, value) *> - statement.addBatch() - } - _ <- statement.executeBatch() - yield () - } - .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala index fc6a02aad..0711089f7 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala @@ -50,7 +50,7 @@ class Select: connection .use { conn => for - statement <- conn.prepareStatement("SELECT * FROM insert_test LIMIT ?") + statement <- conn.prepareStatement("SELECT * FROM ldbc_test LIMIT ?") _ <- statement.setInt(1, len) resultSet <- statement.executeQuery() records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { From ce03f9d930ae70e892d56805f38e05552e6d197b Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:15:26 +0900 Subject: [PATCH 29/57] Added .gitignore target file --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e885d84e7..f51c5557c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,5 @@ target/ .vscode/ metals.sbt -**/benchmark/*.json -**/benchmark/*.svg +**/benchmark/**/*.json +**/benchmark/**/*.svg From 0c44292972c7888110a1e91351d5f03015cb8a7b Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sat, 27 Jul 2024 21:24:32 +0900 Subject: [PATCH 30/57] Action sbt scalafmtAll --- .../main/scala/benchmark/connector/jdbc/Batch.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala index 73ff5a23b..4bdbc2806 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala @@ -61,12 +61,12 @@ class Batch: for statement <- conn.prepareStatement(s"INSERT INTO jdbc_test (c1, c2) VALUES (?, ?)") _ <- records.foldLeft(IO.unit) { - case (acc, (id, value)) => - acc *> - statement.setInt(1, id) *> - statement.setString(2, value) *> - statement.addBatch() - } + case (acc, (id, value)) => + acc *> + statement.setInt(1, id) *> + statement.setString(2, value) *> + statement.addBatch() + } _ <- statement.executeBatch() yield () } From de1af8f0c38564df7e11eb4d9296505768af24c1 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 28 Jul 2024 02:04:16 +0900 Subject: [PATCH 31/57] Added target --- script/python/visualize.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/script/python/visualize.py b/script/python/visualize.py index cc806b93d..9ebdfd130 100644 --- a/script/python/visualize.py +++ b/script/python/visualize.py @@ -9,8 +9,8 @@ output = sys.argv[3] target_names = { - 'ldbc': 'Insert (ldbc)', - 'jdbc': 'Insert (jdbc)', + 'ldbc': 'ldbc', + 'jdbc': 'jdbc', } plot_config = { @@ -22,6 +22,22 @@ 'xstep': 1000, 'ystep': 10, }, + 'Batch': { + 'xlabel': 'Record size', + 'ylabel': 'Throughput (ops/s)', + 'xmin': 0, + 'ymin': 20, + 'xstep': 1000, + 'ystep': 10, + }, + 'Select': { + 'xlabel': 'Record size', + 'ylabel': 'Throughput (ops/s)', + 'xmin': 0, + 'ymin': 20, + 'xstep': 1000, + 'ystep': 10, + }, } def ticks(min, max, step): From ae9cd55b9e5a7eefd758ec627529e5a6c68c2a3e Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 28 Jul 2024 02:04:45 +0900 Subject: [PATCH 32/57] Create benchmark.sh --- script/benchmark.sh | 139 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100755 script/benchmark.sh diff --git a/script/benchmark.sh b/script/benchmark.sh new file mode 100755 index 000000000..b3dc5de0d --- /dev/null +++ b/script/benchmark.sh @@ -0,0 +1,139 @@ +#!/bin/bash + +set -xe + +ROOT="$(cd $(dirname "$0")/..; pwd)" +cd "$ROOT" + +OUT_DIR="benchmark" +OPTIONS="-t 1" + +sbt=sbt + +OUTPUTS=() +TARGETS=() +FEATURES=() +PREFIX='' +SUFFIX='' + +file_path() { + PROJECT=$1 + TARGET=$2 + FEATURE=$3 + + echo "${PROJECT}/src/main/scala/benchmark/connector/${TARGET}/${FEATURE}.scala" +} + +run() { + PROJECT=$1 + TARGET=$2 + FEATURE=$3 + + FILE=$(file_path "$PROJECT" "$TARGET" "$FEATURE") + [ -r "$FILE" ] || return 0 + + mkdir -p "script/${OUT_DIR}/${TARGET}" + OUTPUT="script/${OUT_DIR}/${TARGET}/${FEATURE}.json" + + $sbt "${PROJECT} / clean" + $sbt "${PROJECT} / Jmh / run $OPTIONS connector[.]${TARGET}[.]${FEATURE}[.] -rf json -rff ../${OUTPUT}" + OUTPUTS+=("$OUTPUT") +} + +to_json_rows() { + jq -s '[ .[] | { + benchmark:.benchmark, + target: .benchmark | split(".")[2], + feature: .benchmark | split(".")[3], + index: .params.len | tonumber, + score: (.primaryMetric.rawData[] | .[]) + } ]' +} + +while : +do + [ "$1" = "-0" ] && { + # Skip JMH run but accumulate outpus and plot the charts + # This is expecting the following workflow: + # 1. run `script/benchmark.sh ` one by one + # 2. run `script/benchmark.sh -0 to accumulate all the results and plot the charts + shift + sbt=: + continue + } + + [ "$1" = "-1" ] && { # just run once for test + shift + OPTIONS="-wi 0 -i 1 -t 1 -f 1" + continue + } + + [ "$1" = "-3" ] && { # just run few iterations for test + shift + OPTIONS="-wi 0 -i 3 -t 1 -f 1" + continue + } + + [ "$1" = '-t' ] && [ -n "$2" ] && { + TARGETS+=("$2") + shift; shift + continue + } + + [ "$1" = '-f' ] && [ -n "$2" ] && { + FEATURES+=("$2") + shift; shift + continue + } + + [ "$1" = '-p' ] && [ -n "$2" ] && { + PREFIX="${2}_" + shift; shift + continue + } + + [ "$1" = '-s' ] && [ -n "$2" ] && { + SUFFIX="_${2}" + shift; shift + continue + } + + break +done + +[ ${#TARGETS[@]} = 0 ] && { + TARGETS=( + 'jdbc' + 'ldbc' + ) +} + +[ ${#FEATURES[@]} = 0 ] && { + FEATURES=( + 'Insert' + 'Batch' + 'Select' + ) +} + +run_feature() { + FEATURE="$1" + for target in ${TARGETS[@]}; do + run "benchmark" "$target" "${FEATURE}" + done + + CHART_INPUT="script/${OUT_DIR}/${PREFIX}${FEATURE}${SUFFIX}.json" + CHART_OUTPUT="docs/src/main/mdoc/img/${PREFIX}${FEATURE}${SUFFIX}.svg" + + for output in ${OUTPUTS[@]}; do + jq '.[]' "${output}" + done | to_json_rows > "${CHART_INPUT}" + + script/python/visualize.sh "${FEATURE}" "${CHART_INPUT}" "${CHART_OUTPUT}" + + OUTPUTS=() +} + +for feature in ${FEATURES[@]}; do + run_feature "$feature" +done From fd59bd92af46b64c705414d6a755be501a80ce14 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 28 Jul 2024 02:05:10 +0900 Subject: [PATCH 33/57] Added benchmark result image --- docs/src/main/mdoc/img/Batch.svg | 1160 +++++++++++++++++++++++++++++ docs/src/main/mdoc/img/Insert.svg | 1160 +++++++++++++++++++++++++++++ docs/src/main/mdoc/img/Select.svg | 1145 ++++++++++++++++++++++++++++ 3 files changed, 3465 insertions(+) create mode 100644 docs/src/main/mdoc/img/Batch.svg create mode 100644 docs/src/main/mdoc/img/Insert.svg create mode 100644 docs/src/main/mdoc/img/Select.svg diff --git a/docs/src/main/mdoc/img/Batch.svg b/docs/src/main/mdoc/img/Batch.svg new file mode 100644 index 000000000..01f6bad97 --- /dev/null +++ b/docs/src/main/mdoc/img/Batch.svg @@ -0,0 +1,1160 @@ + + + + + + + + 2024-07-27T15:22:54.531788 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/main/mdoc/img/Insert.svg b/docs/src/main/mdoc/img/Insert.svg new file mode 100644 index 000000000..36597f760 --- /dev/null +++ b/docs/src/main/mdoc/img/Insert.svg @@ -0,0 +1,1160 @@ + + + + + + + + 2024-07-27T13:55:09.372660 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/main/mdoc/img/Select.svg b/docs/src/main/mdoc/img/Select.svg new file mode 100644 index 000000000..b300955a2 --- /dev/null +++ b/docs/src/main/mdoc/img/Select.svg @@ -0,0 +1,1145 @@ + + + + + + + + 2024-07-27T16:50:21.879011 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From db814ddaf0f12d25dfd8745d7778af25c4cb361b Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 28 Jul 2024 17:02:27 +0900 Subject: [PATCH 34/57] Fixed connector insert benchmark --- .../benchmark/connector/jdbc/Insert.scala | 25 +++++++++++++------ .../benchmark/connector/ldbc/Insert.scala | 15 +++++++++-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index 1a6c8f11b..020226236 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -54,17 +54,28 @@ class Insert: var len: Int = uninitialized @Benchmark - def insertN(): Unit = + def statement(): Unit = connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO jdbc_test (c1, c2) VALUES $values") + statement <- conn.createStatement() + _ <- statement.executeUpdate(s"INSERT INTO jdbc_statement_test (c1, c2) VALUES ${records.map { case (v1, v2) => s"($v1, '$v2')" }.mkString(", ")}") + yield () + } + .unsafeRunSync() + + @Benchmark + def prepareStatement(): Unit = + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO jdbc_prepare_statement_test (c1, c2) VALUES $values") _ <- records.zipWithIndex.foldLeft(IO.unit) { - case (acc, ((id, value), index)) => - acc *> - statement.setInt(index * 2 + 1, id) *> - statement.setString(index * 2 + 2, value) - } + case (acc, ((id, value), index)) => + acc *> + statement.setInt(index * 2 + 1, id) *> + statement.setString(index * 2 + 2, value) + } _ <- statement.executeUpdate() yield () } diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala index c2ee5be8b..2801f6b35 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala @@ -54,11 +54,22 @@ class Insert: var len: Int = uninitialized @Benchmark - def insertN(): Unit = + def statement(): Unit = connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO ldbc_test (c1, c2) VALUES $values") + statement <- conn.createStatement() + _ <- statement.executeUpdate(s"INSERT INTO ldbc_statement_test (c1, c2) VALUES ${records.map { case (v1, v2) => s"($v1, '$v2')" }.mkString(", ")}") + yield () + } + .unsafeRunSync() + + @Benchmark + def prepareStatement(): Unit = + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO ldbc_prepare_statement_test (c1, c2) VALUES $values") _ <- records.zipWithIndex.foldLeft(IO.unit) { case (acc, ((id, value), index)) => acc *> From d0ae7ba605b396901f22a294e082c5634ce66bd1 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 28 Jul 2024 17:02:47 +0900 Subject: [PATCH 35/57] Added table for benchmark --- database/benchmark.sql | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/database/benchmark.sql b/database/benchmark.sql index 2fe7092a5..c41cdd5ce 100644 --- a/database/benchmark.sql +++ b/database/benchmark.sql @@ -2,12 +2,22 @@ CREATE DATABASE `benchmark` DEFAULT CHARACTER SET utf8mb4; USE `benchmark`; -CREATE TABLE `jdbc_test` ( +CREATE TABLE `jdbc_statement_test` ( `c1` INT NOT NULL, `c2` VARCHAR(255) NOT NULL ); -CREATE TABLE `ldbc_test` ( +CREATE TABLE `jdbc_prepare_statement_test` ( + `c1` INT NOT NULL, + `c2` VARCHAR(255) NOT NULL +); + +CREATE TABLE `ldbc_statement_test` ( + `c1` INT NOT NULL, + `c2` VARCHAR(255) NOT NULL +); + +CREATE TABLE `ldbc_prepare_statement_test` ( `c1` INT NOT NULL, `c2` VARCHAR(255) NOT NULL ); From 964268b70377fc771e0c51a94d37b07236812e7a Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 28 Jul 2024 17:03:37 +0900 Subject: [PATCH 36/57] Fixed visualize.py --- script/python/visualize.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/script/python/visualize.py b/script/python/visualize.py index 9ebdfd130..a8b109323 100644 --- a/script/python/visualize.py +++ b/script/python/visualize.py @@ -9,8 +9,10 @@ output = sys.argv[3] target_names = { - 'ldbc': 'ldbc', - 'jdbc': 'jdbc', + 'jdbc_Insert_statement': 'jdbc: statement', + 'jdbc_Insert_prepareStatement': 'jdbc: prepareStatement', + 'ldbc_Insert_statement': 'ldbc: statement', + 'ldbc_Insert_prepareStatement': 'ldbc: prepareStatement', } plot_config = { From f380a8913d3eaaa07c05524b01be3b535d0b3e4c Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 28 Jul 2024 17:03:49 +0900 Subject: [PATCH 37/57] Change Insert.svg --- docs/src/main/mdoc/img/Insert.svg | 620 +++++++++++++++++++++++------- 1 file changed, 482 insertions(+), 138 deletions(-) diff --git a/docs/src/main/mdoc/img/Insert.svg b/docs/src/main/mdoc/img/Insert.svg index 36597f760..1a20917c5 100644 --- a/docs/src/main/mdoc/img/Insert.svg +++ b/docs/src/main/mdoc/img/Insert.svg @@ -1,12 +1,12 @@ - + - 2024-07-27T13:55:09.372660 + 2024-07-28T08:00:59.760753 image/svg+xml @@ -22,8 +22,8 @@ @@ -31,8 +31,8 @@ z @@ -40,13 +40,13 @@ z - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -467,13 +467,13 @@ L 336.818149 289.748191 - + - + @@ -481,13 +481,13 @@ L 336.818149 256.872596 - + - + @@ -495,13 +495,13 @@ L 336.818149 223.997 - + - + - + - + - + - + - + - + - + - + - + - + @@ -916,55 +916,97 @@ z - - - + + - - - + + + + + + + + + + + + + + + + + + - + - - - - - - - + + + + + + - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + From 90d0fe7374c80150c4c1a06c1620a5ac316e4904 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 28 Jul 2024 18:33:46 +0900 Subject: [PATCH 38/57] Delete unused --- script/plot_benchmark.py | 50 ---------------------------------------- script/requirements.txt | 3 --- 2 files changed, 53 deletions(-) delete mode 100644 script/plot_benchmark.py delete mode 100644 script/requirements.txt diff --git a/script/plot_benchmark.py b/script/plot_benchmark.py deleted file mode 100644 index 2c45a29df..000000000 --- a/script/plot_benchmark.py +++ /dev/null @@ -1,50 +0,0 @@ -import sys -import seaborn as sns -import matplotlib.pyplot as plt -import pandas as pd -import json -import glob - -def process_jmh_results(file_paths): - data = [] - for file_path in file_paths: - with open(file_path, 'r') as f: - results = json.load(f) - for result in results: - benchmark = result['benchmark'].split('.')[-1] - params = result['params'] - score = result['primaryMetric']['score'] - # パラメータを個別の列として追加 - for param, value in params.items(): - data.append({ - 'benchmark': benchmark, - 'param': param, - 'value': int(value), - 'score': score - }) - return pd.DataFrame(data) - -def plot_results(df, output): - sns.set_theme() - g = sns.relplot( - data=df, - kind="line", - x="value", - y="score", - hue="benchmark", - style="benchmark", - dashes=False, - markers=True - ) - g.set_axis_labels("Record size", "Throughput (ops/s)") - g.legend.set(title=None) - g.tight_layout() - g.savefig(output, format='svg') - -if __name__ == "__main__": - input_pattern = sys.argv[1] - output = sys.argv[2] - - file_paths = glob.glob(input_pattern) - df = process_jmh_results(file_paths) - plot_results(df, output) diff --git a/script/requirements.txt b/script/requirements.txt deleted file mode 100644 index 8eb20a414..000000000 --- a/script/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -pandas -seaborn -matplotlib \ No newline at end of file From 4c22ea84ec9302f308e26f734b0771f9e11dca53 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Sun, 4 Aug 2024 23:20:37 +0900 Subject: [PATCH 39/57] Fixed conflict --- .../benchmark/connector/jdbc/Batch.scala | 20 +- .../benchmark/connector/jdbc/Insert.scala | 30 +- .../benchmark/connector/jdbc/Select.scala | 65 +- .../benchmark/connector/ldbc/Batch.scala | 18 +- .../benchmark/connector/ldbc/Insert.scala | 34 +- .../benchmark/connector/ldbc/Select.scala | 66 +- database/benchmark.sql | 80 ++- docs/src/main/mdoc/img/Insert.svg | 452 +++++++------- docs/src/main/mdoc/img/Select.svg | 587 ++++++++++++------ .../ldbc/connector/net/PacketSocket.scala | 11 +- .../net/packet/response/EOFPacket.scala | 24 +- .../scala/ldbc/connector/ResultSetTest.scala | 3 + script/benchmark.sh | 7 +- script/python/visualize.py | 8 +- 14 files changed, 905 insertions(+), 500 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala index 4bdbc2806..fae86bbcd 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala @@ -55,11 +55,27 @@ class Batch: var len: Int = uninitialized @Benchmark - def batchN(): Unit = + def statement(): Unit = connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO jdbc_test (c1, c2) VALUES (?, ?)") + statement <- conn.createStatement() + _ <- records.foldLeft(IO.unit) { + case (acc, (id, value)) => + acc *> + statement.addBatch(s"INSERT INTO jdbc_statement_test (c1, c2) VALUES ${records.map { case (v1, v2) => s"($v1, '$v2')" }.mkString(", ")}") + } + _ <- statement.executeBatch() + yield () + } + .unsafeRunSync() + + @Benchmark + def prepareStatement(): Unit = + connection + .use { conn => + for + statement <- conn.prepareStatement(s"INSERT INTO jdbc_prepare_statement_test (c1, c2) VALUES (?, ?)") _ <- records.foldLeft(IO.unit) { case (acc, (id, value)) => acc *> diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index 020226236..034d99bfd 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -7,6 +7,7 @@ package benchmark.connector.jdbc import java.util.concurrent.TimeUnit +import java.time.* import scala.compiletime.uninitialized @@ -31,7 +32,7 @@ class Insert: var values: String = uninitialized @volatile - var records: List[(Int, String)] = List.empty + var records: List[(Short, Int, Int, Int, Long, Float, Double, BigDecimal, String, String, Boolean, LocalDate, LocalTime, LocalDateTime, LocalDateTime)] = List.empty @Setup def setupDataSource(): Unit = @@ -46,9 +47,9 @@ class Insert: connection = Resource.make(datasource.getConnection)(_.close()) - values = (1 to len).map(_ => "(?, ?)").mkString(",") + values = (1 to len).map(_ => "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").mkString(",") - records = (1 to len).map(num => (num, s"record$num")).toList + records = (1 to len).map(num => (1.toShort, 1, 1, 1, 1L, 1.1f, 1.1, BigDecimal.decimal(1.1), s"varchar $num", s"text $num", true, LocalDate.now(), LocalTime.now(), LocalDateTime.now(), LocalDateTime.now())).toList @Param(Array("10", "100", "1000", "2000", "4000")) var len: Int = uninitialized @@ -59,7 +60,7 @@ class Insert: .use { conn => for statement <- conn.createStatement() - _ <- statement.executeUpdate(s"INSERT INTO jdbc_statement_test (c1, c2) VALUES ${records.map { case (v1, v2) => s"($v1, '$v2')" }.mkString(", ")}") + _ <- statement.executeUpdate(s"INSERT INTO jdbc_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES ${records.map { case (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) => s"($v1, $v2, $v3, $v4, $v5, $v6, $v7, $v8, '$v9', '$v10', $v11, '$v12', '$v13', '${v14.toString.replace("T", " ")}', '${v15.toString.replace("T", " ")}')" }.mkString(",")}") yield () } .unsafeRunSync() @@ -69,12 +70,25 @@ class Insert: connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO jdbc_prepare_statement_test (c1, c2) VALUES $values") + statement <- conn.prepareStatement(s"INSERT INTO jdbc_prepare_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES $values") _ <- records.zipWithIndex.foldLeft(IO.unit) { - case (acc, ((id, value), index)) => + case (acc, ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15), index)) => acc *> - statement.setInt(index * 2 + 1, id) *> - statement.setString(index * 2 + 2, value) + statement.setShort(index * 15 + 1, v1) *> + statement.setInt(index * 15 + 2, v2) *> + statement.setInt(index * 15 + 3, v3) *> + statement.setInt(index * 15 + 4, v4) *> + statement.setLong(index * 15 + 5, v5) *> + statement.setFloat(index * 15 + 6, v6) *> + statement.setDouble(index * 15 + 7, v7) *> + statement.setBigDecimal(index * 15 + 8, v8.bigDecimal) *> + statement.setString(index * 15 + 9, v9) *> + statement.setString(index * 15 + 10, v10) *> + statement.setBoolean(index * 15 + 11, v11) *> + statement.setDate(index * 15 + 12, v12) *> + statement.setTime(index * 15 + 13, v13) *> + statement.setTimestamp(index * 15 + 14, v14) *> + statement.setTimestamp(index * 15 + 15, v15) } _ <- statement.executeUpdate() yield () diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala index 59623150a..ef8a19470 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala @@ -7,6 +7,7 @@ package benchmark.connector.jdbc import java.util.concurrent.TimeUnit +import java.time.* import scala.compiletime.uninitialized @@ -15,17 +16,20 @@ import com.mysql.cj.jdbc.MysqlDataSource import org.openjdk.jmh.annotations.* import cats.* +import cats.syntax.all.* import cats.effect.* import cats.effect.unsafe.implicits.global -import ldbc.sql.Connection +import ldbc.sql.{Connection, ResultSet} @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) class Select: + type BenchmarkType = (Long, Short, Int, Int, Int, Long, Float, Double, BigDecimal, String, String, Boolean, LocalDate, LocalTime, LocalDateTime, LocalDateTime) + @volatile var connection: Resource[IO, Connection[IO]] = uninitialized @@ -46,19 +50,58 @@ class Select: var len: Int = uninitialized @Benchmark - def selectN: List[(Long, String)] = + def statement: List[BenchmarkType] = connection .use { conn => for - statement <- conn.prepareStatement("SELECT * FROM jdbc_test LIMIT ?") - _ <- statement.setInt(1, len) - resultSet <- statement.executeQuery() - records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { - for - c1 <- resultSet.getLong(1) - c2 <- resultSet.getString(2) - yield (c1, c2) - } + // 処理時間の計測を入れる + statement <- conn.createStatement() + start <- IO(System.nanoTime()) + resultSet <- statement.executeQuery(s"SELECT * FROM jdbc_statement_test LIMIT $len") + end <- IO(System.nanoTime()) + _ <- IO.println("============") *> IO(println(s"statement: ${end - start} nanos")) + records <- consume(resultSet) yield records } .unsafeRunSync() + + //@Benchmark + //def prepareStatement: List[BenchmarkType] = + // connection + // .use { conn => + // for + // statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") + // _ <- statement.setInt(1, len) + // resultSet <- statement.executeQuery() + // records <- consume(resultSet) + // yield records + // } + // .unsafeRunSync() + + private def consume(resultSet: ResultSet[IO]): IO[List[BenchmarkType]] = + def loop(acc: Vector[BenchmarkType]): IO[Vector[BenchmarkType]] = + resultSet.next().flatMap { + case false => Monad[IO].pure(acc) + case true => + for + c1 <- resultSet.getLong(1) + c2 <- resultSet.getShort(2) + c3 <- resultSet.getInt(3) + c4 <- resultSet.getInt(4) + c5 <- resultSet.getInt(5) + c6 <- resultSet.getLong(6) + c7 <- resultSet.getFloat(7) + c8 <- resultSet.getDouble(8) + c9 <- resultSet.getBigDecimal(9) + c10 <- resultSet.getString(10) + c11 <- resultSet.getString(11) + c12 <- resultSet.getBoolean(12) + c13 <- resultSet.getDate(13) + c14 <- resultSet.getTime(14) + c15 <- resultSet.getTimestamp(15) + c16 <- resultSet.getTimestamp(16) + yield + acc <+> Vector((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)) + } + + loop(Vector.empty).map(_.toList) diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala index 60b9186e3..53d5c5a1d 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala @@ -54,7 +54,23 @@ class Batch: var len: Int = uninitialized @Benchmark - def batchN(): Unit = + def statement(): Unit = + connection + .use { conn => + for + statement <- conn.createStatement() + _ <- records.foldLeft(IO.unit) { + case (acc, (id, value)) => + acc *> + statement.addBatch(s"INSERT INTO ldbc_statement_test (c1, c2) VALUES ${records.map { case (v1, v2) => s"($v1, '$v2')" }.mkString(", ")}") + } + _ <- statement.executeBatch() + yield () + } + .unsafeRunSync() + + @Benchmark + def prepareStatement(): Unit = connection .use { conn => for diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala index 2801f6b35..08e976ad8 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala @@ -7,6 +7,7 @@ package benchmark.connector.ldbc import java.util.concurrent.TimeUnit +import java.time.* import scala.compiletime.uninitialized @@ -33,7 +34,7 @@ class Insert: var values: String = uninitialized @volatile - var records: List[(Int, String)] = List.empty + var records: List[(Short, Int, Int, Int, Long, Float, Double, BigDecimal, String, String, Boolean, LocalDate, LocalTime, LocalDateTime, LocalDateTime)] = List.empty @Setup def setup(): Unit = @@ -46,9 +47,9 @@ class Insert: ssl = SSL.Trusted ) - values = (1 to len).map(_ => "(?, ?)").mkString(",") + values = (1 to len).map(_ => "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").mkString(",") - records = (1 to len).map(num => (num, s"record$num")).toList + records = (1 to len).map(num => (1.toShort, 1, 1, 1, 1L, 1.1f, 1.1, BigDecimal.decimal(1.1), s"varchar $num", s"text $num", true, LocalDate.now(), LocalTime.now(), LocalDateTime.now(), LocalDateTime.now())).toList @Param(Array("10", "100", "1000", "2000", "4000")) var len: Int = uninitialized @@ -59,7 +60,7 @@ class Insert: .use { conn => for statement <- conn.createStatement() - _ <- statement.executeUpdate(s"INSERT INTO ldbc_statement_test (c1, c2) VALUES ${records.map { case (v1, v2) => s"($v1, '$v2')" }.mkString(", ")}") + _ <- statement.executeUpdate(s"INSERT INTO ldbc_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES ${records.map { case (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) => s"($v1, $v2, $v3, $v4, $v5, $v6, $v7, $v8, '$v9', '$v10', $v11, '$v12', '$v13', '${v14.toString.replace("T", " ")}', '${v15.toString.replace("T", " ")}')" }.mkString(",")}") yield () } .unsafeRunSync() @@ -69,13 +70,26 @@ class Insert: connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO ldbc_prepare_statement_test (c1, c2) VALUES $values") + statement <- conn.prepareStatement(s"INSERT INTO ldbc_prepare_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES $values") _ <- records.zipWithIndex.foldLeft(IO.unit) { - case (acc, ((id, value), index)) => - acc *> - statement.setInt(index * 2 + 1, id) *> - statement.setString(index * 2 + 2, value) - } + case (acc, ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15), index)) => + acc *> + statement.setShort(index * 15 + 1, v1) *> + statement.setInt(index * 15 + 2, v2) *> + statement.setInt(index * 15 + 3, v3) *> + statement.setInt(index * 15 + 4, v4) *> + statement.setLong(index * 15 + 5, v5) *> + statement.setFloat(index * 15 + 6, v6) *> + statement.setDouble(index * 15 + 7, v7) *> + statement.setBigDecimal(index * 15 + 8, v8.bigDecimal) *> + statement.setString(index * 15 + 9, v9) *> + statement.setString(index * 15 + 10, v10) *> + statement.setBoolean(index * 15 + 11, v11) *> + statement.setDate(index * 15 + 12, v12) *> + statement.setTime(index * 15 + 13, v13) *> + statement.setTimestamp(index * 15 + 14, v14) *> + statement.setTimestamp(index * 15 + 15, v15) + } _ <- statement.executeUpdate() yield () } diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala index 0711089f7..e04bcdd5f 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala @@ -7,18 +7,21 @@ package benchmark.connector.ldbc import java.util.concurrent.TimeUnit +import java.time.* import scala.compiletime.uninitialized import org.openjdk.jmh.annotations.* import cats.* +import cats.syntax.all.* import cats.effect.* import cats.effect.unsafe.implicits.global import org.typelevel.otel4s.trace.Tracer +import ldbc.sql.ResultSet import ldbc.connector.* @BenchmarkMode(Array(Mode.Throughput)) @@ -26,6 +29,8 @@ import ldbc.connector.* @State(Scope.Benchmark) class Select: + type BenchmarkType = (Long, Short, Int, Int, Int, Long, Float, Double, BigDecimal, String, String, Boolean, LocalDate, LocalTime, LocalDateTime, LocalDateTime) + given Tracer[IO] = Tracer.noop[IO] @volatile @@ -42,23 +47,62 @@ class Select: ssl = SSL.Trusted ) - @Param(Array("10", "100", "1000", "2000", "4000")) + @Param(Array("4000")) var len: Int = uninitialized @Benchmark - def selectN: List[(Long, String)] = + def statement: List[BenchmarkType] = connection .use { conn => for - statement <- conn.prepareStatement("SELECT * FROM ldbc_test LIMIT ?") - _ <- statement.setInt(1, len) - resultSet <- statement.executeQuery() - records <- Monad[IO].whileM[List, (Long, String)](resultSet.next()) { - for - c1 <- resultSet.getLong(1) - c2 <- resultSet.getString(2) - yield (c1, c2) - } + // 処理時間の計測を入れる + statement <- conn.createStatement() + //start <- IO(System.nanoTime()) + resultSet <- statement.executeQuery(s"SELECT * FROM jdbc_statement_test LIMIT $len") + //end <- IO(System.nanoTime()) + //_ <- IO.println("============") *> IO(println(s"statement: ${end - start} nanos")) + records <- consume(resultSet) yield records } .unsafeRunSync() + + //@Benchmark + //def prepareStatement: List[BenchmarkType] = + // connection + // .use { conn => + // for + // statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") + // _ <- statement.setInt(1, len) + // resultSet <- statement.executeQuery() + // records <- consume(resultSet) + // yield records + // } + // .unsafeRunSync() + + private def consume(resultSet: ResultSet[IO]): IO[List[BenchmarkType]] = + def loop(acc: Vector[BenchmarkType]): IO[Vector[BenchmarkType]] = + resultSet.next().flatMap { + case false => Monad[IO].pure(acc) + case true => + for + c1 <- resultSet.getLong(1) + c2 <- resultSet.getShort(2) + c3 <- resultSet.getInt(3) + c4 <- resultSet.getInt(4) + c5 <- resultSet.getInt(5) + c6 <- resultSet.getLong(6) + c7 <- resultSet.getFloat(7) + c8 <- resultSet.getDouble(8) + c9 <- resultSet.getBigDecimal(9) + c10 <- resultSet.getString(10) + c11 <- resultSet.getString(11) + c12 <- resultSet.getBoolean(12) + c13 <- resultSet.getDate(13) + c14 <- resultSet.getTime(14) + c15 <- resultSet.getTimestamp(15) + c16 <- resultSet.getTimestamp(16) + yield + acc <+> Vector((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)) + } + + loop(Vector.empty).map(_.toList) diff --git a/database/benchmark.sql b/database/benchmark.sql index c41cdd5ce..bde81219c 100644 --- a/database/benchmark.sql +++ b/database/benchmark.sql @@ -3,21 +3,85 @@ CREATE DATABASE `benchmark` DEFAULT CHARACTER SET utf8mb4; USE `benchmark`; CREATE TABLE `jdbc_statement_test` ( - `c1` INT NOT NULL, - `c2` VARCHAR(255) NOT NULL + `c0` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `c1` TINYINT NOT NULL, + `c2` SMALLINT NOT NULL, + `c3` MEDIUMINT NOT NULL, + `c4` INT NOT NULL, + `c5` BIGINT NOT NULL, + `c6` FLOAT NOT NULL, + `c7` DOUBLE NOT NULL, + `c8` DECIMAL NOT NULL, + `c9` VARCHAR(255) NOT NULL, + `c10` TEXT NOT NULL, + `c11` BOOLEAN NOT NULL, + `c12` DATE NOT NULL, + `c13` TIME NOT NULL, + `c14` DATETIME NOT NULL, + `c15` TIMESTAMP NOT NULL, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE `jdbc_prepare_statement_test` ( - `c1` INT NOT NULL, - `c2` VARCHAR(255) NOT NULL + `c0` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `c1` TINYINT NOT NULL, + `c2` SMALLINT NOT NULL, + `c3` MEDIUMINT NOT NULL, + `c4` INT NOT NULL, + `c5` BIGINT NOT NULL, + `c6` FLOAT NOT NULL, + `c7` DOUBLE NOT NULL, + `c8` DECIMAL NOT NULL, + `c9` VARCHAR(255) NOT NULL, + `c10` TEXT NOT NULL, + `c11` BOOLEAN NOT NULL, + `c12` DATE NOT NULL, + `c13` TIME NOT NULL, + `c14` DATETIME NOT NULL, + `c15` TIMESTAMP NOT NULL, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE `ldbc_statement_test` ( - `c1` INT NOT NULL, - `c2` VARCHAR(255) NOT NULL + `c0` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `c1` TINYINT NOT NULL, + `c2` SMALLINT NOT NULL, + `c3` MEDIUMINT NOT NULL, + `c4` INT NOT NULL, + `c5` BIGINT NOT NULL, + `c6` FLOAT NOT NULL, + `c7` DOUBLE NOT NULL, + `c8` DECIMAL NOT NULL, + `c9` VARCHAR(255) NOT NULL, + `c10` TEXT NOT NULL, + `c11` BOOLEAN NOT NULL, + `c12` DATE NOT NULL, + `c13` TIME NOT NULL, + `c14` DATETIME NOT NULL, + `c15` TIMESTAMP NOT NULL, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE `ldbc_prepare_statement_test` ( - `c1` INT NOT NULL, - `c2` VARCHAR(255) NOT NULL + `c0` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `c1` TINYINT NOT NULL, + `c2` SMALLINT NOT NULL, + `c3` MEDIUMINT NOT NULL, + `c4` INT NOT NULL, + `c5` BIGINT NOT NULL, + `c6` FLOAT NOT NULL, + `c7` DOUBLE NOT NULL, + `c8` DECIMAL NOT NULL, + `c9` VARCHAR(255) NOT NULL, + `c10` TEXT NOT NULL, + `c11` BOOLEAN NOT NULL, + `c12` DATE NOT NULL, + `c13` TIME NOT NULL, + `c14` DATETIME NOT NULL, + `c15` TIMESTAMP NOT NULL, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); diff --git a/docs/src/main/mdoc/img/Insert.svg b/docs/src/main/mdoc/img/Insert.svg index 1a20917c5..db507b555 100644 --- a/docs/src/main/mdoc/img/Insert.svg +++ b/docs/src/main/mdoc/img/Insert.svg @@ -1,12 +1,12 @@ - + - 2024-07-28T08:00:59.760753 + 2024-07-28T16:34:45.827404 image/svg+xml @@ -22,8 +22,8 @@ @@ -31,8 +31,8 @@ z @@ -40,13 +40,13 @@ z - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -467,13 +467,13 @@ L 334.826433 289.868689 - + - + @@ -481,13 +481,13 @@ L 334.826433 256.468041 - + - + @@ -495,13 +495,13 @@ L 334.826433 223.067393 - + - + - + - + - + - + - + - + - + - + - + - + @@ -916,97 +916,97 @@ z - - - + + - - - + + - - - + + - - - + + - + - - - - - - - + + + + + + - + - - - - - - - + + + + + + - + - - - - - - - + + + + + + - + - - - - - - - + + + + + + @@ -1122,18 +1122,18 @@ L 53.31 7.2 - - - + - - + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - + - - + + - - - - - - - - - - + + + + + + + + + - - - + - + - - - + - + @@ -1497,8 +1495,8 @@ z - - + + diff --git a/docs/src/main/mdoc/img/Select.svg b/docs/src/main/mdoc/img/Select.svg index b300955a2..d0896433b 100644 --- a/docs/src/main/mdoc/img/Select.svg +++ b/docs/src/main/mdoc/img/Select.svg @@ -1,12 +1,12 @@ - + - 2024-07-27T16:50:21.879011 + 2024-07-30T05:21:27.572053 image/svg+xml @@ -21,32 +21,32 @@ - - - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -467,13 +467,13 @@ L 337.214251 269.518047 - + - + @@ -481,13 +481,13 @@ L 337.214251 232.641061 - + - + @@ -495,13 +495,13 @@ L 337.214251 195.764074 - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + - + - - - + + - - - + + - - + - + + + + + + + + + - - - - - - + + - - + + - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - + - - + - - - + + + - @@ -1084,21 +1055,127 @@ L 581 4863 L 1159 4863 L 1159 2969 z +" transform="scale(0.015625)"/> + + + + - + + + + + + + + + + + + - - + - - + - - - + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala index d145d158e..1a81fd91d 100644 --- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala +++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala @@ -48,18 +48,23 @@ object PacketSocket: ): PacketSocket[F] = new PacketSocket[F]: private def debug(msg: => String): F[Unit] = - sequenceIdRef.get - .flatMap(id => if debugEnabled then Console[F].println(s"[$id] $msg") else Concurrent[F].unit) + Concurrent[F].whenA(debugEnabled) { + sequenceIdRef.get.flatMap(id => Console[F].println(s"[$id] $msg")) + } + //sequenceIdRef.get + // .flatMap(id => if debugEnabled then Console[F].println(s"[$id] $msg") else Concurrent[F].unit) override def receive[P <: ResponsePacket](decoder: Decoder[P]): F[P] = (for + start <- Concurrent[F].pure(System.nanoTime()) header <- bvs.read(4) payloadSize = parseHeader(header.toByteArray) payload <- bvs.read(payloadSize) response = decoder.decodeValue(payload).require + end <- Concurrent[F].pure(System.nanoTime()) _ <- debug( - s"Client ${ AnsiColor.BLUE }←${ AnsiColor.RESET } Server: ${ AnsiColor.GREEN }$response${ AnsiColor.RESET }" + s"Client ${ AnsiColor.BLUE }←${ AnsiColor.RESET } Server: ${ AnsiColor.GREEN }$response${ AnsiColor.RESET } Time: ${ end - start } nanos" ) _ <- sequenceIdRef.update(_ => ((header.toByteArray(3) + 1) % 256).toByte) yield response).onError { diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala index ca1eae998..188599fb7 100644 --- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala +++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala @@ -34,8 +34,8 @@ import ldbc.connector.data.CapabilitiesFlags */ case class EOFPacket( status: Int, - warnings: Option[Int], - statusFlags: Option[Int] + warnings: Int, + statusFlags: Int ) extends GenericResponsePackets: override def toString: String = "EOF_Packet" @@ -46,8 +46,18 @@ object EOFPacket: def decoder(capabilityFlags: Set[CapabilitiesFlags]): Decoder[EOFPacket] = val hasClientProtocol41Flag = capabilityFlags.contains(CapabilitiesFlags.CLIENT_PROTOCOL_41) - for - status <- uint4 - warnings <- if hasClientProtocol41Flag then uint4.map(_.some) else provide(None) - statusFlags <- if hasClientProtocol41Flag then uint4.map(_.some) else provide(None) - yield EOFPacket(status, warnings, statusFlags) + uint4.flatMap { status => + if hasClientProtocol41Flag then + for + warnings <- uint4 + statusFlags <- uint4 + yield EOFPacket(status, warnings, statusFlags) + else + Decoder.pure(EOFPacket(status, 0, 0)) + //provide(EOFPacket(status, None, None)) + } + //for + // status <- uint4 + // warnings <- if hasClientProtocol41Flag then uint4.map(_.some) else provide(None) + // statusFlags <- if hasClientProtocol41Flag then uint4.map(_.some) else provide(None) + //yield EOFPacket(status, warnings, statusFlags) diff --git a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ResultSetTest.scala b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ResultSetTest.scala index 98647ecdb..83b11e81e 100644 --- a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ResultSetTest.scala +++ b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ResultSetTest.scala @@ -4,6 +4,7 @@ * For more information see LICENSE or https://opensource.org/licenses/MIT */ +/* package ldbc.connector import java.time.* @@ -928,3 +929,5 @@ class ResultSetTest extends CatsEffectSuite: flags = flags, decimals = if useScale then 2 else 0 ) + + */ diff --git a/script/benchmark.sh b/script/benchmark.sh index b3dc5de0d..6b698dc31 100755 --- a/script/benchmark.sh +++ b/script/benchmark.sh @@ -35,7 +35,7 @@ run() { mkdir -p "script/${OUT_DIR}/${TARGET}" OUTPUT="script/${OUT_DIR}/${TARGET}/${FEATURE}.json" - $sbt "${PROJECT} / clean" + #$sbt "${PROJECT} / clean" $sbt "${PROJECT} / Jmh / run $OPTIONS connector[.]${TARGET}[.]${FEATURE}[.] -rf json -rff ../${OUTPUT}" OUTPUTS+=("$OUTPUT") } @@ -43,7 +43,7 @@ run() { to_json_rows() { jq -s '[ .[] | { benchmark:.benchmark, - target: .benchmark | split(".")[2], + target: (.benchmark | split(".") | .[2] + "_" + .[4]), feature: .benchmark | split(".")[3], index: .params.len | tonumber, score: (.primaryMetric.rawData[] | .[]) @@ -125,6 +125,9 @@ run_feature() { CHART_INPUT="script/${OUT_DIR}/${PREFIX}${FEATURE}${SUFFIX}.json" CHART_OUTPUT="docs/src/main/mdoc/img/${PREFIX}${FEATURE}${SUFFIX}.svg" + OUTPUTS+=("script/${OUT_DIR}/jdbc/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/ldbc/${FEATURE}.json") + for output in ${OUTPUTS[@]}; do jq '.[]' "${output}" done | to_json_rows > "${CHART_INPUT}" diff --git a/script/python/visualize.py b/script/python/visualize.py index a8b109323..f9a9f94bf 100644 --- a/script/python/visualize.py +++ b/script/python/visualize.py @@ -9,10 +9,10 @@ output = sys.argv[3] target_names = { - 'jdbc_Insert_statement': 'jdbc: statement', - 'jdbc_Insert_prepareStatement': 'jdbc: prepareStatement', - 'ldbc_Insert_statement': 'ldbc: statement', - 'ldbc_Insert_prepareStatement': 'ldbc: prepareStatement', + 'jdbc_statement': 'jdbc: statement', + 'jdbc_prepareStatement': 'jdbc: prepareStatement', + 'ldbc_statement': 'ldbc: statement', + 'ldbc_prepareStatement': 'ldbc: prepareStatement', } plot_config = { From 8e80be1bfdff3376f768f3e7e8a2f07d686bf75f Mon Sep 17 00:00:00 2001 From: takapi327 Date: Mon, 5 Aug 2024 23:03:06 +0900 Subject: [PATCH 40/57] Action sbt scalafmtAll --- .../benchmark/connector/jdbc/Batch.scala | 10 +- .../benchmark/connector/jdbc/Insert.scala | 94 ++++++++++++++----- .../benchmark/connector/jdbc/Select.scala | 54 +++++++---- .../benchmark/connector/ldbc/Batch.scala | 10 +- .../benchmark/connector/ldbc/Insert.scala | 94 ++++++++++++++----- .../benchmark/connector/ldbc/Select.scala | 50 ++++++---- .../ldbc/connector/net/PacketSocket.scala | 12 +-- .../net/packet/response/EOFPacket.scala | 6 +- .../scala/ldbc/connector/ResultSetTest.scala | 3 - 9 files changed, 233 insertions(+), 100 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala index fae86bbcd..81976326f 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Batch.scala @@ -61,10 +61,12 @@ class Batch: for statement <- conn.createStatement() _ <- records.foldLeft(IO.unit) { - case (acc, (id, value)) => - acc *> - statement.addBatch(s"INSERT INTO jdbc_statement_test (c1, c2) VALUES ${records.map { case (v1, v2) => s"($v1, '$v2')" }.mkString(", ")}") - } + case (acc, (id, value)) => + acc *> + statement.addBatch(s"INSERT INTO jdbc_statement_test (c1, c2) VALUES ${ records + .map { case (v1, v2) => s"($v1, '$v2')" } + .mkString(", ") }") + } _ <- statement.executeBatch() yield () } diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala index 034d99bfd..cae78546b 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Insert.scala @@ -32,7 +32,25 @@ class Insert: var values: String = uninitialized @volatile - var records: List[(Short, Int, Int, Int, Long, Float, Double, BigDecimal, String, String, Boolean, LocalDate, LocalTime, LocalDateTime, LocalDateTime)] = List.empty + var records: List[ + ( + Short, + Int, + Int, + Int, + Long, + Float, + Double, + BigDecimal, + String, + String, + Boolean, + LocalDate, + LocalTime, + LocalDateTime, + LocalDateTime + ) + ] = List.empty @Setup def setupDataSource(): Unit = @@ -49,7 +67,27 @@ class Insert: values = (1 to len).map(_ => "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").mkString(",") - records = (1 to len).map(num => (1.toShort, 1, 1, 1, 1L, 1.1f, 1.1, BigDecimal.decimal(1.1), s"varchar $num", s"text $num", true, LocalDate.now(), LocalTime.now(), LocalDateTime.now(), LocalDateTime.now())).toList + records = (1 to len) + .map(num => + ( + 1.toShort, + 1, + 1, + 1, + 1L, + 1.1f, + 1.1, + BigDecimal.decimal(1.1), + s"varchar $num", + s"text $num", + true, + LocalDate.now(), + LocalTime.now(), + LocalDateTime.now(), + LocalDateTime.now() + ) + ) + .toList @Param(Array("10", "100", "1000", "2000", "4000")) var len: Int = uninitialized @@ -60,7 +98,16 @@ class Insert: .use { conn => for statement <- conn.createStatement() - _ <- statement.executeUpdate(s"INSERT INTO jdbc_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES ${records.map { case (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) => s"($v1, $v2, $v3, $v4, $v5, $v6, $v7, $v8, '$v9', '$v10', $v11, '$v12', '$v13', '${v14.toString.replace("T", " ")}', '${v15.toString.replace("T", " ")}')" }.mkString(",")}") + _ <- + statement.executeUpdate( + s"INSERT INTO jdbc_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES ${ records + .map { + case (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) => + s"($v1, $v2, $v3, $v4, $v5, $v6, $v7, $v8, '$v9', '$v10', $v11, '$v12', '$v13', '${ v14.toString + .replace("T", " ") }', '${ v15.toString.replace("T", " ") }')" + } + .mkString(",") }" + ) yield () } .unsafeRunSync() @@ -70,26 +117,29 @@ class Insert: connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO jdbc_prepare_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES $values") + statement <- + conn.prepareStatement( + s"INSERT INTO jdbc_prepare_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES $values" + ) _ <- records.zipWithIndex.foldLeft(IO.unit) { - case (acc, ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15), index)) => - acc *> - statement.setShort(index * 15 + 1, v1) *> - statement.setInt(index * 15 + 2, v2) *> - statement.setInt(index * 15 + 3, v3) *> - statement.setInt(index * 15 + 4, v4) *> - statement.setLong(index * 15 + 5, v5) *> - statement.setFloat(index * 15 + 6, v6) *> - statement.setDouble(index * 15 + 7, v7) *> - statement.setBigDecimal(index * 15 + 8, v8.bigDecimal) *> - statement.setString(index * 15 + 9, v9) *> - statement.setString(index * 15 + 10, v10) *> - statement.setBoolean(index * 15 + 11, v11) *> - statement.setDate(index * 15 + 12, v12) *> - statement.setTime(index * 15 + 13, v13) *> - statement.setTimestamp(index * 15 + 14, v14) *> - statement.setTimestamp(index * 15 + 15, v15) - } + case (acc, ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15), index)) => + acc *> + statement.setShort(index * 15 + 1, v1) *> + statement.setInt(index * 15 + 2, v2) *> + statement.setInt(index * 15 + 3, v3) *> + statement.setInt(index * 15 + 4, v4) *> + statement.setLong(index * 15 + 5, v5) *> + statement.setFloat(index * 15 + 6, v6) *> + statement.setDouble(index * 15 + 7, v7) *> + statement.setBigDecimal(index * 15 + 8, v8.bigDecimal) *> + statement.setString(index * 15 + 9, v9) *> + statement.setString(index * 15 + 10, v10) *> + statement.setBoolean(index * 15 + 11, v11) *> + statement.setDate(index * 15 + 12, v12) *> + statement.setTime(index * 15 + 13, v13) *> + statement.setTimestamp(index * 15 + 14, v14) *> + statement.setTimestamp(index * 15 + 15, v15) + } _ <- statement.executeUpdate() yield () } diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala index ef8a19470..3848be7e3 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala @@ -21,14 +21,31 @@ import cats.syntax.all.* import cats.effect.* import cats.effect.unsafe.implicits.global -import ldbc.sql.{Connection, ResultSet} +import ldbc.sql.{ Connection, ResultSet } @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) class Select: - type BenchmarkType = (Long, Short, Int, Int, Int, Long, Float, Double, BigDecimal, String, String, Boolean, LocalDate, LocalTime, LocalDateTime, LocalDateTime) + type BenchmarkType = ( + Long, + Short, + Int, + Int, + Int, + Long, + Float, + Double, + BigDecimal, + String, + String, + Boolean, + LocalDate, + LocalTime, + LocalDateTime, + LocalDateTime + ) @volatile var connection: Resource[IO, Connection[IO]] = uninitialized @@ -56,17 +73,17 @@ class Select: for // 処理時間の計測を入れる statement <- conn.createStatement() - start <- IO(System.nanoTime()) + start <- IO(System.nanoTime()) resultSet <- statement.executeQuery(s"SELECT * FROM jdbc_statement_test LIMIT $len") - end <- IO(System.nanoTime()) - _ <- IO.println("============") *> IO(println(s"statement: ${end - start} nanos")) - records <- consume(resultSet) + end <- IO(System.nanoTime()) + _ <- IO.println("============") *> IO(println(s"statement: ${ end - start } nanos")) + records <- consume(resultSet) yield records } .unsafeRunSync() - //@Benchmark - //def prepareStatement: List[BenchmarkType] = + // @Benchmark + // def prepareStatement: List[BenchmarkType] = // connection // .use { conn => // for @@ -84,15 +101,15 @@ class Select: case false => Monad[IO].pure(acc) case true => for - c1 <- resultSet.getLong(1) - c2 <- resultSet.getShort(2) - c3 <- resultSet.getInt(3) - c4 <- resultSet.getInt(4) - c5 <- resultSet.getInt(5) - c6 <- resultSet.getLong(6) - c7 <- resultSet.getFloat(7) - c8 <- resultSet.getDouble(8) - c9 <- resultSet.getBigDecimal(9) + c1 <- resultSet.getLong(1) + c2 <- resultSet.getShort(2) + c3 <- resultSet.getInt(3) + c4 <- resultSet.getInt(4) + c5 <- resultSet.getInt(5) + c6 <- resultSet.getLong(6) + c7 <- resultSet.getFloat(7) + c8 <- resultSet.getDouble(8) + c9 <- resultSet.getBigDecimal(9) c10 <- resultSet.getString(10) c11 <- resultSet.getString(11) c12 <- resultSet.getBoolean(12) @@ -100,8 +117,7 @@ class Select: c14 <- resultSet.getTime(14) c15 <- resultSet.getTimestamp(15) c16 <- resultSet.getTimestamp(16) - yield - acc <+> Vector((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)) + yield acc <+> Vector((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)) } loop(Vector.empty).map(_.toList) diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala index 53d5c5a1d..f1b8f290a 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Batch.scala @@ -60,10 +60,12 @@ class Batch: for statement <- conn.createStatement() _ <- records.foldLeft(IO.unit) { - case (acc, (id, value)) => - acc *> - statement.addBatch(s"INSERT INTO ldbc_statement_test (c1, c2) VALUES ${records.map { case (v1, v2) => s"($v1, '$v2')" }.mkString(", ")}") - } + case (acc, (id, value)) => + acc *> + statement.addBatch(s"INSERT INTO ldbc_statement_test (c1, c2) VALUES ${ records + .map { case (v1, v2) => s"($v1, '$v2')" } + .mkString(", ") }") + } _ <- statement.executeBatch() yield () } diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala index 08e976ad8..04085ee16 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Insert.scala @@ -34,7 +34,25 @@ class Insert: var values: String = uninitialized @volatile - var records: List[(Short, Int, Int, Int, Long, Float, Double, BigDecimal, String, String, Boolean, LocalDate, LocalTime, LocalDateTime, LocalDateTime)] = List.empty + var records: List[ + ( + Short, + Int, + Int, + Int, + Long, + Float, + Double, + BigDecimal, + String, + String, + Boolean, + LocalDate, + LocalTime, + LocalDateTime, + LocalDateTime + ) + ] = List.empty @Setup def setup(): Unit = @@ -49,7 +67,27 @@ class Insert: values = (1 to len).map(_ => "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").mkString(",") - records = (1 to len).map(num => (1.toShort, 1, 1, 1, 1L, 1.1f, 1.1, BigDecimal.decimal(1.1), s"varchar $num", s"text $num", true, LocalDate.now(), LocalTime.now(), LocalDateTime.now(), LocalDateTime.now())).toList + records = (1 to len) + .map(num => + ( + 1.toShort, + 1, + 1, + 1, + 1L, + 1.1f, + 1.1, + BigDecimal.decimal(1.1), + s"varchar $num", + s"text $num", + true, + LocalDate.now(), + LocalTime.now(), + LocalDateTime.now(), + LocalDateTime.now() + ) + ) + .toList @Param(Array("10", "100", "1000", "2000", "4000")) var len: Int = uninitialized @@ -60,7 +98,16 @@ class Insert: .use { conn => for statement <- conn.createStatement() - _ <- statement.executeUpdate(s"INSERT INTO ldbc_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES ${records.map { case (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) => s"($v1, $v2, $v3, $v4, $v5, $v6, $v7, $v8, '$v9', '$v10', $v11, '$v12', '$v13', '${v14.toString.replace("T", " ")}', '${v15.toString.replace("T", " ")}')" }.mkString(",")}") + _ <- + statement.executeUpdate( + s"INSERT INTO ldbc_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES ${ records + .map { + case (v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) => + s"($v1, $v2, $v3, $v4, $v5, $v6, $v7, $v8, '$v9', '$v10', $v11, '$v12', '$v13', '${ v14.toString + .replace("T", " ") }', '${ v15.toString.replace("T", " ") }')" + } + .mkString(",") }" + ) yield () } .unsafeRunSync() @@ -70,26 +117,29 @@ class Insert: connection .use { conn => for - statement <- conn.prepareStatement(s"INSERT INTO ldbc_prepare_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES $values") + statement <- + conn.prepareStatement( + s"INSERT INTO ldbc_prepare_statement_test (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) VALUES $values" + ) _ <- records.zipWithIndex.foldLeft(IO.unit) { - case (acc, ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15), index)) => - acc *> - statement.setShort(index * 15 + 1, v1) *> - statement.setInt(index * 15 + 2, v2) *> - statement.setInt(index * 15 + 3, v3) *> - statement.setInt(index * 15 + 4, v4) *> - statement.setLong(index * 15 + 5, v5) *> - statement.setFloat(index * 15 + 6, v6) *> - statement.setDouble(index * 15 + 7, v7) *> - statement.setBigDecimal(index * 15 + 8, v8.bigDecimal) *> - statement.setString(index * 15 + 9, v9) *> - statement.setString(index * 15 + 10, v10) *> - statement.setBoolean(index * 15 + 11, v11) *> - statement.setDate(index * 15 + 12, v12) *> - statement.setTime(index * 15 + 13, v13) *> - statement.setTimestamp(index * 15 + 14, v14) *> - statement.setTimestamp(index * 15 + 15, v15) - } + case (acc, ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15), index)) => + acc *> + statement.setShort(index * 15 + 1, v1) *> + statement.setInt(index * 15 + 2, v2) *> + statement.setInt(index * 15 + 3, v3) *> + statement.setInt(index * 15 + 4, v4) *> + statement.setLong(index * 15 + 5, v5) *> + statement.setFloat(index * 15 + 6, v6) *> + statement.setDouble(index * 15 + 7, v7) *> + statement.setBigDecimal(index * 15 + 8, v8.bigDecimal) *> + statement.setString(index * 15 + 9, v9) *> + statement.setString(index * 15 + 10, v10) *> + statement.setBoolean(index * 15 + 11, v11) *> + statement.setDate(index * 15 + 12, v12) *> + statement.setTime(index * 15 + 13, v13) *> + statement.setTimestamp(index * 15 + 14, v14) *> + statement.setTimestamp(index * 15 + 15, v15) + } _ <- statement.executeUpdate() yield () } diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala index e04bcdd5f..c601d9023 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala @@ -29,7 +29,24 @@ import ldbc.connector.* @State(Scope.Benchmark) class Select: - type BenchmarkType = (Long, Short, Int, Int, Int, Long, Float, Double, BigDecimal, String, String, Boolean, LocalDate, LocalTime, LocalDateTime, LocalDateTime) + type BenchmarkType = ( + Long, + Short, + Int, + Int, + Int, + Long, + Float, + Double, + BigDecimal, + String, + String, + Boolean, + LocalDate, + LocalTime, + LocalDateTime, + LocalDateTime + ) given Tracer[IO] = Tracer.noop[IO] @@ -57,17 +74,17 @@ class Select: for // 処理時間の計測を入れる statement <- conn.createStatement() - //start <- IO(System.nanoTime()) + // start <- IO(System.nanoTime()) resultSet <- statement.executeQuery(s"SELECT * FROM jdbc_statement_test LIMIT $len") - //end <- IO(System.nanoTime()) - //_ <- IO.println("============") *> IO(println(s"statement: ${end - start} nanos")) + // end <- IO(System.nanoTime()) + // _ <- IO.println("============") *> IO(println(s"statement: ${end - start} nanos")) records <- consume(resultSet) yield records } .unsafeRunSync() - //@Benchmark - //def prepareStatement: List[BenchmarkType] = + // @Benchmark + // def prepareStatement: List[BenchmarkType] = // connection // .use { conn => // for @@ -85,15 +102,15 @@ class Select: case false => Monad[IO].pure(acc) case true => for - c1 <- resultSet.getLong(1) - c2 <- resultSet.getShort(2) - c3 <- resultSet.getInt(3) - c4 <- resultSet.getInt(4) - c5 <- resultSet.getInt(5) - c6 <- resultSet.getLong(6) - c7 <- resultSet.getFloat(7) - c8 <- resultSet.getDouble(8) - c9 <- resultSet.getBigDecimal(9) + c1 <- resultSet.getLong(1) + c2 <- resultSet.getShort(2) + c3 <- resultSet.getInt(3) + c4 <- resultSet.getInt(4) + c5 <- resultSet.getInt(5) + c6 <- resultSet.getLong(6) + c7 <- resultSet.getFloat(7) + c8 <- resultSet.getDouble(8) + c9 <- resultSet.getBigDecimal(9) c10 <- resultSet.getString(10) c11 <- resultSet.getString(11) c12 <- resultSet.getBoolean(12) @@ -101,8 +118,7 @@ class Select: c14 <- resultSet.getTime(14) c15 <- resultSet.getTimestamp(15) c16 <- resultSet.getTimestamp(16) - yield - acc <+> Vector((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)) + yield acc <+> Vector((c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16)) } loop(Vector.empty).map(_.toList) diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala index 1a81fd91d..317108cd5 100644 --- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala +++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala @@ -48,15 +48,15 @@ object PacketSocket: ): PacketSocket[F] = new PacketSocket[F]: private def debug(msg: => String): F[Unit] = - Concurrent[F].whenA(debugEnabled) { - sequenceIdRef.get.flatMap(id => Console[F].println(s"[$id] $msg")) - } - //sequenceIdRef.get - // .flatMap(id => if debugEnabled then Console[F].println(s"[$id] $msg") else Concurrent[F].unit) + Concurrent[F].whenA(debugEnabled) { + sequenceIdRef.get.flatMap(id => Console[F].println(s"[$id] $msg")) + } + // sequenceIdRef.get + // .flatMap(id => if debugEnabled then Console[F].println(s"[$id] $msg") else Concurrent[F].unit) override def receive[P <: ResponsePacket](decoder: Decoder[P]): F[P] = (for - start <- Concurrent[F].pure(System.nanoTime()) + start <- Concurrent[F].pure(System.nanoTime()) header <- bvs.read(4) payloadSize = parseHeader(header.toByteArray) payload <- bvs.read(payloadSize) diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala index 188599fb7..cf468f532 100644 --- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala +++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala @@ -54,10 +54,10 @@ object EOFPacket: yield EOFPacket(status, warnings, statusFlags) else Decoder.pure(EOFPacket(status, 0, 0)) - //provide(EOFPacket(status, None, None)) + // provide(EOFPacket(status, None, None)) } - //for + // for // status <- uint4 // warnings <- if hasClientProtocol41Flag then uint4.map(_.some) else provide(None) // statusFlags <- if hasClientProtocol41Flag then uint4.map(_.some) else provide(None) - //yield EOFPacket(status, warnings, statusFlags) + // yield EOFPacket(status, warnings, statusFlags) diff --git a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ResultSetTest.scala b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ResultSetTest.scala index 83b11e81e..98647ecdb 100644 --- a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ResultSetTest.scala +++ b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ResultSetTest.scala @@ -4,7 +4,6 @@ * For more information see LICENSE or https://opensource.org/licenses/MIT */ -/* package ldbc.connector import java.time.* @@ -929,5 +928,3 @@ class ResultSetTest extends CatsEffectSuite: flags = flags, decimals = if useScale then 2 else 0 ) - - */ From 1338e86454c429263d71cb3995217db84d04a983 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Mon, 5 Aug 2024 23:07:29 +0900 Subject: [PATCH 41/57] Action sbt scalafmtAll --- .../src/main/scala/ldbc/connector/net/PacketSocket.scala | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala index 317108cd5..3da50f24f 100644 --- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala +++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala @@ -48,11 +48,9 @@ object PacketSocket: ): PacketSocket[F] = new PacketSocket[F]: private def debug(msg: => String): F[Unit] = - Concurrent[F].whenA(debugEnabled) { - sequenceIdRef.get.flatMap(id => Console[F].println(s"[$id] $msg")) - } - // sequenceIdRef.get - // .flatMap(id => if debugEnabled then Console[F].println(s"[$id] $msg") else Concurrent[F].unit) + Concurrent[F].whenA(debugEnabled) { + sequenceIdRef.get.flatMap(id => Console[F].println(s"[$id] $msg")) + } override def receive[P <: ResponsePacket](decoder: Decoder[P]): F[P] = (for From 98d42c3462b8b9c14fcb495dde3004aa30a0ad03 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 6 Aug 2024 00:05:44 +0900 Subject: [PATCH 42/57] Delete unused --- .../src/main/scala/ldbc/connector/net/PacketSocket.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala index 3da50f24f..a328e2cc9 100644 --- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala +++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/PacketSocket.scala @@ -54,15 +54,13 @@ object PacketSocket: override def receive[P <: ResponsePacket](decoder: Decoder[P]): F[P] = (for - start <- Concurrent[F].pure(System.nanoTime()) header <- bvs.read(4) payloadSize = parseHeader(header.toByteArray) payload <- bvs.read(payloadSize) response = decoder.decodeValue(payload).require - end <- Concurrent[F].pure(System.nanoTime()) _ <- debug( - s"Client ${ AnsiColor.BLUE }←${ AnsiColor.RESET } Server: ${ AnsiColor.GREEN }$response${ AnsiColor.RESET } Time: ${ end - start } nanos" + s"Client ${ AnsiColor.BLUE }←${ AnsiColor.RESET } Server: ${ AnsiColor.GREEN }$response${ AnsiColor.RESET }" ) _ <- sequenceIdRef.update(_ => ((header.toByteArray(3) + 1) % 256).toByte) yield response).onError { From 02af7ec7f777015927c6f24759f2bb48e39ecb5e Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 6 Aug 2024 00:06:06 +0900 Subject: [PATCH 43/57] Delete unused comment out code --- .../ldbc/connector/net/packet/response/EOFPacket.scala | 6 ------ 1 file changed, 6 deletions(-) diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala index cf468f532..24273c1f9 100644 --- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala +++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala @@ -54,10 +54,4 @@ object EOFPacket: yield EOFPacket(status, warnings, statusFlags) else Decoder.pure(EOFPacket(status, 0, 0)) - // provide(EOFPacket(status, None, None)) } - // for - // status <- uint4 - // warnings <- if hasClientProtocol41Flag then uint4.map(_.some) else provide(None) - // statusFlags <- if hasClientProtocol41Flag then uint4.map(_.some) else provide(None) - // yield EOFPacket(status, warnings, statusFlags) From ea6d2d8f1730306af902e85e9b41358e1f19db29 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 6 Aug 2024 00:06:52 +0900 Subject: [PATCH 44/57] Action sbt scalafmtAll --- .../scala/ldbc/connector/net/packet/response/EOFPacket.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala index 24273c1f9..9810b1eca 100644 --- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala +++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/net/packet/response/EOFPacket.scala @@ -52,6 +52,5 @@ object EOFPacket: warnings <- uint4 statusFlags <- uint4 yield EOFPacket(status, warnings, statusFlags) - else - Decoder.pure(EOFPacket(status, 0, 0)) + else Decoder.pure(EOFPacket(status, 0, 0)) } From 6c3b501837bf9b0955e8430d1d0c43c689c5b489 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Mon, 12 Aug 2024 18:02:42 +0900 Subject: [PATCH 45/57] Delete measure debug code --- .../benchmark/connector/jdbc/Select.scala | 28 ++++++++----------- .../benchmark/connector/ldbc/Select.scala | 28 ++++++++----------- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala index 3848be7e3..71f5a8ced 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala @@ -71,29 +71,25 @@ class Select: connection .use { conn => for - // 処理時間の計測を入れる statement <- conn.createStatement() - start <- IO(System.nanoTime()) resultSet <- statement.executeQuery(s"SELECT * FROM jdbc_statement_test LIMIT $len") - end <- IO(System.nanoTime()) - _ <- IO.println("============") *> IO(println(s"statement: ${ end - start } nanos")) records <- consume(resultSet) yield records } .unsafeRunSync() - // @Benchmark - // def prepareStatement: List[BenchmarkType] = - // connection - // .use { conn => - // for - // statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") - // _ <- statement.setInt(1, len) - // resultSet <- statement.executeQuery() - // records <- consume(resultSet) - // yield records - // } - // .unsafeRunSync() + @Benchmark + def prepareStatement: List[BenchmarkType] = + connection + .use { conn => + for + statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") + _ <- statement.setInt(1, len) + resultSet <- statement.executeQuery() + records <- consume(resultSet) + yield records + } + .unsafeRunSync() private def consume(resultSet: ResultSet[IO]): IO[List[BenchmarkType]] = def loop(acc: Vector[BenchmarkType]): IO[Vector[BenchmarkType]] = diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala index c601d9023..bb39322dd 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala @@ -72,29 +72,25 @@ class Select: connection .use { conn => for - // 処理時間の計測を入れる statement <- conn.createStatement() - // start <- IO(System.nanoTime()) resultSet <- statement.executeQuery(s"SELECT * FROM jdbc_statement_test LIMIT $len") - // end <- IO(System.nanoTime()) - // _ <- IO.println("============") *> IO(println(s"statement: ${end - start} nanos")) records <- consume(resultSet) yield records } .unsafeRunSync() - // @Benchmark - // def prepareStatement: List[BenchmarkType] = - // connection - // .use { conn => - // for - // statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") - // _ <- statement.setInt(1, len) - // resultSet <- statement.executeQuery() - // records <- consume(resultSet) - // yield records - // } - // .unsafeRunSync() + @Benchmark + def prepareStatement: List[BenchmarkType] = + connection + .use { conn => + for + statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") + _ <- statement.setInt(1, len) + resultSet <- statement.executeQuery() + records <- consume(resultSet) + yield records + } + .unsafeRunSync() private def consume(resultSet: ResultSet[IO]): IO[List[BenchmarkType]] = def loop(acc: Vector[BenchmarkType]): IO[Vector[BenchmarkType]] = From 0595685633f670deb6527dddb7c864b381b76743 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 13 Aug 2024 18:29:43 +0900 Subject: [PATCH 46/57] Fixed Benchmark Param --- benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala index bb39322dd..bf5c623e5 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala @@ -64,7 +64,7 @@ class Select: ssl = SSL.Trusted ) - @Param(Array("4000")) + @Param(Array("10", "100", "1000", "2000", "4000")) var len: Int = uninitialized @Benchmark From 2d596199eed78d5ada9b7c29c826e3f402683b22 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 13 Aug 2024 18:30:00 +0900 Subject: [PATCH 47/57] Added formatter PASCAL settings --- benchmark/src/main/scala/benchmark/Model.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/benchmark/src/main/scala/benchmark/Model.scala b/benchmark/src/main/scala/benchmark/Model.scala index 16d6a8fb8..4137ae5b2 100644 --- a/benchmark/src/main/scala/benchmark/Model.scala +++ b/benchmark/src/main/scala/benchmark/Model.scala @@ -7,6 +7,9 @@ package benchmark import ldbc.query.builder.Table +import ldbc.query.builder.formatter.Naming + +given Naming = Naming.PASCAL case class Model1( c1: Int From ca2236923c12f784235e9249ef5fbf0270242bb7 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 13 Aug 2024 18:30:20 +0900 Subject: [PATCH 48/57] Added additionalSettings in benchmark project --- build.sbt | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sbt b/build.sbt index e4113d70a..ba9c272a9 100644 --- a/build.sbt +++ b/build.sbt @@ -197,6 +197,7 @@ lazy val tests = crossProject(JVMPlatform) lazy val benchmark = (project in file("benchmark")) .settings(description := "Projects for Benchmark Measurement") + .settings(scalacOptions ++= additionalSettings) .settings(scalacOptions --= removeSettings) .settings(commonSettings) .settings( From 72fd73ca3b256ab12298747047866f17a2acf5df Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 13 Aug 2024 18:30:42 +0900 Subject: [PATCH 49/57] Create wrapper benchmark code --- .../benchmark/wrapper/doobie/Select.scala | 52 +++++++++++++ .../scala/benchmark/wrapper/ldbc/Select.scala | 73 +++++++++++++++++++ .../benchmark/wrapper/slick/Select.scala | 68 +++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 benchmark/src/main/scala/benchmark/wrapper/doobie/Select.scala create mode 100644 benchmark/src/main/scala/benchmark/wrapper/ldbc/Select.scala create mode 100644 benchmark/src/main/scala/benchmark/wrapper/slick/Select.scala diff --git a/benchmark/src/main/scala/benchmark/wrapper/doobie/Select.scala b/benchmark/src/main/scala/benchmark/wrapper/doobie/Select.scala new file mode 100644 index 000000000..8d146a3de --- /dev/null +++ b/benchmark/src/main/scala/benchmark/wrapper/doobie/Select.scala @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.wrapper.doobie + +import java.util.concurrent.TimeUnit + +import scala.compiletime.uninitialized + +import com.mysql.cj.jdbc.MysqlDataSource + +import org.openjdk.jmh.annotations.* + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import doobie.* +import doobie.implicits.* + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Select: + + @volatile + var transactor: Resource[IO, Transactor[IO]] = uninitialized + + @Setup + def setup(): Unit = + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("world") + ds.setUser("ldbc") + ds.setPassword("password") + + transactor = ExecutionContexts.fixedThreadPool[IO](1).map(ce => Transactor.fromDataSource[IO](ds, ce)) + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @Benchmark + def selectN: List[(Int, String, String)] = + transactor.use { xa => + sql"SELECT ID, Name, CountryCode FROM city LIMIT $len" + .query[(Int, String, String)] + .to[List] + .transact(xa) + }.unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/wrapper/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/wrapper/ldbc/Select.scala new file mode 100644 index 000000000..5bbabc94d --- /dev/null +++ b/benchmark/src/main/scala/benchmark/wrapper/ldbc/Select.scala @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.wrapper.ldbc + +import java.util.concurrent.TimeUnit + +import scala.compiletime.uninitialized + +import com.mysql.cj.jdbc.MysqlDataSource + +import org.openjdk.jmh.annotations.* + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import ldbc.sql.Connection +import ldbc.query.builder.Table +import ldbc.query.builder.syntax.io.* + +import benchmark.City + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Select: + + @volatile + var connection: Resource[IO, Connection[IO]] = uninitialized + + @volatile + var query: Table[City] = uninitialized + + @Setup + def setup(): Unit = + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("world") + ds.setUser("ldbc") + ds.setPassword("password") + + val datasource = jdbc.connector.MysqlDataSource[IO](ds) + + connection = Resource.make(datasource.getConnection)(_.close()) + + query = Table[City]("city") + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @Benchmark + def querySelectN: List[(Int, String, String)] = + connection.use { conn => + query + .select(city => (city.id, city.name, city.countryCode)) + .limit(len) + .query + .to[List] + .readOnly(conn) + }.unsafeRunSync() + + @Benchmark + def dslSelectN: List[(Int, String, String)] = + connection.use { conn => + sql"SELECT ID, Name, CountryCode FROM city LIMIT $len" + .query[(Int, String, String)] + .to[List] + .readOnly(conn) + }.unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/wrapper/slick/Select.scala b/benchmark/src/main/scala/benchmark/wrapper/slick/Select.scala new file mode 100644 index 000000000..321679067 --- /dev/null +++ b/benchmark/src/main/scala/benchmark/wrapper/slick/Select.scala @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.wrapper.slick + +import java.util.concurrent.TimeUnit + +import scala.concurrent.Await +import scala.concurrent.duration.Duration +import scala.compiletime.uninitialized + +import com.mysql.cj.jdbc.MysqlDataSource + +import org.openjdk.jmh.annotations.* + +import slick.jdbc.MySQLProfile.api.* + +import benchmark.City + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Select: + + @volatile + var db: Database = uninitialized + + @volatile + var query: TableQuery[CityTable] = uninitialized + + @Setup + def setup(): Unit = + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("world") + ds.setUser("ldbc") + ds.setPassword("password") + + db = Database.forDataSource(ds, None) + + query = TableQuery[CityTable] + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @TearDown + def closeDatabase(): Unit = + db.close() + + @Benchmark + def selectN: Seq[(Int, String, String)] = + Await.result( + db.run(query.map(city => (city.id, city.name, city.countryCode)).take(len).result), + Duration.Inf + ) + +class CityTable(tag: Tag) extends Table[City](tag, "city"): + def id = column[Int]("ID", O.AutoInc, O.PrimaryKey) + def name = column[String]("Name") + def countryCode = column[String]("CountryCode") + def district = column[String]("District") + def population = column[Int]("Population") + + def * = (id, name, countryCode, district, population).mapTo[City] From 9c08512c12dbbd8c6a0c58f9ece67a4a2b394e2a Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 13 Aug 2024 18:31:47 +0900 Subject: [PATCH 50/57] Added TYPES settings --- script/benchmark.sh | 59 +++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/script/benchmark.sh b/script/benchmark.sh index 6b698dc31..215929062 100755 --- a/script/benchmark.sh +++ b/script/benchmark.sh @@ -19,24 +19,26 @@ SUFFIX='' file_path() { PROJECT=$1 TARGET=$2 - FEATURE=$3 + TYPE=$3 + FEATURE=$4 - echo "${PROJECT}/src/main/scala/benchmark/connector/${TARGET}/${FEATURE}.scala" + echo "${PROJECT}/src/main/scala/benchmark/${TYPE}/${TARGET}/${FEATURE}.scala" } run() { PROJECT=$1 TARGET=$2 - FEATURE=$3 + TYPE=$3 + FEATURE=$4 - FILE=$(file_path "$PROJECT" "$TARGET" "$FEATURE") + FILE=$(file_path "$PROJECT" "$TARGET" "$TYPE" "$FEATURE") [ -r "$FILE" ] || return 0 - mkdir -p "script/${OUT_DIR}/${TARGET}" - OUTPUT="script/${OUT_DIR}/${TARGET}/${FEATURE}.json" + mkdir -p "script/${OUT_DIR}/${TYPE}/${TARGET}" + OUTPUT="script/${OUT_DIR}/${TYPE}/${TARGET}/${FEATURE}.json" - #$sbt "${PROJECT} / clean" - $sbt "${PROJECT} / Jmh / run $OPTIONS connector[.]${TARGET}[.]${FEATURE}[.] -rf json -rff ../${OUTPUT}" + $sbt "${PROJECT} / clean" + $sbt "${PROJECT} / Jmh / run $OPTIONS ${TYPE}[.]${TARGET}[.]${FEATURE}[.] -rf json -rff ../${OUTPUT}" OUTPUTS+=("$OUTPUT") } @@ -101,10 +103,19 @@ do break done +[ ${#TYPES[@]} = 0 ] && { + TYPES=( + 'connector' + 'wrapper' + ) +} + [ ${#TARGETS[@]} = 0 ] && { TARGETS=( 'jdbc' 'ldbc' + 'doobie' + 'slick' ) } @@ -116,17 +127,26 @@ done ) } +EXCLUDE=('doobie' 'slick') + run_feature() { - FEATURE="$1" + TYPE="$1" + FEATURE="$2" + # If TYPE is connector, only jdbc and ldbc are targeted. + [ "$TYPE" = "connector" ] && TARGETS=(${TARGETS[@]/doobie/}) + [ "$TYPE" = "connector" ] && TARGETS=(${TARGETS[@]/slick/}) + for target in ${TARGETS[@]}; do - run "benchmark" "$target" "${FEATURE}" + run "benchmark" "$target" "${TYPE}" "${FEATURE}" done - CHART_INPUT="script/${OUT_DIR}/${PREFIX}${FEATURE}${SUFFIX}.json" - CHART_OUTPUT="docs/src/main/mdoc/img/${PREFIX}${FEATURE}${SUFFIX}.svg" + CHART_INPUT="script/${OUT_DIR}/${TYPE}/${PREFIX}${FEATURE}${SUFFIX}.json" + CHART_OUTPUT="docs/src/main/mdoc/img/${TYPE}/${PREFIX}${FEATURE}${SUFFIX}.svg" - OUTPUTS+=("script/${OUT_DIR}/jdbc/${FEATURE}.json") - #OUTPUTS+=("script/${OUT_DIR}/ldbc/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/${TYPE}/jdbc/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/${TYPE}/ldbc/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/${TYPE}/doobie/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/${TYPE}/slick/${FEATURE}.json") for output in ${OUTPUTS[@]}; do jq '.[]' "${output}" @@ -137,6 +157,13 @@ run_feature() { OUTPUTS=() } -for feature in ${FEATURES[@]}; do - run_feature "$feature" +run_type() { + TYPE="$1" + for feature in ${FEATURES[@]}; do + run_feature "$TYPE" "$feature" + done +} + +for type in ${TYPES[@]}; do + run_type "$type" done From 0fe70e2dc852a9936382f20fc82fb45aedc55321 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 13 Aug 2024 18:32:03 +0900 Subject: [PATCH 51/57] Added target_names --- script/python/visualize.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/script/python/visualize.py b/script/python/visualize.py index f9a9f94bf..f91a1e845 100644 --- a/script/python/visualize.py +++ b/script/python/visualize.py @@ -13,6 +13,10 @@ 'jdbc_prepareStatement': 'jdbc: prepareStatement', 'ldbc_statement': 'ldbc: statement', 'ldbc_prepareStatement': 'ldbc: prepareStatement', + 'ldbc_querySelectN': 'ldbc (query builder)', + 'ldbc_dslSelectN': 'ldbc (plain sql)', + 'doobie_selectN': 'doobie', + 'slick_selectN': 'slick', } plot_config = { From 22698d02f94d03d0b4c9f3044e55a8657c5679be Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 13 Aug 2024 22:38:59 +0900 Subject: [PATCH 52/57] Delete unused --- .../benchmark/caseclass/CompileCreate.scala | 42 ------- .../benchmark/caseclass/RuntimeCreate.scala | 101 ----------------- .../benchmark/doobie/CompileCreateQuery.scala | 43 ------- .../main/scala/benchmark/doobie/Insert.scala | 65 ----------- .../benchmark/doobie/RuntimeCreateQuery.scala | 71 ------------ .../main/scala/benchmark/doobie/Select.scala | 48 -------- .../scala/benchmark/lepus/CompileCreate.scala | 44 -------- .../benchmark/lepus/CompileCreateQuery.scala | 43 ------- .../main/scala/benchmark/lepus/Insert.scala | 73 ------------ .../scala/benchmark/lepus/RuntimeCreate.scala | 103 ----------------- .../benchmark/lepus/RuntimeCreateQuery.scala | 93 ---------------- .../main/scala/benchmark/lepus/Select.scala | 65 ----------- .../benchmark/slick/CompileCreateQuery.scala | 48 -------- .../benchmark/slick/CompileCreation.scala | 45 -------- .../main/scala/benchmark/slick/Insert.scala | 69 ------------ .../scala/benchmark/slick/RuntimeCreate.scala | 82 -------------- .../benchmark/slick/RuntimeCreateQuery.scala | 105 ------------------ .../main/scala/benchmark/slick/Select.scala | 60 ---------- 18 files changed, 1200 deletions(-) delete mode 100644 benchmark/src/main/scala/benchmark/caseclass/CompileCreate.scala delete mode 100644 benchmark/src/main/scala/benchmark/caseclass/RuntimeCreate.scala delete mode 100644 benchmark/src/main/scala/benchmark/doobie/CompileCreateQuery.scala delete mode 100644 benchmark/src/main/scala/benchmark/doobie/Insert.scala delete mode 100644 benchmark/src/main/scala/benchmark/doobie/RuntimeCreateQuery.scala delete mode 100644 benchmark/src/main/scala/benchmark/doobie/Select.scala delete mode 100644 benchmark/src/main/scala/benchmark/lepus/CompileCreate.scala delete mode 100644 benchmark/src/main/scala/benchmark/lepus/CompileCreateQuery.scala delete mode 100644 benchmark/src/main/scala/benchmark/lepus/Insert.scala delete mode 100644 benchmark/src/main/scala/benchmark/lepus/RuntimeCreate.scala delete mode 100644 benchmark/src/main/scala/benchmark/lepus/RuntimeCreateQuery.scala delete mode 100644 benchmark/src/main/scala/benchmark/lepus/Select.scala delete mode 100644 benchmark/src/main/scala/benchmark/slick/CompileCreateQuery.scala delete mode 100644 benchmark/src/main/scala/benchmark/slick/CompileCreation.scala delete mode 100644 benchmark/src/main/scala/benchmark/slick/Insert.scala delete mode 100644 benchmark/src/main/scala/benchmark/slick/RuntimeCreate.scala delete mode 100644 benchmark/src/main/scala/benchmark/slick/RuntimeCreateQuery.scala delete mode 100644 benchmark/src/main/scala/benchmark/slick/Select.scala diff --git a/benchmark/src/main/scala/benchmark/caseclass/CompileCreate.scala b/benchmark/src/main/scala/benchmark/caseclass/CompileCreate.scala deleted file mode 100644 index 20e37ffa4..000000000 --- a/benchmark/src/main/scala/benchmark/caseclass/CompileCreate.scala +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.caseclass - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import benchmark.Compiler - -@BenchmarkMode(Array(Mode.SingleShotTime)) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class CompileCreate: - - @Param(Array("1", "5", "10", "20", "25")) - var size: Int = 0 - - var source: String = "" - - var compiler: Compiler = uninitialized - - @Setup(Level.Iteration) - def setup(): Unit = - compiler = new Compiler - - val properties = (1 to size).map(i => s"c$i: Int").mkString(",\n") - - source = s""" - |case class Table$size( - | $properties - |) - |""".stripMargin - - @Benchmark - def createCaseClassN = compiler.compile(source) diff --git a/benchmark/src/main/scala/benchmark/caseclass/RuntimeCreate.scala b/benchmark/src/main/scala/benchmark/caseclass/RuntimeCreate.scala deleted file mode 100644 index af77f0f50..000000000 --- a/benchmark/src/main/scala/benchmark/caseclass/RuntimeCreate.scala +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.caseclass - -import java.util.concurrent.TimeUnit - -import org.openjdk.jmh.annotations.* - -import benchmark.* - -@BenchmarkMode(Array(Mode.AverageTime)) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 10, time = 200, timeUnit = TimeUnit.MILLISECONDS) -@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class RuntimeCreate: - - @Benchmark - def createM1 = Model1( - c1 = 1 - ) - - @Benchmark - def createM5 = Model5( - c1 = 1, - c2 = 2, - c3 = 3, - c4 = 4, - c5 = 5 - ) - - @Benchmark - def createM10 = Model10( - c1 = 1, - c2 = 2, - c3 = 3, - c4 = 4, - c5 = 5, - c6 = 6, - c7 = 7, - c8 = 8, - c9 = 9, - c10 = 10 - ) - - @Benchmark - def createM20 = Model20( - c1 = 1, - c2 = 2, - c3 = 3, - c4 = 4, - c5 = 5, - c6 = 6, - c7 = 7, - c8 = 8, - c9 = 9, - c10 = 10, - c11 = 11, - c12 = 12, - c13 = 13, - c14 = 14, - c15 = 15, - c16 = 16, - c17 = 17, - c18 = 18, - c19 = 19, - c20 = 20 - ) - - @Benchmark - def createM25 = Model25( - c1 = 1, - c2 = 2, - c3 = 3, - c4 = 4, - c5 = 5, - c6 = 6, - c7 = 7, - c8 = 8, - c9 = 9, - c10 = 10, - c11 = 11, - c12 = 12, - c13 = 13, - c14 = 14, - c15 = 15, - c16 = 16, - c17 = 17, - c18 = 18, - c19 = 19, - c20 = 20, - c21 = 21, - c22 = 22, - c23 = 23, - c24 = 24, - c25 = 25 - ) diff --git a/benchmark/src/main/scala/benchmark/doobie/CompileCreateQuery.scala b/benchmark/src/main/scala/benchmark/doobie/CompileCreateQuery.scala deleted file mode 100644 index 9ff0f2697..000000000 --- a/benchmark/src/main/scala/benchmark/doobie/CompileCreateQuery.scala +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.doobie - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import benchmark.Compiler - -@BenchmarkMode(Array(Mode.SingleShotTime)) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class CompileCreateQuery: - - @Param(Array("1", "5", "10", "20", "25")) - var size: Int = 0 - - var source: String = "" - - var compiler: Compiler = uninitialized - - @Setup(Level.Iteration) - def setup(): Unit = - compiler = new Compiler - - source = s""" - |import doobie.* - |import doobie.implicits.* - | - |val len = 5000 - |val query = sql"SELECT ${ (1 to size).map(i => s"c$i").mkString(", ") } FROM model$size LIMIT $$len" - | .query[(${ (1 to size).map(_ => "Int").mkString(", ") })] - |""".stripMargin - - @Benchmark - def createQuery = compiler.compile(source) diff --git a/benchmark/src/main/scala/benchmark/doobie/Insert.scala b/benchmark/src/main/scala/benchmark/doobie/Insert.scala deleted file mode 100644 index 7d73a4b93..000000000 --- a/benchmark/src/main/scala/benchmark/doobie/Insert.scala +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.doobie - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import cats.data.NonEmptyList - -import cats.effect.IO -import cats.effect.unsafe.implicits.global - -import doobie.* -import doobie.implicits.* -import doobie.util.fragments.values - -@BenchmarkMode(Array(Mode.Throughput)) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -class Insert: - - @volatile - var xa: Transactor[IO] = uninitialized - - @volatile - var records: NonEmptyList[(Int, String)] = uninitialized - - @Setup - def setupDataSource(): Unit = - xa = Transactor.after.set( - Transactor.fromDriverManager[IO]( - "com.mysql.cj.jdbc.Driver", - "jdbc:mysql://127.0.0.1:13306/world", - "ldbc", - "password", - None - ), - HC.rollback - ) - - records = NonEmptyList.fromListUnsafe((1 to len).map(num => (num, s"record$num")).toList) - - @Param(Array("10", "100", "1000", "2000", "4000")) - var len: Int = uninitialized - - @Benchmark - def insertN: Unit = - (sql"INSERT INTO test (c1, c2)" ++ values(records)).update.run - .transact(xa) - .unsafeRunSync() - - @Benchmark - def batchN: Unit = - val sql = "INSERT INTO test (c1, c2) VALUES (?, ?)" - Update[(Int, String)](sql) - .updateMany(records) - .transact(xa) - .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/doobie/RuntimeCreateQuery.scala b/benchmark/src/main/scala/benchmark/doobie/RuntimeCreateQuery.scala deleted file mode 100644 index 5c7dff059..000000000 --- a/benchmark/src/main/scala/benchmark/doobie/RuntimeCreateQuery.scala +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.doobie - -import java.util.concurrent.TimeUnit - -import org.openjdk.jmh.annotations.* - -import doobie.* -import doobie.implicits.* - -import benchmark.* - -@BenchmarkMode(Array(Mode.AverageTime)) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 10, time = 200, timeUnit = TimeUnit.MILLISECONDS) -@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class RuntimeCreateQuery: - - @Benchmark - def createM1 = sql"SELECT c1 FROM model1".query[Int] - - @Benchmark - def createM5 = sql"SELECT c1, c2, c3, c4, c5 FROM model5".query[(Int, Int, Int, Int, Int)] - - @Benchmark - def createM10 = sql"SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 FROM model10" - .query[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)] - - @Benchmark - def createM20 = - sql"SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20 FROM model20" - .query[(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)] - - @Benchmark - def createM25 = - sql"SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25 FROM model25" - .query[ - ( - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int, - Int - ) - ] diff --git a/benchmark/src/main/scala/benchmark/doobie/Select.scala b/benchmark/src/main/scala/benchmark/doobie/Select.scala deleted file mode 100644 index 6613d62af..000000000 --- a/benchmark/src/main/scala/benchmark/doobie/Select.scala +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.doobie - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import cats.effect.IO -import cats.effect.unsafe.implicits.global - -import doobie.* -import doobie.implicits.* - -@BenchmarkMode(Array(Mode.Throughput)) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -class Select: - - @volatile - var xa: Transactor[IO] = uninitialized - - @Setup - def setup(): Unit = - xa = Transactor.fromDriverManager[IO]( - "com.mysql.cj.jdbc.Driver", - "jdbc:mysql://127.0.0.1:13306/world", - "ldbc", - "password", - None - ) - - @Param(Array("10", "100", "1000", "2000", "4000")) - var len: Int = uninitialized - - @Benchmark - def selectN: List[(Int, String, String)] = - sql"SELECT ID, Name, CountryCode FROM city LIMIT $len" - .query[(Int, String, String)] - .to[List] - .transact(xa) - .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/lepus/CompileCreate.scala b/benchmark/src/main/scala/benchmark/lepus/CompileCreate.scala deleted file mode 100644 index dcc89c7c0..000000000 --- a/benchmark/src/main/scala/benchmark/lepus/CompileCreate.scala +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.lepus - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import benchmark.Compiler - -@BenchmarkMode(Array(Mode.SingleShotTime)) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class CompileCreate: - - @Param(Array("1", "5", "10", "20", "25")) - var size: Int = 0 - - var source: String = "" - - var compiler: Compiler = uninitialized - - @Setup(Level.Iteration) - def setup(): Unit = - compiler = new Compiler - - val columns = (1 to size).map(i => s"column(\"c$i\", INT)").mkString(",\n") - - source = s""" - |import ldbc.core.* - |import benchmark.Model$size - |val table = Table[Model$size](\"model$size\")( - | $columns - |) - |""".stripMargin - - @Benchmark - def createTableN = compiler.compile(source) diff --git a/benchmark/src/main/scala/benchmark/lepus/CompileCreateQuery.scala b/benchmark/src/main/scala/benchmark/lepus/CompileCreateQuery.scala deleted file mode 100644 index 3eb4b82e3..000000000 --- a/benchmark/src/main/scala/benchmark/lepus/CompileCreateQuery.scala +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.lepus - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import benchmark.Compiler - -@BenchmarkMode(Array(Mode.SingleShotTime)) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class CompileCreateQuery: - - @Param(Array("1", "5", "10", "20", "25")) - var size: Int = 0 - - var source: String = "" - - var compiler: Compiler = uninitialized - - @Setup(Level.Iteration) - def setup(): Unit = - compiler = new Compiler - - source = s""" - |import ldbc.query.builder.Table - |import benchmark.Model$size - |val tableQuery = Table[Model$size] - | - |val query = tableQuery.select(v => (${ (1 to size).map(i => s"v.c$i").mkString(", ") })) - | .limit(5000) - |""".stripMargin - - @Benchmark - def createQuery = compiler.compile(source) diff --git a/benchmark/src/main/scala/benchmark/lepus/Insert.scala b/benchmark/src/main/scala/benchmark/lepus/Insert.scala deleted file mode 100644 index 9aff7c492..000000000 --- a/benchmark/src/main/scala/benchmark/lepus/Insert.scala +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.lepus - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import com.mysql.cj.jdbc.MysqlDataSource - -import org.openjdk.jmh.annotations.* - -import cats.effect.IO -import cats.effect.unsafe.implicits.global - -import ldbc.sql.DataSource -import ldbc.dsl.logging.LogHandler -import ldbc.query.builder.Table -import ldbc.query.builder.syntax.io.* - -@BenchmarkMode(Array(Mode.Throughput)) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -class Insert: - - @volatile - var dataSource: DataSource[IO] = uninitialized - - @volatile - var noLog: LogHandler[IO] = uninitialized - - @volatile - var query: Table[Test] = uninitialized - - @volatile - var records: List[(Int, String)] = List.empty - - @Setup - def setupDataSource(): Unit = - val ds = new MysqlDataSource() - ds.setServerName("127.0.0.1") - ds.setPortNumber(13306) - ds.setDatabaseName("world") - ds.setUser("ldbc") - ds.setPassword("password") - dataSource = jdbc.connector.MysqlDataSource[IO](ds) - - records = (1 to len).map(num => (num, s"record$num")).toList - - noLog = _ => IO.unit - - query = Table[Test] - - @Param(Array("10", "100", "1000", "2000", "4000")) - var len: Int = uninitialized - - @Benchmark - def insertN: Unit = - given LogHandler[IO] = noLog - (for - connection <- dataSource.getConnection - result <- query - .insertInto(test => (test.c1, test.c2)) - .values(records) - .update - .rollback(connection) - yield result).unsafeRunSync() - -case class Test(id: Option[Int], c1: Int, c2: String) derives Table diff --git a/benchmark/src/main/scala/benchmark/lepus/RuntimeCreate.scala b/benchmark/src/main/scala/benchmark/lepus/RuntimeCreate.scala deleted file mode 100644 index 90dcd843f..000000000 --- a/benchmark/src/main/scala/benchmark/lepus/RuntimeCreate.scala +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.lepus - -import java.util.concurrent.TimeUnit - -import org.openjdk.jmh.annotations.* - -import ldbc.schema.* - -import benchmark.* - -@BenchmarkMode(Array(Mode.AverageTime)) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 10, time = 200, timeUnit = TimeUnit.MILLISECONDS) -@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class RuntimeCreate: - - @Benchmark - def createM1 = Table[Model1]("model1")( - column("c1", INT) - ) - - @Benchmark - def createM5 = Table[Model5]("model5")( - column("c1", INT), - column("c2", INT), - column("c3", INT), - column("c4", INT), - column("c5", INT) - ) - - @Benchmark - def createM10 = Table[Model10]("model10")( - column("c1", INT), - column("c2", INT), - column("c3", INT), - column("c4", INT), - column("c5", INT), - column("c6", INT), - column("c7", INT), - column("c8", INT), - column("c9", INT), - column("c10", INT) - ) - - @Benchmark - def createM20 = Table[Model20]("model20")( - column("c1", INT), - column("c2", INT), - column("c3", INT), - column("c4", INT), - column("c5", INT), - column("c6", INT), - column("c7", INT), - column("c8", INT), - column("c9", INT), - column("c10", INT), - column("c11", INT), - column("c12", INT), - column("c13", INT), - column("c14", INT), - column("c15", INT), - column("c16", INT), - column("c17", INT), - column("c18", INT), - column("c19", INT), - column("c20", INT) - ) - - @Benchmark - def createM25 = Table[Model25]("model25")( - column("c1", INT), - column("c2", INT), - column("c3", INT), - column("c4", INT), - column("c5", INT), - column("c6", INT), - column("c7", INT), - column("c8", INT), - column("c9", INT), - column("c10", INT), - column("c11", INT), - column("c12", INT), - column("c13", INT), - column("c14", INT), - column("c15", INT), - column("c16", INT), - column("c17", INT), - column("c18", INT), - column("c19", INT), - column("c20", INT), - column("c21", INT), - column("c22", INT), - column("c23", INT), - column("c24", INT), - column("c25", INT) - ) diff --git a/benchmark/src/main/scala/benchmark/lepus/RuntimeCreateQuery.scala b/benchmark/src/main/scala/benchmark/lepus/RuntimeCreateQuery.scala deleted file mode 100644 index bf56c7cea..000000000 --- a/benchmark/src/main/scala/benchmark/lepus/RuntimeCreateQuery.scala +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.lepus - -import java.util.concurrent.TimeUnit - -import org.openjdk.jmh.annotations.* - -import ldbc.query.builder.Table - -import benchmark.* - -@BenchmarkMode(Array(Mode.AverageTime)) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 10, time = 200, timeUnit = TimeUnit.MILLISECONDS) -@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class RuntimeCreateQuery: - - @Benchmark - def createM1 = - Table[Model1].select(_.c1) - - @Benchmark - def createM5 = - Table[Model5].select(v => (v.c1, v.c2, v.c3, v.c4, v.c5)) - - @Benchmark - def createM10 = - Table[Model10].select(v => (v.c1, v.c2, v.c3, v.c4, v.c5, v.c6, v.c7, v.c8, v.c9, v.c10)) - - @Benchmark - def createM20 = - Table[Model20].select(v => - ( - v.c1, - v.c2, - v.c3, - v.c4, - v.c5, - v.c6, - v.c7, - v.c8, - v.c9, - v.c10, - v.c11, - v.c12, - v.c13, - v.c14, - v.c15, - v.c16, - v.c17, - v.c18, - v.c19, - v.c20 - ) - ) - - @Benchmark - def createM25 = - Table[Model25].select(v => - ( - v.c1, - v.c2, - v.c3, - v.c4, - v.c5, - v.c6, - v.c7, - v.c8, - v.c9, - v.c10, - v.c11, - v.c12, - v.c13, - v.c14, - v.c15, - v.c16, - v.c17, - v.c18, - v.c19, - v.c20, - v.c21, - v.c22, - v.c23, - v.c24, - v.c25 - ) - ) diff --git a/benchmark/src/main/scala/benchmark/lepus/Select.scala b/benchmark/src/main/scala/benchmark/lepus/Select.scala deleted file mode 100644 index 9bfc87fe7..000000000 --- a/benchmark/src/main/scala/benchmark/lepus/Select.scala +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.lepus - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import com.mysql.cj.jdbc.MysqlDataSource - -import org.openjdk.jmh.annotations.* - -import cats.effect.IO -import cats.effect.unsafe.implicits.global - -import ldbc.sql.DataSource -import ldbc.dsl.logging.LogHandler -import ldbc.query.builder.Table -import ldbc.query.builder.syntax.io.* - -import benchmark.City - -@BenchmarkMode(Array(Mode.Throughput)) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -class Select: - - @volatile - var dataSource: DataSource[IO] = uninitialized - - @volatile - var noLog: LogHandler[IO] = uninitialized - - @Setup - def setup(): Unit = - val ds = new MysqlDataSource() - ds.setServerName("127.0.0.1") - ds.setPortNumber(13306) - ds.setDatabaseName("world") - ds.setUser("ldbc") - ds.setPassword("password") - dataSource = jdbc.connector.MysqlDataSource[IO](ds) - - noLog = _ => IO.unit - - @Param(Array("10", "100", "1000", "2000", "4000")) - var len: Int = uninitialized - - @Benchmark - def selectN: List[(Int, String, String)] = - given LogHandler[IO] = noLog - (for - connection <- dataSource.getConnection - result <- Table[City] - .select(city => (city.id, city.name, city.countryCode)) - .limit(len) - .query - .to[List] - .readOnly(connection) - yield result) - .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/slick/CompileCreateQuery.scala b/benchmark/src/main/scala/benchmark/slick/CompileCreateQuery.scala deleted file mode 100644 index c0d8848c9..000000000 --- a/benchmark/src/main/scala/benchmark/slick/CompileCreateQuery.scala +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.slick - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import benchmark.Compiler - -@BenchmarkMode(Array(Mode.SingleShotTime)) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class CompileCreateQuery: - - @Param(Array("1", "5", "10", "20", "25")) - var size: Int = 0 - - var source: String = "" - - var compiler: Compiler = uninitialized - - @Setup(Level.Iteration) - def setup(): Unit = - compiler = new Compiler - - val columns = (1 to size).map(i => s"def c$i = column[Int](\"c$i\")").mkString("\n ") - val * = (1 to size).map(i => s"c$i").mkString(", ") - - source = s""" - |import slick.jdbc.MySQLProfile.api.* - |import benchmark.Model$size - |class Model${ size }Table(tag: Tag) extends Table[Model$size](tag, "model$size"): - | $columns - | def * = (${ * }).mapTo[Model$size] - | - |val tableQuery = TableQuery[Model${ size }Table] - |val query = tableQuery.map(v => (${ (1 to size).map(i => s"v.c$i").mkString(", ") })).take(5000) - |""".stripMargin - - @Benchmark - def createQuery = compiler.compile(source) diff --git a/benchmark/src/main/scala/benchmark/slick/CompileCreation.scala b/benchmark/src/main/scala/benchmark/slick/CompileCreation.scala deleted file mode 100644 index 105a9f607..000000000 --- a/benchmark/src/main/scala/benchmark/slick/CompileCreation.scala +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.slick - -import java.util.concurrent.TimeUnit - -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import benchmark.Compiler - -@BenchmarkMode(Array(Mode.SingleShotTime)) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class CompileCreation: - - @Param(Array("1", "5", "10", "20", "25")) - var size: Int = 0 - - var source: String = "" - - var compiler: Compiler = uninitialized - - @Setup(Level.Iteration) - def setup(): Unit = - compiler = new Compiler - - val columns = (1 to size).map(i => s"def c$i = column[Int](\"c$i\")").mkString("\n ") - val * = (1 to size).map(i => s"c$i").mkString(", ") - - source = s""" - |import slick.jdbc.MySQLProfile.api.* - |import benchmark.Model$size - |class Model${ size }Table(tag: Tag) extends Table[Model$size](tag, "model$size"): - | $columns - | def * = (${ * }).mapTo[Model$size] - |""".stripMargin - - @Benchmark - def createTableN = compiler.compile(source) diff --git a/benchmark/src/main/scala/benchmark/slick/Insert.scala b/benchmark/src/main/scala/benchmark/slick/Insert.scala deleted file mode 100644 index 94dc5c4b9..000000000 --- a/benchmark/src/main/scala/benchmark/slick/Insert.scala +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.slick - -import java.util.concurrent.TimeUnit - -import scala.concurrent.Await -import scala.concurrent.duration.Duration -import scala.compiletime.uninitialized - -import slick.jdbc.MySQLProfile.api.* - -import org.openjdk.jmh.annotations.* - -@BenchmarkMode(Array(Mode.Throughput)) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -class Insert: - - @volatile - var db: Database = uninitialized - - @volatile - var query: TableQuery[TestTable] = uninitialized - - @volatile - var records: List[Test] = List.empty - - @Setup - def setupDataSource(): Unit = - db = Database.forURL( - url = "jdbc:mysql://127.0.0.1:13306/world", - user = "ldbc", - password = "password", - driver = "com.mysql.cj.jdbc.Driver" - ) - - query = TableQuery[TestTable] - - records = (1 to len).map(num => Test(None, num, s"record$num")).toList - - @Param(Array("10", "100", "1000", "2000", "4000")) - var len: Int = uninitialized - - @Benchmark - def insertN: Unit = - Await.result( - db.run(query ++= records), - Duration.Inf - ) - - // @Benchmark - // def batchN: Unit = - // Await.result( - // db.run(query ++= records), - // Duration.Inf - // ) - -case class Test(id: Option[Int], c1: Int, c2: String) -class TestTable(tag: Tag) extends Table[Test](tag, "test"): - def id = column[Int]("id", O.AutoInc, O.PrimaryKey) - def c1 = column[Int]("c1") - def c2 = column[String]("c2") - - def * = (id, c1, c2).mapTo[Test] diff --git a/benchmark/src/main/scala/benchmark/slick/RuntimeCreate.scala b/benchmark/src/main/scala/benchmark/slick/RuntimeCreate.scala deleted file mode 100644 index b6f964061..000000000 --- a/benchmark/src/main/scala/benchmark/slick/RuntimeCreate.scala +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.slick - -import java.util.concurrent.TimeUnit - -import org.openjdk.jmh.annotations.* - -import slick.jdbc.MySQLProfile.api.* - -import benchmark.* - -@BenchmarkMode(Array(Mode.AverageTime)) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 10, time = 200, timeUnit = TimeUnit.MILLISECONDS) -@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class RuntimeCreate: - - @Benchmark - def createM1 = - class Model1Table(tag: Tag) extends Table[Model1](tag, "model1"): - def c1 = column[Int]("c1") - def * = (c1).mapTo[Model1] - TableQuery[Model1Table] - - @Benchmark - def createM5 = - class Model5Table(tag: Tag) extends Table[Model5](tag, "model5"): - def c1 = column[Int]("c1") - def c2 = column[Int]("c2") - def c3 = column[Int]("c3") - def c4 = column[Int]("c4") - def c5 = column[Int]("c5") - def * = (c1, c2, c3, c4, c5).mapTo[Model5] - TableQuery[Model5Table] - - @Benchmark - def createM10 = - class Model10Table(tag: Tag) extends Table[Model10](tag, "model10"): - def c1 = column[Int]("c1") - def c2 = column[Int]("c2") - def c3 = column[Int]("c3") - def c4 = column[Int]("c4") - def c5 = column[Int]("c5") - def c6 = column[Int]("c6") - def c7 = column[Int]("c7") - def c8 = column[Int]("c8") - def c9 = column[Int]("c9") - def c10 = column[Int]("c10") - def * = (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10).mapTo[Model10] - TableQuery[Model10Table] - - @Benchmark - def createM20 = - class Model20Table(tag: Tag) extends Table[Model20](tag, "model20"): - def c1 = column[Int]("c1") - def c2 = column[Int]("c2") - def c3 = column[Int]("c3") - def c4 = column[Int]("c4") - def c5 = column[Int]("c5") - def c6 = column[Int]("c6") - def c7 = column[Int]("c7") - def c8 = column[Int]("c8") - def c9 = column[Int]("c9") - def c10 = column[Int]("c10") - def c11 = column[Int]("c11") - def c12 = column[Int]("c12") - def c13 = column[Int]("c13") - def c14 = column[Int]("c14") - def c15 = column[Int]("c15") - def c16 = column[Int]("c16") - def c17 = column[Int]("c17") - def c18 = column[Int]("c18") - def c19 = column[Int]("c19") - def c20 = column[Int]("c20") - def * = (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20).mapTo[Model20] - TableQuery[Model20Table] diff --git a/benchmark/src/main/scala/benchmark/slick/RuntimeCreateQuery.scala b/benchmark/src/main/scala/benchmark/slick/RuntimeCreateQuery.scala deleted file mode 100644 index fdb9bcc06..000000000 --- a/benchmark/src/main/scala/benchmark/slick/RuntimeCreateQuery.scala +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.slick - -import java.util.concurrent.TimeUnit - -import org.openjdk.jmh.annotations.* - -import slick.jdbc.MySQLProfile.api.* - -import benchmark.* - -@BenchmarkMode(Array(Mode.AverageTime)) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 10, time = 200, timeUnit = TimeUnit.MILLISECONDS) -@Measurement(iterations = 20, time = 500, timeUnit = TimeUnit.MILLISECONDS) -@State(Scope.Thread) -class RuntimeCreateQuery: - - @Benchmark - def createM1 = - class Model1Table(tag: Tag) extends Table[Model1](tag, "model1"): - def c1 = column[Int]("c1") - def * = (c1).mapTo[Model1] - TableQuery[Model1Table].map(_.c1) - - @Benchmark - def createM5 = - class Model5Table(tag: Tag) extends Table[Model5](tag, "model5"): - def c1 = column[Int]("c1") - def c2 = column[Int]("c2") - def c3 = column[Int]("c3") - def c4 = column[Int]("c4") - def c5 = column[Int]("c5") - def * = (c1, c2, c3, c4, c5).mapTo[Model5] - TableQuery[Model5Table].map(v => (v.c1, v.c2, v.c3, v.c4, v.c5)) - - @Benchmark - def createM10 = - class Model10Table(tag: Tag) extends Table[Model10](tag, "model10"): - def c1 = column[Int]("c1") - def c2 = column[Int]("c2") - def c3 = column[Int]("c3") - def c4 = column[Int]("c4") - def c5 = column[Int]("c5") - def c6 = column[Int]("c6") - def c7 = column[Int]("c7") - def c8 = column[Int]("c8") - def c9 = column[Int]("c9") - def c10 = column[Int]("c10") - def * = (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10).mapTo[Model10] - TableQuery[Model10Table].map(v => (v.c1, v.c2, v.c3, v.c4, v.c5, v.c6, v.c7, v.c8, v.c9, v.c10)) - - @Benchmark - def createM20 = - class Model20Table(tag: Tag) extends Table[Model20](tag, "model20"): - def c1 = column[Int]("c1") - def c2 = column[Int]("c2") - def c3 = column[Int]("c3") - def c4 = column[Int]("c4") - def c5 = column[Int]("c5") - def c6 = column[Int]("c6") - def c7 = column[Int]("c7") - def c8 = column[Int]("c8") - def c9 = column[Int]("c9") - def c10 = column[Int]("c10") - def c11 = column[Int]("c11") - def c12 = column[Int]("c12") - def c13 = column[Int]("c13") - def c14 = column[Int]("c14") - def c15 = column[Int]("c15") - def c16 = column[Int]("c16") - def c17 = column[Int]("c17") - def c18 = column[Int]("c18") - def c19 = column[Int]("c19") - def c20 = column[Int]("c20") - def * = (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20).mapTo[Model20] - TableQuery[Model20Table].map(v => - ( - v.c1, - v.c2, - v.c3, - v.c4, - v.c5, - v.c6, - v.c7, - v.c8, - v.c9, - v.c10, - v.c11, - v.c12, - v.c13, - v.c14, - v.c15, - v.c16, - v.c17, - v.c18, - v.c19, - v.c20 - ) - ) diff --git a/benchmark/src/main/scala/benchmark/slick/Select.scala b/benchmark/src/main/scala/benchmark/slick/Select.scala deleted file mode 100644 index c47f85843..000000000 --- a/benchmark/src/main/scala/benchmark/slick/Select.scala +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2023-2024 by Takahiko Tominaga - * This software is licensed under the MIT License (MIT). - * For more information see LICENSE or https://opensource.org/licenses/MIT - */ - -package benchmark.slick - -import java.util.concurrent.TimeUnit - -import scala.concurrent.Await -import scala.concurrent.duration.Duration -import scala.compiletime.uninitialized - -import org.openjdk.jmh.annotations.* - -import slick.jdbc.MySQLProfile.api.* - -import benchmark.City - -@BenchmarkMode(Array(Mode.Throughput)) -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Benchmark) -class Select: - - @volatile - var db: Database = uninitialized - - @volatile - var query: TableQuery[CityTable] = uninitialized - - @Setup - def setup(): Unit = - db = Database.forURL( - url = "jdbc:mysql://127.0.0.1:13306/world", - user = "ldbc", - password = "password", - driver = "com.mysql.cj.jdbc.Driver" - ) - - query = TableQuery[CityTable] - - @Param(Array("10", "100", "1000", "2000", "4000")) - var len: Int = uninitialized - - @Benchmark - def selectN: Seq[(Int, String, String)] = - Await.result( - db.run(query.map(city => (city.id, city.name, city.countryCode)).take(len).result), - Duration.Inf - ) - -class CityTable(tag: Tag) extends Table[City](tag, "city"): - def id = column[Int]("ID", O.AutoInc, O.PrimaryKey) - def name = column[String]("Name") - def countryCode = column[String]("CountryCode") - def district = column[String]("District") - def population = column[Int]("Population") - - def * = (id, name, countryCode, district, population).mapTo[City] From 27d6e935d5b5e4746b92d2c1c3c38187aca76ffe Mon Sep 17 00:00:00 2001 From: takapi327 Date: Tue, 13 Aug 2024 22:46:54 +0900 Subject: [PATCH 53/57] Create wrapper Insert Benchmark --- .../benchmark/wrapper/doobie/Insert.scala | 67 ++++++++++++++++ .../scala/benchmark/wrapper/ldbc/Insert.scala | 78 +++++++++++++++++++ .../benchmark/wrapper/slick/Insert.scala | 77 ++++++++++++++++++ 3 files changed, 222 insertions(+) create mode 100644 benchmark/src/main/scala/benchmark/wrapper/doobie/Insert.scala create mode 100644 benchmark/src/main/scala/benchmark/wrapper/ldbc/Insert.scala create mode 100644 benchmark/src/main/scala/benchmark/wrapper/slick/Insert.scala diff --git a/benchmark/src/main/scala/benchmark/wrapper/doobie/Insert.scala b/benchmark/src/main/scala/benchmark/wrapper/doobie/Insert.scala new file mode 100644 index 000000000..bc0b82422 --- /dev/null +++ b/benchmark/src/main/scala/benchmark/wrapper/doobie/Insert.scala @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.wrapper.doobie + +import java.util.concurrent.TimeUnit + +import scala.compiletime.uninitialized + +import com.mysql.cj.jdbc.MysqlDataSource + +import org.openjdk.jmh.annotations.* + +import cats.data.NonEmptyList + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import doobie.* +import doobie.implicits.* +import doobie.util.fragments.values + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Insert: + + @volatile + var transactor: Resource[IO, Transactor[IO]] = uninitialized + + @volatile + var records: NonEmptyList[(Int, String)] = uninitialized + + @Setup + def setupDataSource(): Unit = + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("world") + ds.setUser("ldbc") + ds.setPassword("password") + + transactor = ExecutionContexts.fixedThreadPool[IO](1).map(ce => Transactor.fromDataSource[IO](ds, ce)) + + records = NonEmptyList.fromListUnsafe((1 to len).map(num => (num, s"record$num")).toList) + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @Benchmark + def insertN: Unit = + transactor.use { xa => + (sql"INSERT INTO test (c1, c2)" ++ values(records)).update.run + .transact(xa) + }.unsafeRunSync() + + @Benchmark + def batchN: Unit = + transactor.use { xa => + val sql = "INSERT INTO test (c1, c2) VALUES (?, ?)" + Update[(Int, String)](sql) + .updateMany(records) + .transact(xa) + }.unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/wrapper/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/wrapper/ldbc/Insert.scala new file mode 100644 index 000000000..e6ca49715 --- /dev/null +++ b/benchmark/src/main/scala/benchmark/wrapper/ldbc/Insert.scala @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.wrapper.ldbc + +import java.util.concurrent.TimeUnit + +import scala.compiletime.uninitialized + +import com.mysql.cj.jdbc.MysqlDataSource + +import org.openjdk.jmh.annotations.* + +import cats.data.NonEmptyList + +import cats.effect.* +import cats.effect.unsafe.implicits.global + +import ldbc.sql.Connection +import ldbc.query.builder.Table +import ldbc.query.builder.syntax.io.* + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Insert: + + @volatile + var connection: Resource[IO, Connection[IO]] = uninitialized + + @volatile + var query: Table[Test] = uninitialized + + @volatile + var records: List[(Int, String)] = List.empty + + @Setup + def setupDataSource(): Unit = + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("world") + ds.setUser("ldbc") + ds.setPassword("password") + + val datasource = jdbc.connector.MysqlDataSource[IO](ds) + + connection = Resource.make(datasource.getConnection)(_.close()) + + records = (1 to len).map(num => (num, s"record$num")).toList + + query = Table[Test] + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @Benchmark + def queryInsertN: Unit = + connection.use { conn => + query + .insertInto(test => (test.c1, test.c2)) + .values(records) + .update + .commit(conn) + }.unsafeRunSync() + + @Benchmark + def dslInsertN: Unit = + connection.use { conn => + (sql"INSERT INTO test (c1, c2)" ++ values(NonEmptyList.fromListUnsafe(records))) + .update + .commit(conn) + }.unsafeRunSync() + +case class Test(id: Option[Int], c1: Int, c2: String) derives Table diff --git a/benchmark/src/main/scala/benchmark/wrapper/slick/Insert.scala b/benchmark/src/main/scala/benchmark/wrapper/slick/Insert.scala new file mode 100644 index 000000000..79fccf4f7 --- /dev/null +++ b/benchmark/src/main/scala/benchmark/wrapper/slick/Insert.scala @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2023-2024 by Takahiko Tominaga + * This software is licensed under the MIT License (MIT). + * For more information see LICENSE or https://opensource.org/licenses/MIT + */ + +package benchmark.wrapper.slick + +import java.util.concurrent.TimeUnit + +import scala.concurrent.Await +import scala.concurrent.duration.Duration +import scala.compiletime.uninitialized + +import com.mysql.cj.jdbc.MysqlDataSource + +import slick.jdbc.MySQLProfile.api.* + +import org.openjdk.jmh.annotations.* + +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class Insert: + + @volatile + var db: Database = uninitialized + + @volatile + var query: TableQuery[TestTable] = uninitialized + + @volatile + var records: List[Test] = List.empty + + @Setup + def setupDataSource(): Unit = + val ds = new MysqlDataSource() + ds.setServerName("127.0.0.1") + ds.setPortNumber(13306) + ds.setDatabaseName("world") + ds.setUser("ldbc") + ds.setPassword("password") + + db = Database.forDataSource(ds, None) + + query = TableQuery[TestTable] + + records = (1 to len).map(num => Test(None, num, s"record$num")).toList + + @Param(Array("10", "100", "1000", "2000", "4000")) + var len: Int = uninitialized + + @TearDown + def closeDatabase(): Unit = + db.close() + + @Benchmark + def insertN: Unit = + Await.result( + db.run(query ++= records), + Duration.Inf + ) + + @Benchmark + def batchN: Unit = + Await.result( + db.run(query ++= records), + Duration.Inf + ) + +case class Test(id: Option[Int], c1: Int, c2: String) +class TestTable(tag: Tag) extends Table[Test](tag, "test"): + def id = column[Int]("id", O.AutoInc, O.PrimaryKey) + def c1 = column[Int]("c1") + def c2 = column[String]("c2") + + def * = (id, c1, c2).mapTo[Test] From 0b89912f119935200855381b1c87703c6f83e6ae Mon Sep 17 00:00:00 2001 From: takapi327 Date: Wed, 14 Aug 2024 12:41:04 +0900 Subject: [PATCH 54/57] Renam TYPE -> KIND --- script/benchmark.sh | 56 +++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/script/benchmark.sh b/script/benchmark.sh index 215929062..43fab92bc 100755 --- a/script/benchmark.sh +++ b/script/benchmark.sh @@ -19,26 +19,26 @@ SUFFIX='' file_path() { PROJECT=$1 TARGET=$2 - TYPE=$3 + KIND=$3 FEATURE=$4 - echo "${PROJECT}/src/main/scala/benchmark/${TYPE}/${TARGET}/${FEATURE}.scala" + echo "${PROJECT}/src/main/scala/benchmark/${KIND}/${TARGET}/${FEATURE}.scala" } run() { PROJECT=$1 TARGET=$2 - TYPE=$3 + KIND=$3 FEATURE=$4 - FILE=$(file_path "$PROJECT" "$TARGET" "$TYPE" "$FEATURE") + FILE=$(file_path "$PROJECT" "$TARGET" "$KIND" "$FEATURE") [ -r "$FILE" ] || return 0 - mkdir -p "script/${OUT_DIR}/${TYPE}/${TARGET}" - OUTPUT="script/${OUT_DIR}/${TYPE}/${TARGET}/${FEATURE}.json" + mkdir -p "script/${OUT_DIR}/${KIND}/${TARGET}" + OUTPUT="script/${OUT_DIR}/${KIND}/${TARGET}/${FEATURE}.json" $sbt "${PROJECT} / clean" - $sbt "${PROJECT} / Jmh / run $OPTIONS ${TYPE}[.]${TARGET}[.]${FEATURE}[.] -rf json -rff ../${OUTPUT}" + $sbt "${PROJECT} / Jmh / run $OPTIONS ${KIND}[.]${TARGET}[.]${FEATURE}[.] -rf json -rff ../${OUTPUT}" OUTPUTS+=("$OUTPUT") } @@ -76,6 +76,12 @@ do continue } + [ "$1" = '-k' ] && [ -n "$2" ] && { + KINDS+=("$2") + shift; shift + continue + } + [ "$1" = '-t' ] && [ -n "$2" ] && { TARGETS+=("$2") shift; shift @@ -103,8 +109,8 @@ do break done -[ ${#TYPES[@]} = 0 ] && { - TYPES=( +[ ${#KINDS[@]} = 0 ] && { + KINDS=( 'connector' 'wrapper' ) @@ -130,23 +136,23 @@ done EXCLUDE=('doobie' 'slick') run_feature() { - TYPE="$1" + KIND="$1" FEATURE="$2" - # If TYPE is connector, only jdbc and ldbc are targeted. - [ "$TYPE" = "connector" ] && TARGETS=(${TARGETS[@]/doobie/}) - [ "$TYPE" = "connector" ] && TARGETS=(${TARGETS[@]/slick/}) + # If KIND is connector, only jdbc and ldbc are targeted. + [ "$KIND" = "connector" ] && TARGETS=(${TARGETS[@]/doobie/}) + [ "$KIND" = "connector" ] && TARGETS=(${TARGETS[@]/slick/}) for target in ${TARGETS[@]}; do - run "benchmark" "$target" "${TYPE}" "${FEATURE}" + run "benchmark" "$target" "${KIND}" "${FEATURE}" done - CHART_INPUT="script/${OUT_DIR}/${TYPE}/${PREFIX}${FEATURE}${SUFFIX}.json" - CHART_OUTPUT="docs/src/main/mdoc/img/${TYPE}/${PREFIX}${FEATURE}${SUFFIX}.svg" + CHART_INPUT="script/${OUT_DIR}/${KIND}/${PREFIX}${FEATURE}${SUFFIX}.json" + CHART_OUTPUT="docs/src/main/mdoc/img/${KIND}/${PREFIX}${FEATURE}${SUFFIX}.svg" - #OUTPUTS+=("script/${OUT_DIR}/${TYPE}/jdbc/${FEATURE}.json") - #OUTPUTS+=("script/${OUT_DIR}/${TYPE}/ldbc/${FEATURE}.json") - #OUTPUTS+=("script/${OUT_DIR}/${TYPE}/doobie/${FEATURE}.json") - #OUTPUTS+=("script/${OUT_DIR}/${TYPE}/slick/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/${KIND}/jdbc/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/${KIND}/ldbc/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/${KIND}/doobie/${FEATURE}.json") + #OUTPUTS+=("script/${OUT_DIR}/${KIND}/slick/${FEATURE}.json") for output in ${OUTPUTS[@]}; do jq '.[]' "${output}" @@ -157,13 +163,13 @@ run_feature() { OUTPUTS=() } -run_type() { - TYPE="$1" +run_kind() { + KIND="$1" for feature in ${FEATURES[@]}; do - run_feature "$TYPE" "$feature" + run_feature "$KIND" "$feature" done } -for type in ${TYPES[@]}; do - run_type "$type" +for kind in ${KINDS[@]}; do + run_kind "$kind" done From 0ad2cc3004dd9b6ecfd08c65e63e9b3c65fd75ed Mon Sep 17 00:00:00 2001 From: takapi327 Date: Wed, 14 Aug 2024 12:41:24 +0900 Subject: [PATCH 55/57] Added insertN benchmark --- script/python/visualize.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/script/python/visualize.py b/script/python/visualize.py index f91a1e845..3c192a2e2 100644 --- a/script/python/visualize.py +++ b/script/python/visualize.py @@ -17,6 +17,10 @@ 'ldbc_dslSelectN': 'ldbc (plain sql)', 'doobie_selectN': 'doobie', 'slick_selectN': 'slick', + 'ldbc_queryInsertN': 'ldbc (query builder)', + 'ldbc_dslInsertN': 'ldbc (plain sql)', + 'doobie_insertN': 'doobie', + 'slick_insertN': 'slick', } plot_config = { From 878c2f1a6de6df0071bc21ee41cbfe8269da9da9 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Wed, 14 Aug 2024 12:41:53 +0900 Subject: [PATCH 56/57] Added docs image --- docs/src/main/mdoc/img/connector/Select.svg | 1487 +++++++++++++++++++ docs/src/main/mdoc/img/wrapper/Select.svg | 1258 ++++++++++++++++ 2 files changed, 2745 insertions(+) create mode 100644 docs/src/main/mdoc/img/connector/Select.svg create mode 100644 docs/src/main/mdoc/img/wrapper/Select.svg diff --git a/docs/src/main/mdoc/img/connector/Select.svg b/docs/src/main/mdoc/img/connector/Select.svg new file mode 100644 index 000000000..25079f432 --- /dev/null +++ b/docs/src/main/mdoc/img/connector/Select.svg @@ -0,0 +1,1487 @@ + + + + + + + + 2024-08-12T12:37:55.113757 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/main/mdoc/img/wrapper/Select.svg b/docs/src/main/mdoc/img/wrapper/Select.svg new file mode 100644 index 000000000..0db468e40 --- /dev/null +++ b/docs/src/main/mdoc/img/wrapper/Select.svg @@ -0,0 +1,1258 @@ + + + + + + + + 2024-08-13T14:37:21.894535 + image/svg+xml + + + Matplotlib v3.8.4, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 8c8bc61ec1ef32105a484a3a919f8588deb419e0 Mon Sep 17 00:00:00 2001 From: takapi327 Date: Wed, 14 Aug 2024 12:43:23 +0900 Subject: [PATCH 57/57] Action sbt scalafmtAll --- .../benchmark/connector/jdbc/Select.scala | 20 ++++++------ .../benchmark/connector/ldbc/Select.scala | 22 ++++++------- .../benchmark/wrapper/doobie/Insert.scala | 24 ++++++++------ .../benchmark/wrapper/doobie/Select.scala | 14 ++++---- .../scala/benchmark/wrapper/ldbc/Insert.scala | 29 +++++++++-------- .../scala/benchmark/wrapper/ldbc/Select.scala | 32 +++++++++++-------- .../benchmark/wrapper/slick/Insert.scala | 8 ++--- 7 files changed, 81 insertions(+), 68 deletions(-) diff --git a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala index 71f5a8ced..1aeee2c9e 100644 --- a/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/jdbc/Select.scala @@ -80,16 +80,16 @@ class Select: @Benchmark def prepareStatement: List[BenchmarkType] = - connection - .use { conn => - for - statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") - _ <- statement.setInt(1, len) - resultSet <- statement.executeQuery() - records <- consume(resultSet) - yield records - } - .unsafeRunSync() + connection + .use { conn => + for + statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") + _ <- statement.setInt(1, len) + resultSet <- statement.executeQuery() + records <- consume(resultSet) + yield records + } + .unsafeRunSync() private def consume(resultSet: ResultSet[IO]): IO[List[BenchmarkType]] = def loop(acc: Vector[BenchmarkType]): IO[Vector[BenchmarkType]] = diff --git a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala index bf5c623e5..bcfdfacf9 100644 --- a/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/connector/ldbc/Select.scala @@ -74,23 +74,23 @@ class Select: for statement <- conn.createStatement() resultSet <- statement.executeQuery(s"SELECT * FROM jdbc_statement_test LIMIT $len") - records <- consume(resultSet) + records <- consume(resultSet) yield records } .unsafeRunSync() @Benchmark def prepareStatement: List[BenchmarkType] = - connection - .use { conn => - for - statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") - _ <- statement.setInt(1, len) - resultSet <- statement.executeQuery() - records <- consume(resultSet) - yield records - } - .unsafeRunSync() + connection + .use { conn => + for + statement <- conn.prepareStatement("SELECT * FROM jdbc_prepare_statement_test LIMIT ?") + _ <- statement.setInt(1, len) + resultSet <- statement.executeQuery() + records <- consume(resultSet) + yield records + } + .unsafeRunSync() private def consume(resultSet: ResultSet[IO]): IO[List[BenchmarkType]] = def loop(acc: Vector[BenchmarkType]): IO[Vector[BenchmarkType]] = diff --git a/benchmark/src/main/scala/benchmark/wrapper/doobie/Insert.scala b/benchmark/src/main/scala/benchmark/wrapper/doobie/Insert.scala index bc0b82422..f9d112661 100644 --- a/benchmark/src/main/scala/benchmark/wrapper/doobie/Insert.scala +++ b/benchmark/src/main/scala/benchmark/wrapper/doobie/Insert.scala @@ -52,16 +52,20 @@ class Insert: @Benchmark def insertN: Unit = - transactor.use { xa => - (sql"INSERT INTO test (c1, c2)" ++ values(records)).update.run - .transact(xa) - }.unsafeRunSync() + transactor + .use { xa => + (sql"INSERT INTO test (c1, c2)" ++ values(records)).update.run + .transact(xa) + } + .unsafeRunSync() @Benchmark def batchN: Unit = - transactor.use { xa => - val sql = "INSERT INTO test (c1, c2) VALUES (?, ?)" - Update[(Int, String)](sql) - .updateMany(records) - .transact(xa) - }.unsafeRunSync() + transactor + .use { xa => + val sql = "INSERT INTO test (c1, c2) VALUES (?, ?)" + Update[(Int, String)](sql) + .updateMany(records) + .transact(xa) + } + .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/wrapper/doobie/Select.scala b/benchmark/src/main/scala/benchmark/wrapper/doobie/Select.scala index 8d146a3de..21d519aec 100644 --- a/benchmark/src/main/scala/benchmark/wrapper/doobie/Select.scala +++ b/benchmark/src/main/scala/benchmark/wrapper/doobie/Select.scala @@ -44,9 +44,11 @@ class Select: @Benchmark def selectN: List[(Int, String, String)] = - transactor.use { xa => - sql"SELECT ID, Name, CountryCode FROM city LIMIT $len" - .query[(Int, String, String)] - .to[List] - .transact(xa) - }.unsafeRunSync() + transactor + .use { xa => + sql"SELECT ID, Name, CountryCode FROM city LIMIT $len" + .query[(Int, String, String)] + .to[List] + .transact(xa) + } + .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/wrapper/ldbc/Insert.scala b/benchmark/src/main/scala/benchmark/wrapper/ldbc/Insert.scala index e6ca49715..f73d5c53c 100644 --- a/benchmark/src/main/scala/benchmark/wrapper/ldbc/Insert.scala +++ b/benchmark/src/main/scala/benchmark/wrapper/ldbc/Insert.scala @@ -49,7 +49,7 @@ class Insert: val datasource = jdbc.connector.MysqlDataSource[IO](ds) connection = Resource.make(datasource.getConnection)(_.close()) - + records = (1 to len).map(num => (num, s"record$num")).toList query = Table[Test] @@ -59,20 +59,23 @@ class Insert: @Benchmark def queryInsertN: Unit = - connection.use { conn => - query - .insertInto(test => (test.c1, test.c2)) - .values(records) - .update - .commit(conn) - }.unsafeRunSync() + connection + .use { conn => + query + .insertInto(test => (test.c1, test.c2)) + .values(records) + .update + .commit(conn) + } + .unsafeRunSync() @Benchmark def dslInsertN: Unit = - connection.use { conn => - (sql"INSERT INTO test (c1, c2)" ++ values(NonEmptyList.fromListUnsafe(records))) - .update - .commit(conn) - }.unsafeRunSync() + connection + .use { conn => + (sql"INSERT INTO test (c1, c2)" ++ values(NonEmptyList.fromListUnsafe(records))).update + .commit(conn) + } + .unsafeRunSync() case class Test(id: Option[Int], c1: Int, c2: String) derives Table diff --git a/benchmark/src/main/scala/benchmark/wrapper/ldbc/Select.scala b/benchmark/src/main/scala/benchmark/wrapper/ldbc/Select.scala index 5bbabc94d..b8eaa28b9 100644 --- a/benchmark/src/main/scala/benchmark/wrapper/ldbc/Select.scala +++ b/benchmark/src/main/scala/benchmark/wrapper/ldbc/Select.scala @@ -54,20 +54,24 @@ class Select: @Benchmark def querySelectN: List[(Int, String, String)] = - connection.use { conn => - query - .select(city => (city.id, city.name, city.countryCode)) - .limit(len) - .query - .to[List] - .readOnly(conn) - }.unsafeRunSync() + connection + .use { conn => + query + .select(city => (city.id, city.name, city.countryCode)) + .limit(len) + .query + .to[List] + .readOnly(conn) + } + .unsafeRunSync() @Benchmark def dslSelectN: List[(Int, String, String)] = - connection.use { conn => - sql"SELECT ID, Name, CountryCode FROM city LIMIT $len" - .query[(Int, String, String)] - .to[List] - .readOnly(conn) - }.unsafeRunSync() + connection + .use { conn => + sql"SELECT ID, Name, CountryCode FROM city LIMIT $len" + .query[(Int, String, String)] + .to[List] + .readOnly(conn) + } + .unsafeRunSync() diff --git a/benchmark/src/main/scala/benchmark/wrapper/slick/Insert.scala b/benchmark/src/main/scala/benchmark/wrapper/slick/Insert.scala index 79fccf4f7..1812c080c 100644 --- a/benchmark/src/main/scala/benchmark/wrapper/slick/Insert.scala +++ b/benchmark/src/main/scala/benchmark/wrapper/slick/Insert.scala @@ -63,10 +63,10 @@ class Insert: @Benchmark def batchN: Unit = - Await.result( - db.run(query ++= records), - Duration.Inf - ) + Await.result( + db.run(query ++= records), + Duration.Inf + ) case class Test(id: Option[Int], c1: Int, c2: String) class TestTable(tag: Tag) extends Table[Test](tag, "test"):