Small performance improvements (resolving world-ids and sql-querys)

This commit is contained in:
Lukas Rieger (Blue) 2022-08-09 22:35:21 +02:00
parent 057d25bd15
commit 44906f889b
No known key found for this signature in database
GPG Key ID: 2D09EC5ED2687FF2
2 changed files with 53 additions and 40 deletions

View File

@ -49,6 +49,7 @@
import de.bluecolored.bluemap.core.world.World; import de.bluecolored.bluemap.core.world.World;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.spongepowered.configurate.ConfigurateException; import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.gson.GsonConfigurationLoader; import org.spongepowered.configurate.gson.GsonConfigurationLoader;
import org.spongepowered.configurate.loader.HeaderMode; import org.spongepowered.configurate.loader.HeaderMode;
@ -59,6 +60,7 @@
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
@ -81,13 +83,13 @@ public BlueMapService(ServerInterface serverInterface, BlueMapConfigProvider con
this.serverInterface = serverInterface; this.serverInterface = serverInterface;
this.configs = configProvider; this.configs = configProvider;
this.worldIds = new HashMap<>(); this.worldIds = new ConcurrentHashMap<>();
this.storages = new HashMap<>(); this.storages = new HashMap<>();
StateDumper.global().register(this); StateDumper.global().register(this);
} }
public synchronized String getWorldId(Path worldFolder) throws IOException { public String getWorldId(Path worldFolder) throws IOException {
// fast-path // fast-path
String id = worldIds.get(worldFolder); String id = worldIds.get(worldFolder);
if (id != null) return id; if (id != null) return id;
@ -102,22 +104,29 @@ public synchronized String getWorldId(Path worldFolder) throws IOException {
id = worldIds.get(worldFolder); id = worldIds.get(worldFolder);
if (id != null) return id; 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"); Logger.global.logDebug("Loading world id for '" + worldFolder + "'...");
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);
// 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); worldIds.put(worldFolder, id);
return id; return id;
} }
id = Files.readString(idFile);
worldIds.put(worldFolder, id);
return id;
} }
public synchronized void createOrUpdateWebApp(boolean force) throws ConfigurationException { public synchronized void createOrUpdateWebApp(boolean force) throws ConfigurationException {
@ -217,12 +226,13 @@ private synchronized void loadWorldsAndMaps() throws ConfigurationException, Int
maps.put(id, map); maps.put(id, map);
// load marker-config by converting it first from hocon to json and then loading it with MarkerGson // 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() String markerJson = GsonConfigurationLoader.builder()
.headerMode(HeaderMode.NONE) .headerMode(HeaderMode.NONE)
.lenient(false) .lenient(false)
.indent(0) .indent(0)
.buildAndSaveString(mapConfig.getMarkerSets()); .buildAndSaveString(markerSetNode);
Gson gson = MarkerGson.addAdapters(new GsonBuilder()) Gson gson = MarkerGson.addAdapters(new GsonBuilder())
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES)
.create(); .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."); "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 = storageConfig.createStorage();
storage.initialize(); storage.initialize();
} catch (Exception ex) { } catch (Exception ex) {

View File

@ -538,34 +538,28 @@ private void recoveringConnection(ConnectionConsumer action, int tries) throws S
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private <R> R recoveringConnection(ConnectionFunction<R> action, int tries) throws SQLException, IOException { private <R> R recoveringConnection(ConnectionFunction<R> action, int tries) throws SQLException, IOException {
SQLException sqlException = null; SQLException sqlException = null;
for (int i = 0; i < tries; i++) {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
R result; try {
try { for (int i = 0; i < tries; i++) {
result = action.apply(connection); try (Connection connection = dataSource.getConnection()) {
connection.commit(); R result;
} catch (SQLRecoverableException ex) { try {
connection.rollback(); result = action.apply(connection);
if (sqlException == null) { connection.commit();
sqlException = ex; return result;
} else { } catch (SQLRecoverableException ex) {
sqlException.addSuppressed(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 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) { private DataSource createDataSource(ConnectionFactory connectionFactory) {
PoolableConnectionFactory poolableConnectionFactory = PoolableConnectionFactory poolableConnectionFactory =
new PoolableConnectionFactory(connectionFactory, null); new PoolableConnectionFactory(() -> {
Logger.global.logDebug("Creating new SQL-Connection...");
return connectionFactory.createConnection();
}, null);
poolableConnectionFactory.setPoolStatements(true); poolableConnectionFactory.setPoolStatements(true);
poolableConnectionFactory.setMaxOpenPreparedStatements(20); poolableConnectionFactory.setMaxOpenPreparedStatements(20);
poolableConnectionFactory.setDefaultAutoCommit(false);
poolableConnectionFactory.setAutoCommitOnReturn(false);
poolableConnectionFactory.setRollbackOnReturn(true);
poolableConnectionFactory.setFastFailValidation(true);
GenericObjectPoolConfig<PoolableConnection> objectPoolConfig = new GenericObjectPoolConfig<>(); GenericObjectPoolConfig<PoolableConnection> objectPoolConfig = new GenericObjectPoolConfig<>();
objectPoolConfig.setMinIdle(1); objectPoolConfig.setMinIdle(1);