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

bchapuis pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git


The following commit(s) were added to refs/heads/main by this push:
     new 3ad2fe3a Optimize vector tile export and log slow queries (#753)
3ad2fe3a is described below

commit 3ad2fe3a0d183204ffdc48b286039632fd09bd36
Author: Bertil Chapuis <[email protected]>
AuthorDate: Thu Aug 24 11:19:23 2023 +0200

    Optimize vector tile export and log slow queries (#753)
    
    * Simplify the TileStore interface
    
    * Cache the AST of the SQL queries
    
    * Log queries taking more than 10sec to execute
    
    * Remove boundaries at low zoom levels
    
    * Use simplified waterway
---
 .run/basemap-mbtiles.run.xml                       |  7 ++++-
 .../baremaps/benchmarks/MBTilesBenchmark.java      | 23 -----------------
 .../org/apache/baremaps/tilestore/TileStore.java   | 30 ----------------------
 .../baremaps/tilestore/mbtiles/MBTilesStore.java   | 21 ---------------
 .../baremaps/tilestore/postgres/PostgresQuery.java |  4 ++-
 .../tilestore/postgres/PostgresTileStore.java      | 10 +++++++-
 .../org/apache/baremaps/utils/PostgresUtils.java   | 13 +++++++---
 .../org/apache/baremaps/utils/SqliteUtils.java     |  5 ++--
 .../apache/baremaps/workflow/WorkflowContext.java  |  2 +-
 .../baremaps/workflow/tasks/ExportVectorTiles.java |  2 +-
 basemap/layers/boundary/tileset.js                 |  2 +-
 basemap/layers/waterway/tileset.js                 |  4 +--
 12 files changed, 34 insertions(+), 89 deletions(-)

diff --git a/.run/basemap-mbtiles.run.xml b/.run/basemap-mbtiles.run.xml
index 6a57530d..fd32451f 100644
--- a/.run/basemap-mbtiles.run.xml
+++ b/.run/basemap-mbtiles.run.xml
@@ -2,7 +2,7 @@
   <configuration default="false" name="basemap-mbtiles" type="Application" 
factoryName="Application">
     <option name="MAIN_CLASS_NAME" value="org.apache.baremaps.cli.Baremaps" />
     <module name="baremaps-cli" />
-    <option name="PROGRAM_PARAMETERS" value="map mbtiles --mbtiles 
$USER_HOME$/Datasets/Baremaps/tiles.mbtiles --tilejson tileset.js --style 
style.js" />
+    <option name="PROGRAM_PARAMETERS" value="map mbtiles --mbtiles 
tiles.mbtiles --tilejson tileset.js --style style.js" />
     <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/basemap" />
     <extension name="coverage">
       <pattern>
@@ -10,6 +10,11 @@
         <option name="ENABLED" value="true" />
       </pattern>
     </extension>
+    <extension 
name="software.aws.toolkits.jetbrains.core.execution.JavaAwsConnectionExtension">
+      <option name="credential" />
+      <option name="region" />
+      <option name="useCurrentConnection" value="false" />
+    </extension>
     <method v="2">
       <option name="Make" enabled="true" />
     </method>
diff --git 
a/baremaps-benchmark/src/main/java/org/apache/baremaps/benchmarks/MBTilesBenchmark.java
 
b/baremaps-benchmark/src/main/java/org/apache/baremaps/benchmarks/MBTilesBenchmark.java
index 8d170729..18435fb3 100644
--- 
a/baremaps-benchmark/src/main/java/org/apache/baremaps/benchmarks/MBTilesBenchmark.java
+++ 
b/baremaps-benchmark/src/main/java/org/apache/baremaps/benchmarks/MBTilesBenchmark.java
@@ -18,7 +18,6 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.security.SecureRandom;
-import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 import org.apache.baremaps.tilestore.TileCoord;
 import org.apache.baremaps.tilestore.TileStoreException;
@@ -66,28 +65,6 @@ public class MBTilesBenchmark {
     }
   }
 
-  @Benchmark
-  @BenchmarkMode(Mode.SingleShotTime)
-  public void writeMBTilesBatch(MBTilesBenchmark benchmark) throws 
TileStoreException {
-    var coords = new ArrayList<TileCoord>();
-    var buffers = new ArrayList<ByteBuffer>();
-    for (int i = 0; i < benchmark.iterations; i++) {
-      var bytes = new byte[1 << 16];
-      random.nextBytes(bytes);
-      coords.add(new TileCoord(0, 0, i));
-      buffers.add(ByteBuffer.wrap(bytes));
-      if (coords.size() == 100) {
-        random.nextBytes(bytes);
-        mbTilesStore.write(coords, buffers);
-        coords.clear();
-        buffers.clear();
-      }
-    }
-    mbTilesStore.write(coords, buffers);
-    coords.clear();
-    buffers.clear();
-  }
-
   public static void main(String[] args) throws RunnerException {
     Options opt =
         new 
OptionsBuilder().include(MBTilesBenchmark.class.getSimpleName()).forks(1).build();
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/TileStore.java 
b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/TileStore.java
index 926fe088..c7288383 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/TileStore.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/TileStore.java
@@ -15,8 +15,6 @@ package org.apache.baremaps.tilestore;
 
 
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
 
 /** Represents a store for tiles. */
 public interface TileStore {
@@ -30,21 +28,6 @@ public interface TileStore {
    */
   ByteBuffer read(TileCoord tileCoord) throws TileStoreException;
 
-  /**
-   * Reads the content of several tiles.
-   *
-   * @param tileCoords the tile coordinates
-   * @return the content of the tiles
-   * @throws TileStoreException
-   */
-  default List<ByteBuffer> read(List<TileCoord> tileCoords) throws 
TileStoreException {
-    var blobs = new ArrayList<ByteBuffer>(tileCoords.size());
-    for (var tileCoord : tileCoords) {
-      blobs.add(read(tileCoord));
-    }
-    return blobs;
-  }
-
   /**
    * Writes the content of a tile.
    *
@@ -54,19 +37,6 @@ public interface TileStore {
    */
   void write(TileCoord tileCoord, ByteBuffer blob) throws TileStoreException;
 
-  /**
-   * Writes the content of several tiles.
-   *
-   * @param tileCoords the tile coordinates
-   * @param blobs the content of the tiles
-   * @throws TileStoreException
-   */
-  default void write(List<TileCoord> tileCoords, List<ByteBuffer> blobs) 
throws TileStoreException {
-    for (int i = 0; i < tileCoords.size(); i++) {
-      write(tileCoords.get(i), blobs.get(i));
-    }
-  }
-
   /**
    * Deletes the content of a tile.
    *
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/mbtiles/MBTilesStore.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/mbtiles/MBTilesStore.java
index 847a2c9a..a5cb03e0 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/mbtiles/MBTilesStore.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/mbtiles/MBTilesStore.java
@@ -22,7 +22,6 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import javax.sql.DataSource;
 import org.apache.baremaps.tilestore.TileCoord;
@@ -106,26 +105,6 @@ public class MBTilesStore implements TileStore {
     }
   }
 
-  /** {@inheritDoc} */
-  @Override
-  public void write(List<TileCoord> tileCoords, List<ByteBuffer> blobs) throws 
TileStoreException {
-    try (Connection connection = dataSource.getConnection();
-        PreparedStatement statement = 
connection.prepareStatement(INSERT_TILE)) {
-      for (int i = 0; i < tileCoords.size(); i++) {
-        TileCoord tileCoord = tileCoords.get(i);
-        ByteBuffer blob = blobs.get(i);
-        statement.setInt(1, tileCoord.z());
-        statement.setInt(2, tileCoord.x());
-        statement.setInt(3, reverseY(tileCoord.y(), tileCoord.z()));
-        statement.setBytes(4, blob.array());
-        statement.addBatch();
-      }
-      statement.executeBatch();
-    } catch (SQLException e) {
-      throw new TileStoreException(e);
-    }
-  }
-
   /** {@inheritDoc} */
   @Override
   public void delete(TileCoord tileCoord) throws TileStoreException {
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/postgres/PostgresQuery.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/postgres/PostgresQuery.java
index 5047ace8..542ca854 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/postgres/PostgresQuery.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/postgres/PostgresQuery.java
@@ -29,6 +29,7 @@ public class PostgresQuery {
   private final Integer minzoom;
   private final Integer maxzoom;
   private final String sql;
+  private final PlainSelect ast;
 
   /**
    * Constructs a {@code PostgresQuery}.
@@ -43,6 +44,7 @@ public class PostgresQuery {
     this.minzoom = minzoom;
     this.maxzoom = maxzoom;
     this.sql = sql;
+    this.ast = parse(sql);
   }
 
   /**
@@ -87,7 +89,7 @@ public class PostgresQuery {
    * @return the AST
    */
   public PlainSelect getAst() {
-    return parse(sql);
+    return ast;
   }
 
   private PlainSelect parse(String query) {
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/postgres/PostgresTileStore.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/postgres/PostgresTileStore.java
index 8f531921..7b4f75fb 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/postgres/PostgresTileStore.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/postgres/PostgresTileStore.java
@@ -100,14 +100,15 @@ public class PostgresTileStore implements TileStore {
   /** {@inheritDoc} */
   @Override
   public ByteBuffer read(TileCoord tileCoord) throws TileStoreException {
+    String sql = withQuery(tileCoord);
     try (Connection connection = datasource.getConnection();
         Statement statement = connection.createStatement();
         ByteArrayOutputStream data = new ByteArrayOutputStream()) {
 
       int length = 0;
       if (queries.stream().anyMatch(query -> zoomPredicate(query, 
tileCoord.z()))) {
-        String sql = withQuery(tileCoord);
         logger.debug("Executing query: {}", sql);
+        long start = System.currentTimeMillis();
         try (GZIPOutputStream gzip = new GZIPOutputStream(data);
             ResultSet resultSet = statement.executeQuery(sql)) {
           while (resultSet.next()) {
@@ -116,6 +117,13 @@ public class PostgresTileStore implements TileStore {
             gzip.write(bytes);
           }
         }
+        long stop = System.currentTimeMillis();
+        long duration = stop - start;
+
+        // Log slow queries (> 10s)
+        if (duration > 10_000) {
+          logger.warn("Executed query for tile {} in {} ms: {}", tileCoord, 
duration, sql);
+        }
       }
 
       if (length > 0) {
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/utils/PostgresUtils.java 
b/baremaps-core/src/main/java/org/apache/baremaps/utils/PostgresUtils.java
index ab5cf6e3..e1768a15 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/utils/PostgresUtils.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/utils/PostgresUtils.java
@@ -23,13 +23,18 @@ import java.nio.charset.StandardCharsets;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Statement;
+import javax.sql.DataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** A helper class for creating data sources and executing queries. */
 public final class PostgresUtils {
 
+  private static final Logger logger = 
LoggerFactory.getLogger(PostgresUtils.class);
+
   private PostgresUtils() {}
 
-  public static HikariDataSource createDataSource(String host, Integer port, 
String database,
+  public static DataSource createDataSource(String host, Integer port, String 
database,
       String username, String password) {
     return createDataSource(
         String.format("jdbc:postgresql://%s:%s/%s?&user=%s&password=%s", host, 
port,
@@ -43,8 +48,8 @@ public final class PostgresUtils {
    * @param url the JDBC url
    * @return the data source
    */
-  public static HikariDataSource createDataSource(String url) {
-    return createDataSource(url, Runtime.getRuntime().availableProcessors());
+  public static DataSource createDataSource(String url) {
+    return createDataSource(url, Runtime.getRuntime().availableProcessors() * 
2);
   }
 
   /**
@@ -54,7 +59,7 @@ public final class PostgresUtils {
    * @param poolSize the pool size
    * @return the data source
    */
-  public static HikariDataSource createDataSource(String url, int poolSize) {
+  public static DataSource createDataSource(String url, int poolSize) {
     if (poolSize < 1) {
       throw new IllegalArgumentException("PoolSize cannot be inferior to 1");
     }
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/utils/SqliteUtils.java 
b/baremaps-core/src/main/java/org/apache/baremaps/utils/SqliteUtils.java
index 35e980ae..d2403146 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/utils/SqliteUtils.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/utils/SqliteUtils.java
@@ -25,6 +25,7 @@ import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.sql.Statement;
+import javax.sql.DataSource;
 import org.sqlite.SQLiteConfig;
 import org.sqlite.SQLiteConfig.JournalMode;
 import org.sqlite.SQLiteConfig.LockingMode;
@@ -43,7 +44,7 @@ public final class SqliteUtils {
    * @param path the path to the SQLite database
    * @return the SQLite data source
    */
-  public static HikariDataSource createDataSource(Path path, boolean readOnly) 
{
+  public static DataSource createDataSource(Path path, boolean readOnly) {
     var sqliteConfig = new SQLiteConfig();
     sqliteConfig.setReadOnly(readOnly);
     sqliteConfig.setCacheSize(1000000);
@@ -57,8 +58,6 @@ public final class SqliteUtils {
     sqliteDataSource.setConfig(sqliteConfig);
     sqliteDataSource.setUrl("jdbc:sqlite:" + path.toAbsolutePath());
 
-    System.out.println(path.toAbsolutePath());
-
     var hikariConfig = new HikariConfig();
     hikariConfig.setDataSource(sqliteDataSource);
     hikariConfig.setMaximumPoolSize(readOnly ? 
Runtime.getRuntime().availableProcessors() : 1);
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/workflow/WorkflowContext.java 
b/baremaps-core/src/main/java/org/apache/baremaps/workflow/WorkflowContext.java
index eff85f26..b03060ca 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/workflow/WorkflowContext.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/workflow/WorkflowContext.java
@@ -33,7 +33,7 @@ public class WorkflowContext {
    * @return the data source
    */
   public DataSource getDataSource(String database) {
-    return dataSources.computeIfAbsent(database, d -> 
PostgresUtils.createDataSource(d));
+    return dataSources.computeIfAbsent(database, 
PostgresUtils::createDataSource);
   }
 
 }
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/workflow/tasks/ExportVectorTiles.java
 
b/baremaps-core/src/main/java/org/apache/baremaps/workflow/tasks/ExportVectorTiles.java
index 07c2a9ae..5bced5a8 100644
--- 
a/baremaps-core/src/main/java/org/apache/baremaps/workflow/tasks/ExportVectorTiles.java
+++ 
b/baremaps-core/src/main/java/org/apache/baremaps/workflow/tasks/ExportVectorTiles.java
@@ -74,7 +74,7 @@ public record ExportVectorTiles(
         StreamUtils.stream(TileCoord.iterator(envelope, tileset.getMinzoom(), 
tileset.getMaxzoom()))
             .peek(new ProgressLogger<>(count, 5000));
 
-    StreamUtils.batch(stream, 10).forEach(new TileChannel(sourceTileStore, 
targetTileStore));
+    StreamUtils.batch(stream).forEach(new TileChannel(sourceTileStore, 
targetTileStore));
   }
 
   private TileStore sourceTileStore(Tileset tileset, DataSource datasource) {
diff --git a/basemap/layers/boundary/tileset.js 
b/basemap/layers/boundary/tileset.js
index 75525332..8529b222 100644
--- a/basemap/layers/boundary/tileset.js
+++ b/basemap/layers/boundary/tileset.js
@@ -13,7 +13,7 @@ export default {
     id: 'boundary',
     queries: [
         {
-            minzoom: 10,
+            minzoom: 13,
             maxzoom: 20,
             sql:
                 "SELECT id, tags, geom FROM osm_ways WHERE tags ? 'boundary'",
diff --git a/basemap/layers/waterway/tileset.js 
b/basemap/layers/waterway/tileset.js
index 177c4a37..81940686 100644
--- a/basemap/layers/waterway/tileset.js
+++ b/basemap/layers/waterway/tileset.js
@@ -19,11 +19,11 @@ export default {
         },
         {
             "minzoom": 10,
-            "maxzoom": 12,
+            "maxzoom": 13,
             "sql": "SELECT id, tags, geom FROM osm_waterway_z$zoom WHERE tags 
->> 'waterway' IN ('river', 'stream')"
         },
         {
-            "minzoom": 12,
+            "minzoom": 13,
             "maxzoom": 20,
             "sql": "SELECT id, tags, geom FROM osm_ways WHERE tags ? 
'waterway'"
         }

Reply via email to