mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-12-25 01:57:53 +01:00
Merge pull request #4011 from stormboomer/Stormboomer-Performance-MySQL-Storage
Drasticly improve zoom tile calculation for larger maps when using MySQL/MariaDB storage Engine
This commit is contained in:
commit
ebb9dc00d0
@ -809,14 +809,10 @@ public class MySQLMapStorage extends MapStorage {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
c = getConnection();
|
c = getConnection();
|
||||||
boolean done = false;
|
Statement stmt = c.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, //we want to stream our resultset one row at a time, we are not interessted in going back
|
||||||
int limit = 100;
|
java.sql.ResultSet.CONCUR_READ_ONLY); //since we do not handle the entire resultset in memory -> tell the statement that we are going to work read only
|
||||||
int offset = 0;
|
stmt.setFetchSize(100); //we can change the jdbc "retrieval chunk size". Basicly we limit how much rows are kept in memory. Bigger value = less network calls to DB, but more memory consumption
|
||||||
while (!done) {
|
ResultSet rs = stmt.executeQuery(String.format("SELECT x,y,zoom,Format FROM %s WHERE MapID=%d;", tableTiles, mapkey)); //we do the query, but do not set any limit / offset. Since data is not kept in memory, just streamed from DB this should not be a problem, only the rows from setFetchSize are kept in memory.
|
||||||
// Query tiles for given mapkey
|
|
||||||
Statement stmt = c.createStatement();
|
|
||||||
ResultSet rs = stmt.executeQuery(String.format("SELECT x,y,zoom,Format FROM %s WHERE MapID=%d LIMIT %d OFFSET %d;", tableTiles, mapkey, limit, offset));
|
|
||||||
int cnt = 0;
|
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
|
StorageTile st = new StorageTile(world, map, rs.getInt("x"), rs.getInt("y"), rs.getInt("zoom"), var);
|
||||||
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
final MapType.ImageEncoding encoding = MapType.ImageEncoding.fromOrd(rs.getInt("Format"));
|
||||||
@ -825,13 +821,9 @@ public class MySQLMapStorage extends MapStorage {
|
|||||||
if(cbBase != null && st.zoom == 0)
|
if(cbBase != null && st.zoom == 0)
|
||||||
cbBase.tileFound(st, encoding);
|
cbBase.tileFound(st, encoding);
|
||||||
st.cleanup();
|
st.cleanup();
|
||||||
cnt++;
|
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
stmt.close();
|
stmt.close();
|
||||||
if (cnt < limit) done = true;
|
|
||||||
offset += cnt;
|
|
||||||
}
|
|
||||||
if(cbEnd != null)
|
if(cbEnd != null)
|
||||||
cbEnd.searchEnded();
|
cbEnd.searchEnded();
|
||||||
} catch (SQLException x) {
|
} catch (SQLException x) {
|
||||||
|
@ -107,9 +107,15 @@ public class ImageIOManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static BufferOutputStream imageIOEncode(BufferedImage img, ImageFormat fmt) {
|
public static BufferOutputStream imageIOEncode(BufferedImage img, ImageFormat fmt) {
|
||||||
BufferOutputStream bos = new BufferOutputStream();
|
if(isRequiredJDKVersion(17,-1,-1)){
|
||||||
|
return imageIOEncodeUnsafe(img, fmt); //we can skip Thread safety for more performance
|
||||||
|
}
|
||||||
synchronized(imageioLock) {
|
synchronized(imageioLock) {
|
||||||
|
return imageIOEncodeUnsafe(img, fmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static BufferOutputStream imageIOEncodeUnsafe(BufferedImage img, ImageFormat fmt) {
|
||||||
|
BufferOutputStream bos = new BufferOutputStream();
|
||||||
try {
|
try {
|
||||||
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
||||||
|
|
||||||
@ -158,17 +164,69 @@ public class ImageIOManager {
|
|||||||
Log.info("Error encoding image - " + iox.getMessage());
|
Log.info("Error encoding image - " + iox.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return bos;
|
return bos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BufferedImage imageIODecode(MapStorageTile.TileRead tr) throws IOException {
|
public static BufferedImage imageIODecode(MapStorageTile.TileRead tr) throws IOException {
|
||||||
|
if(isRequiredJDKVersion(17,-1,-1)){
|
||||||
|
return imageIODecodeUnsafe(tr); //we can skip Thread safety for more performance
|
||||||
|
}
|
||||||
synchronized(imageioLock) {
|
synchronized(imageioLock) {
|
||||||
|
return imageIODecodeUnsafe(tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BufferedImage imageIODecodeUnsafe(MapStorageTile.TileRead tr) throws IOException {
|
||||||
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
||||||
if (tr.format == ImageEncoding.WEBP) {
|
if (tr.format == ImageEncoding.WEBP) {
|
||||||
return doWEBPDecode(tr.image);
|
return doWEBPDecode(tr.image);
|
||||||
}
|
}
|
||||||
return ImageIO.read(tr.image);
|
return ImageIO.read(tr.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current JDK is running at least a specific version
|
||||||
|
* targetMinor and targetBuild can be set to -1, if the java.version only provides a Major release this will then only check for the major release
|
||||||
|
* @param targetMajor the required minimum major version
|
||||||
|
* @param targetMinor the required minimum minor version
|
||||||
|
* @param targetBuild the required minimum build version
|
||||||
|
* @return true if the current JDK version is the required minimum version
|
||||||
|
*/
|
||||||
|
private static boolean isRequiredJDKVersion(int targetMajor, int targetMinor, int targetBuild){
|
||||||
|
String javaVersion = System.getProperty("java.version");
|
||||||
|
String[] versionParts = javaVersion.split("\\.");
|
||||||
|
if(versionParts.length < 3){
|
||||||
|
if(versionParts.length == 1
|
||||||
|
&& targetMinor == -1
|
||||||
|
&& targetBuild == -1
|
||||||
|
&& parseInt(versionParts[0], -1) >= targetMajor){
|
||||||
|
return true;//we only have a major version and thats ok
|
||||||
|
}
|
||||||
|
return false; //can not evaluate
|
||||||
|
}
|
||||||
|
int major = parseInt(versionParts[0], -1);
|
||||||
|
int minor = parseInt(versionParts[1], -1);
|
||||||
|
int build = parseInt(versionParts[2], -1);
|
||||||
|
if(major != -1 && major >= targetMajor &&
|
||||||
|
minor != -1 && minor >= targetMinor &&
|
||||||
|
build != -1 && build >= targetBuild
|
||||||
|
){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a string to int, with a dynamic fallback value if not parsable
|
||||||
|
* @param input the String to parse
|
||||||
|
* @param fallback the Fallback value to use
|
||||||
|
* @return the parsed integer or the fallback value if unparsable
|
||||||
|
*/
|
||||||
|
private static int parseInt(String input, int fallback){
|
||||||
|
int output = fallback;
|
||||||
|
try{
|
||||||
|
output = Integer.parseInt(input);
|
||||||
|
} catch (NumberFormatException e) {}
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ eclipse {
|
|||||||
name = "Dynmap(DynmapCoreAPI)"
|
name = "Dynmap(DynmapCoreAPI)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
|
||||||
|
|
||||||
description = "DynmapCoreAPI"
|
description = "DynmapCoreAPI"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user