This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 33ba50162ff HDDS-15268. Speed up 
TestUnhealthyContainersDerbyPerformance (a bit) (#10492)
33ba50162ff is described below

commit 33ba50162ff4f96e6879c153461a1016bb88ffed
Author: Arafat2198 <[email protected]>
AuthorDate: Sun Jun 14 21:27:37 2026 +0530

    HDDS-15268. Speed up TestUnhealthyContainersDerbyPerformance (a bit) 
(#10492)
    
    Co-authored-by: Cursor <[email protected]>
---
 .../recon/persistence/DerbyDataSourceProvider.java |   3 +-
 .../TestUnhealthyContainersDerbyPerformance.java   | 123 +++++++++++++++------
 2 files changed, 94 insertions(+), 32 deletions(-)

diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/persistence/DerbyDataSourceProvider.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/persistence/DerbyDataSourceProvider.java
index adafe200086..e0b413df517 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/persistence/DerbyDataSourceProvider.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/persistence/DerbyDataSourceProvider.java
@@ -51,7 +51,8 @@ public DataSource get() {
       LOG.error("Error creating Recon Derby DB.", e);
     }
     EmbeddedDataSource dataSource = new EmbeddedDataSource();
-    dataSource.setDatabaseName(jdbcUrl.split(":")[2]);
+    String dbName = jdbcUrl.replaceFirst("^jdbc:derby:", "");
+    dataSource.setDatabaseName(dbName);
     dataSource.setUser(RECON_SCHEMA_NAME);
     return dataSource;
   }
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/persistence/TestUnhealthyContainersDerbyPerformance.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/persistence/TestUnhealthyContainersDerbyPerformance.java
index f4134c40219..66c6b271432 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/persistence/TestUnhealthyContainersDerbyPerformance.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/persistence/TestUnhealthyContainersDerbyPerformance.java
@@ -46,6 +46,7 @@
 import org.apache.ozone.recon.schema.ReconSchemaGenerationModule;
 import 
org.apache.ozone.recon.schema.generated.tables.daos.UnhealthyContainersDao;
 import org.jooq.DSLContext;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.MethodOrderer;
 import org.junit.jupiter.api.Order;
@@ -74,9 +75,9 @@
  *
  * <h2>Performance settings applied in this test</h2>
  * <ul>
- *   <li><b>Page cache</b>: {@code derby.storage.pageCacheSize = 20000}
- *       (~80 MB of 4-KB pages) keeps hot B-tree nodes in memory, reducing
- *       filesystem reads even with the file-based Derby driver.</li>
+ *   <li><b>In-memory database</b>: The test uses an in-memory Derby database
+ *       ({@code jdbc:derby:memory:...}) to eliminate disk I/O and fsync 
overhead
+ *       during the 1-million-row benchmark.</li>
  *   <li><b>JDBC fetch size</b>: set to {@value #READ_PAGE_SIZE} on each query
  *       so Derby pre-buffers a full page of rows per JDBC round-trip instead
  *       of the default 1-row-at-a-time fetch.</li>
@@ -184,8 +185,8 @@ public class TestUnhealthyContainersDerbyPerformance {
   private static final int READ_PAGE_SIZE = 5_000;
 
   // -----------------------------------------------------------------------
-  // Performance thresholds (CI-safe; expected run times are 5–10× faster
-  // than the original file-based Derby baseline after the optimisations)
+  // Performance thresholds (CI-safe; expected run times are significantly 
faster
+  // than the original file-based Derby baseline after switching to in-memory)
   // -----------------------------------------------------------------------
 
   /** Maximum acceptable time to insert all TOTAL_RECORDS into Derby. */
@@ -220,43 +221,89 @@ public class TestUnhealthyContainersDerbyPerformance {
   // One-time setup: create Derby schema + insert 1 M records
   // -----------------------------------------------------------------------
 
+  private String inMemoryDbName;
+
   /**
-   * Initialises the embedded Derby database and creates the Recon schema.
+   * Initialises the embedded in-memory Derby database and creates the Recon 
schema.
    * Data population is done in dedicated test methods.
    *
-   * <p>The {@code @TempDir} is injected as a <em>method parameter</em> rather
-   * than a class field.  With {@code @TestInstance(PER_CLASS)}, a field-level
-   * {@code @TempDir} is populated by JUnit's {@code TempDirExtension} in its
-   * own {@code beforeAll} callback, which may run <em>after</em> the user's
-   * {@code @BeforeAll} — leaving it null when needed here.  A method
-   * parameter is resolved by JUnit before the method body executes.</p>
-   *
-   * <h3>Performance settings applied here</h3>
-   * <ul>
-   *   <li><b>Page cache</b> ({@code derby.storage.pageCacheSize = 20000}):
-   *       ~80 MB of 4-KB B-tree pages resident in heap — covers the hot path
-   *       for index scans on a 1-M-row table even with the file-based
-   *       driver.</li>
-   * </ul>
+   * <p>Reuses {@link DerbyDataSourceConfigurationProvider} for all connection 
settings
+   * and overrides only {@code getJdbcUrl()} to use an in-memory Derby database
+   * ({@code jdbc:derby:memory:...}), eliminating disk I/O and fsync overhead 
across
+   * the benchmark's insert, replace, and delete transactions.</p>
    */
   @BeforeAll
   public void setUpDatabase(@TempDir Path tempDir) throws Exception {
+    inMemoryDbName = "reconPerf_" + java.util.UUID.randomUUID().toString();
     LOG.info("=== Derby Performance Benchmark — Setup ===");
     LOG.info("Dataset: {} states × {} container IDs = {} total records",
         TESTED_STATES.size(), CONTAINER_ID_RANGE, TOTAL_RECORDS);
 
-    // Derby engine property — must be set before the first connection.
-    //
-    // pageCacheSize: number of 4-KB pages Derby keeps in its buffer pool.
-    //   Default = 1,000 pages (4 MB) — far too small for a 1-M-row table.
-    //   20,000 pages = ~80 MB, enough to hold the full B-tree for both the
-    //   primary-key index and the composite (state, container_id) index.
-    System.setProperty("derby.storage.pageCacheSize", "20000");
-
-    // ----- Guice wiring (mirrors AbstractReconSqlDBTest) -----
     File configDir = Files.createDirectory(tempDir.resolve("Config")).toFile();
-    Provider<DataSourceConfiguration> configProvider =
-        new DerbyDataSourceConfigurationProvider(configDir);
+    DataSourceConfiguration base = new 
DerbyDataSourceConfigurationProvider(configDir).get();
+
+    // Reuse DerbyDataSourceConfigurationProvider settings but point to an 
in-memory DB.
+    Provider<DataSourceConfiguration> configProvider = () -> new 
DataSourceConfiguration() {
+      @Override
+      public String getDriverClass() {
+        return base.getDriverClass();
+      }
+
+      @Override
+      public String getJdbcUrl() {
+        return "jdbc:derby:memory:" + inMemoryDbName;
+      }
+
+      @Override
+      public String getUserName() {
+        return base.getUserName();
+      }
+
+      @Override
+      public String getPassword() {
+        return base.getPassword();
+      }
+
+      @Override
+      public boolean setAutoCommit() {
+        return base.setAutoCommit();
+      }
+
+      @Override
+      public long getConnectionTimeout() {
+        return base.getConnectionTimeout();
+      }
+
+      @Override
+      public String getSqlDialect() {
+        return base.getSqlDialect();
+      }
+
+      @Override
+      public Integer getMaxActiveConnections() {
+        return base.getMaxActiveConnections();
+      }
+
+      @Override
+      public long getMaxConnectionAge() {
+        return base.getMaxConnectionAge();
+      }
+
+      @Override
+      public long getMaxIdleConnectionAge() {
+        return base.getMaxIdleConnectionAge();
+      }
+
+      @Override
+      public String getConnectionTestStatement() {
+        return base.getConnectionTestStatement();
+      }
+
+      @Override
+      public long getIdleConnectionTestPeriod() {
+        return base.getIdleConnectionTestPeriod();
+      }
+    };
 
     Injector injector = Guice.createInjector(
         new JooqPersistenceModule(configProvider),
@@ -277,6 +324,20 @@ protected void configure() {
     schemaManager = new ContainerHealthSchemaManager(schemaDefinition, new 
OzoneConfiguration());
   }
 
+  @AfterAll
+  public void tearDownDatabase() {
+    if (inMemoryDbName != null) {
+      try (java.sql.Connection conn = java.sql.DriverManager.getConnection(
+          "jdbc:derby:memory:" + inMemoryDbName + ";drop=true")) {
+        conn.isValid(1);
+      } catch (java.sql.SQLException e) {
+        if (!"08006".equals(e.getSQLState())) {
+          LOG.warn("Unexpected SQLState while dropping in-memory Derby DB: 
{}", e.getSQLState(), e);
+        }
+      }
+    }
+  }
+
   // -----------------------------------------------------------------------
   // Test 1 — Batch INSERT performance for 1M records
   // -----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to