From 44906f889bc15b011250c08153c690b18b5b0d74 Mon Sep 17 00:00:00 2001 From: "Lukas Rieger (Blue)" Date: Tue, 9 Aug 2022 22:35:21 +0200 Subject: [PATCH] Small performance improvements (resolving world-ids and sql-querys) --- .../bluemap/common/BlueMapService.java | 42 +++++++++------ .../bluemap/core/storage/sql/SQLStorage.java | 51 ++++++++++--------- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java index 72b26bb6..8442350b 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java @@ -49,6 +49,7 @@ import de.bluecolored.bluemap.core.world.World; import org.apache.commons.io.FileUtils; import org.spongepowered.configurate.ConfigurateException; +import org.spongepowered.configurate.ConfigurationNode; import org.spongepowered.configurate.gson.GsonConfigurationLoader; import org.spongepowered.configurate.loader.HeaderMode; @@ -59,6 +60,7 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; /** @@ -81,13 +83,13 @@ public BlueMapService(ServerInterface serverInterface, BlueMapConfigProvider con this.serverInterface = serverInterface; this.configs = configProvider; - this.worldIds = new HashMap<>(); + this.worldIds = new ConcurrentHashMap<>(); this.storages = new HashMap<>(); StateDumper.global().register(this); } - public synchronized String getWorldId(Path worldFolder) throws IOException { + public String getWorldId(Path worldFolder) throws IOException { // fast-path String id = worldIds.get(worldFolder); if (id != null) return id; @@ -102,22 +104,29 @@ public synchronized String getWorldId(Path worldFolder) throws IOException { id = worldIds.get(worldFolder); if (id != null) return id; - // now we can be sure it wasn't loaded yet .. load + synchronized (this) { + // check again if another thread has already added the world + id = worldIds.get(worldFolder); + if (id != null) return id; - Path idFile = worldFolder.resolve("bluemap.id"); - if (!Files.exists(idFile)) { - id = this.serverInterface.getWorld(worldFolder) - .flatMap(ServerWorld::getId) - .orElse(UUID.randomUUID().toString()); - Files.writeString(idFile, id, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + Logger.global.logDebug("Loading world id for '" + worldFolder + "'..."); + // now we can be sure it wasn't loaded yet .. load + Path idFile = worldFolder.resolve("bluemap.id"); + if (!Files.exists(idFile)) { + id = this.serverInterface.getWorld(worldFolder) + .flatMap(ServerWorld::getId) + .orElse(UUID.randomUUID().toString()); + Files.writeString(idFile, id, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + + worldIds.put(worldFolder, id); + return id; + } + + id = Files.readString(idFile); worldIds.put(worldFolder, id); return id; } - - id = Files.readString(idFile); - worldIds.put(worldFolder, id); - return id; } public synchronized void createOrUpdateWebApp(boolean force) throws ConfigurationException { @@ -217,12 +226,13 @@ private synchronized void loadWorldsAndMaps() throws ConfigurationException, Int maps.put(id, map); // load marker-config by converting it first from hocon to json and then loading it with MarkerGson - if (!mapConfig.getMarkerSets().empty()) { + ConfigurationNode markerSetNode = mapConfig.getMarkerSets(); + if (markerSetNode != null && !markerSetNode.empty()) { String markerJson = GsonConfigurationLoader.builder() .headerMode(HeaderMode.NONE) .lenient(false) .indent(0) - .buildAndSaveString(mapConfig.getMarkerSets()); + .buildAndSaveString(markerSetNode); Gson gson = MarkerGson.addAdapters(new GsonBuilder()) .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) .create(); @@ -257,6 +267,8 @@ public synchronized Storage getStorage(String storageId) throws ConfigurationExc "You will either need to define that storage, or change the map-config to use a storage-config that exists."); } + Logger.global.logInfo("Initializing Storage: '" + storageId + "' (Type: " + storageConfig.getStorageType() + ")"); + storage = storageConfig.createStorage(); storage.initialize(); } catch (Exception ex) { diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/storage/sql/SQLStorage.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/storage/sql/SQLStorage.java index 1bcf6ee9..2da28b47 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/storage/sql/SQLStorage.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/storage/sql/SQLStorage.java @@ -538,34 +538,28 @@ private void recoveringConnection(ConnectionConsumer action, int tries) throws S @SuppressWarnings("SameParameterValue") private R recoveringConnection(ConnectionFunction action, int tries) throws SQLException, IOException { SQLException sqlException = null; - for (int i = 0; i < tries; i++) { - try (Connection connection = dataSource.getConnection()) { - connection.setAutoCommit(false); - R result; - try { - result = action.apply(connection); - connection.commit(); - } catch (SQLRecoverableException ex) { - connection.rollback(); - if (sqlException == null) { - sqlException = ex; - } else { - sqlException.addSuppressed(ex); + try { + for (int i = 0; i < tries; i++) { + try (Connection connection = dataSource.getConnection()) { + R result; + try { + result = action.apply(connection); + connection.commit(); + return result; + } catch (SQLRecoverableException ex) { + if (sqlException == null) { + sqlException = ex; + } else { + sqlException.addSuppressed(ex); + } } - continue; - } catch (SQLException | RuntimeException ex) { - connection.rollback(); - throw ex; } - - connection.setAutoCommit(true); - return result; - } catch (SQLException | IOException | RuntimeException ex) { - if (sqlException != null) - ex.addSuppressed(sqlException); - throw ex; } + } catch (SQLException | IOException | RuntimeException ex) { + if (sqlException != null) + ex.addSuppressed(sqlException); + throw ex; } assert sqlException != null; // should never be null if we end up here @@ -680,9 +674,16 @@ private DataSource createDataSource(String dbUrl, String user, String password, private DataSource createDataSource(ConnectionFactory connectionFactory) { PoolableConnectionFactory poolableConnectionFactory = - new PoolableConnectionFactory(connectionFactory, null); + new PoolableConnectionFactory(() -> { + Logger.global.logDebug("Creating new SQL-Connection..."); + return connectionFactory.createConnection(); + }, null); poolableConnectionFactory.setPoolStatements(true); poolableConnectionFactory.setMaxOpenPreparedStatements(20); + poolableConnectionFactory.setDefaultAutoCommit(false); + poolableConnectionFactory.setAutoCommitOnReturn(false); + poolableConnectionFactory.setRollbackOnReturn(true); + poolableConnectionFactory.setFastFailValidation(true); GenericObjectPoolConfig objectPoolConfig = new GenericObjectPoolConfig<>(); objectPoolConfig.setMinIdle(1);