mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-24 19:25:15 +01:00
Various performance and concurrency optimizations
This commit is contained in:
parent
fd887b47b4
commit
05aa0960f2
@ -2,6 +2,7 @@ package org.dynmap;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
@ -59,26 +60,34 @@ public class TileHashManager {
|
|||||||
}
|
}
|
||||||
/* Write to file */
|
/* Write to file */
|
||||||
public void writeToFile(File tiledir, byte[] crcbuf) {
|
public void writeToFile(File tiledir, byte[] crcbuf) {
|
||||||
|
RandomAccessFile fd = null;
|
||||||
try {
|
try {
|
||||||
RandomAccessFile fd = new RandomAccessFile(getHashFile(tiledir), "rw");
|
fd = new RandomAccessFile(getHashFile(tiledir), "rw");
|
||||||
fd.seek(0);
|
fd.seek(0);
|
||||||
fd.write(crcbuf);
|
fd.write(crcbuf);
|
||||||
fd.close();
|
|
||||||
} catch (IOException iox) {
|
} catch (IOException iox) {
|
||||||
Log.severe("Error writing hash file - " + getHashFile(tiledir).getPath());
|
Log.severe("Error writing hash file - " + getHashFile(tiledir).getPath());
|
||||||
|
} finally {
|
||||||
|
if(fd != null) {
|
||||||
|
try { fd.close(); } catch (IOException iox) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read from file */
|
/* Read from file */
|
||||||
public void readFromFile(File tiledir, byte[] crcbuf) {
|
public void readFromFile(File tiledir, byte[] crcbuf) {
|
||||||
|
RandomAccessFile fd = null;
|
||||||
try {
|
try {
|
||||||
RandomAccessFile fd = new RandomAccessFile(getHashFile(tiledir), "r");
|
fd = new RandomAccessFile(getHashFile(tiledir), "r");
|
||||||
fd.seek(0);
|
fd.seek(0);
|
||||||
fd.read(crcbuf);
|
fd.read(crcbuf);
|
||||||
fd.close();
|
|
||||||
} catch (IOException iox) {
|
} catch (IOException iox) {
|
||||||
Arrays.fill(crcbuf, (byte)0xFF);
|
Arrays.fill(crcbuf, (byte)0xFF);
|
||||||
writeToFile(tiledir, crcbuf);
|
writeToFile(tiledir, crcbuf);
|
||||||
|
} finally {
|
||||||
|
if(fd != null) {
|
||||||
|
try { fd.close(); } catch (IOException iox) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Read CRC */
|
/* Read CRC */
|
||||||
@ -100,8 +109,8 @@ public class TileHashManager {
|
|||||||
private static final int MAX_CACHED_TILEHASHFILES = 25;
|
private static final int MAX_CACHED_TILEHASHFILES = 25;
|
||||||
private Object lock = new Object();
|
private Object lock = new Object();
|
||||||
private LRULinkedHashMap<TileHashFile, byte[]> tilehash = new LRULinkedHashMap<TileHashFile, byte[]>(MAX_CACHED_TILEHASHFILES);
|
private LRULinkedHashMap<TileHashFile, byte[]> tilehash = new LRULinkedHashMap<TileHashFile, byte[]>(MAX_CACHED_TILEHASHFILES);
|
||||||
private CRC32 crc32 = new CRC32();
|
private LinkedList<byte[]> crcworkbufs = new LinkedList<byte[]>();
|
||||||
private byte[] crcworkbuf = new byte[8192];
|
private LinkedList<CRC32> crcs = new LinkedList<CRC32>();
|
||||||
|
|
||||||
public TileHashManager(File tileroot, boolean enabled) {
|
public TileHashManager(File tileroot, boolean enabled) {
|
||||||
tiledir = tileroot;
|
tiledir = tileroot;
|
||||||
@ -130,22 +139,41 @@ public class TileHashManager {
|
|||||||
if(!enabled) {
|
if(!enabled) {
|
||||||
return 0; /* Return value that doesn't match */
|
return 0; /* Return value that doesn't match */
|
||||||
}
|
}
|
||||||
|
CRC32 crc32;
|
||||||
|
byte[] crcworkbuf;
|
||||||
synchronized(lock) {
|
synchronized(lock) {
|
||||||
if(crcworkbuf.length < (4*newbuf.length)){
|
if(crcworkbufs.isEmpty()) {
|
||||||
crcworkbuf = new byte[4*newbuf.length];
|
crcworkbuf = new byte[4*newbuf.length];
|
||||||
}
|
}
|
||||||
for(int i = 0, off = 0; i < newbuf.length; i++) {
|
else {
|
||||||
int v = newbuf[i];
|
crcworkbuf = crcworkbufs.removeFirst();
|
||||||
crcworkbuf[off++] = (byte)v;
|
}
|
||||||
crcworkbuf[off++] = (byte)(v>>8);
|
if(crcs.isEmpty()) {
|
||||||
crcworkbuf[off++] = (byte)(v>>16);
|
crc32 = new CRC32();
|
||||||
crcworkbuf[off++] = (byte)(v>>24);
|
}
|
||||||
|
else {
|
||||||
|
crc32 = crcs.removeFirst();
|
||||||
|
crc32.reset();
|
||||||
}
|
}
|
||||||
/* Calculate CRC-32 for buffer */
|
|
||||||
crc32.reset();
|
|
||||||
crc32.update(crcworkbuf, 0, 4*newbuf.length);
|
|
||||||
return crc32.getValue();
|
|
||||||
}
|
}
|
||||||
|
if(crcworkbuf.length < (4*newbuf.length)){
|
||||||
|
crcworkbuf = new byte[4*newbuf.length];
|
||||||
|
}
|
||||||
|
for(int i = 0, off = 0; i < newbuf.length; i++) {
|
||||||
|
int v = newbuf[i];
|
||||||
|
crcworkbuf[off++] = (byte)v;
|
||||||
|
crcworkbuf[off++] = (byte)(v>>8);
|
||||||
|
crcworkbuf[off++] = (byte)(v>>16);
|
||||||
|
crcworkbuf[off++] = (byte)(v>>24);
|
||||||
|
}
|
||||||
|
/* Calculate CRC-32 for buffer */
|
||||||
|
crc32.update(crcworkbuf, 0, 4*newbuf.length);
|
||||||
|
long v = crc32.getValue();
|
||||||
|
synchronized(lock) {
|
||||||
|
crcworkbufs.addFirst(crcworkbuf);
|
||||||
|
crcs.addFirst(crc32);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
/* Update hashcode for given tile */
|
/* Update hashcode for given tile */
|
||||||
public void updateHashCode(String key, String subtype, int tx, int ty, long newcrc) {
|
public void updateHashCode(String key, String subtype, int tx, int ty, long newcrc) {
|
||||||
|
@ -21,8 +21,8 @@ public class DefaultHDLighting implements HDLighting {
|
|||||||
|
|
||||||
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
|
/* Apply lighting to given pixel colors (1 outcolor if normal, 2 if night/day) */
|
||||||
public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) {
|
public void applyLighting(HDPerspectiveState ps, HDShaderState ss, Color incolor, Color[] outcolor) {
|
||||||
for(Color oc: outcolor)
|
for(int i = 0; i < outcolor.length; i++)
|
||||||
oc.setColor(incolor);
|
outcolor[i].setColor(incolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test if Biome Data is needed for this renderer */
|
/* Test if Biome Data is needed for this renderer */
|
||||||
|
@ -117,8 +117,8 @@ public class DefaultHDShader implements HDShader {
|
|||||||
* Reset renderer state for new ray
|
* Reset renderer state for new ray
|
||||||
*/
|
*/
|
||||||
public void reset(HDPerspectiveState ps) {
|
public void reset(HDPerspectiveState ps) {
|
||||||
for(Color c: color)
|
for(int i = 0; i < color.length; i++)
|
||||||
c.setTransparent();
|
color[i].setTransparent();
|
||||||
pixelodd = (ps.getPixelX() & 0x3) + (ps.getPixelY()<<1);
|
pixelodd = (ps.getPixelX() & 0x3) + (ps.getPixelY()<<1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,8 +169,8 @@ public class DefaultHDShader implements HDShader {
|
|||||||
lighting.applyLighting(ps, this, c, tmpcolor);
|
lighting.applyLighting(ps, this, c, tmpcolor);
|
||||||
/* If we got alpha from subblock model, use it instead */
|
/* If we got alpha from subblock model, use it instead */
|
||||||
if(subalpha >= 0) {
|
if(subalpha >= 0) {
|
||||||
for(Color clr : tmpcolor)
|
for(int j = 0; j < tmpcolor.length; j++)
|
||||||
clr.setAlpha(Math.max(subalpha,clr.getAlpha()));
|
tmpcolor[j].setAlpha(Math.max(subalpha,tmpcolor[j].getAlpha()));
|
||||||
}
|
}
|
||||||
/* Blend color with accumulated color (weighted by alpha) */
|
/* Blend color with accumulated color (weighted by alpha) */
|
||||||
if(!transparency) { /* No transparency support */
|
if(!transparency) { /* No transparency support */
|
||||||
|
@ -145,7 +145,8 @@ public class IsoHDPerspective implements HDPerspective {
|
|||||||
BlockStep [] steps = { BlockStep.Y_PLUS, BlockStep.X_MINUS, BlockStep.X_PLUS,
|
BlockStep [] steps = { BlockStep.Y_PLUS, BlockStep.X_MINUS, BlockStep.X_PLUS,
|
||||||
BlockStep.Z_MINUS, BlockStep.Z_PLUS };
|
BlockStep.Z_MINUS, BlockStep.Z_PLUS };
|
||||||
emitlevel = skylevel = 0;
|
emitlevel = skylevel = 0;
|
||||||
for(BlockStep s : steps) {
|
for(int i = 0; i < steps.length; i++) {
|
||||||
|
BlockStep s = steps[i];
|
||||||
mapiter.stepPosition(s);
|
mapiter.stepPosition(s);
|
||||||
int v = mapiter.getBlockEmittedLight();
|
int v = mapiter.getBlockEmittedLight();
|
||||||
if(v > emitlevel) emitlevel = v;
|
if(v > emitlevel) emitlevel = v;
|
||||||
@ -448,7 +449,8 @@ public class IsoHDPerspective implements HDPerspective {
|
|||||||
mapiter.getBlockTypeIDAt(BlockStep.X_MINUS) }; /* To north */
|
mapiter.getBlockTypeIDAt(BlockStep.X_MINUS) }; /* To north */
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < 4; i++)
|
||||||
if(ids[i] == REDSTONE_BLKTYPEID) flags |= (1<<i);
|
if(ids[i] == REDSTONE_BLKTYPEID)
|
||||||
|
flags |= (1<<i);
|
||||||
switch(flags) {
|
switch(flags) {
|
||||||
case 0: /* Nothing nearby */
|
case 0: /* Nothing nearby */
|
||||||
case 15: /* NSEW */
|
case 15: /* NSEW */
|
||||||
@ -517,8 +519,8 @@ public class IsoHDPerspective implements HDPerspective {
|
|||||||
return blockdata;
|
return blockdata;
|
||||||
}
|
}
|
||||||
private final boolean containsID(int id, int[] linkids) {
|
private final boolean containsID(int id, int[] linkids) {
|
||||||
for(int lid: linkids)
|
for(int i = 0; i < linkids.length; i++)
|
||||||
if(id == lid)
|
if(id == linkids[i])
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -640,16 +642,8 @@ public class IsoHDPerspective implements HDPerspective {
|
|||||||
if(visit_block(mapiter, shaderstate, shaderdone)) {
|
if(visit_block(mapiter, shaderstate, shaderdone)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* If X step is next best */
|
|
||||||
if((t_next_x <= t_next_y) && (t_next_x <= t_next_z)) {
|
|
||||||
x += x_inc;
|
|
||||||
t = t_next_x;
|
|
||||||
t_next_x += dt_dx;
|
|
||||||
laststep = stepx;
|
|
||||||
mapiter.stepPosition(laststep);
|
|
||||||
}
|
|
||||||
/* If Y step is next best */
|
/* If Y step is next best */
|
||||||
else if((t_next_y <= t_next_x) && (t_next_y <= t_next_z)) {
|
if((t_next_y <= t_next_x) && (t_next_y <= t_next_z)) {
|
||||||
y += y_inc;
|
y += y_inc;
|
||||||
t = t_next_y;
|
t = t_next_y;
|
||||||
t_next_y += dt_dy;
|
t_next_y += dt_dy;
|
||||||
@ -658,6 +652,14 @@ public class IsoHDPerspective implements HDPerspective {
|
|||||||
/* If outside 0-127 range */
|
/* If outside 0-127 range */
|
||||||
if((y & (~0x7F)) != 0) return;
|
if((y & (~0x7F)) != 0) return;
|
||||||
}
|
}
|
||||||
|
/* If X step is next best */
|
||||||
|
else if((t_next_x <= t_next_y) && (t_next_x <= t_next_z)) {
|
||||||
|
x += x_inc;
|
||||||
|
t = t_next_x;
|
||||||
|
t_next_x += dt_dx;
|
||||||
|
laststep = stepx;
|
||||||
|
mapiter.stepPosition(laststep);
|
||||||
|
}
|
||||||
/* Else, Z step is next best */
|
/* Else, Z step is next best */
|
||||||
else {
|
else {
|
||||||
z += z_inc;
|
z += z_inc;
|
||||||
|
@ -123,8 +123,8 @@ public class TexturePackHDShader implements HDShader {
|
|||||||
* Reset renderer state for new ray
|
* Reset renderer state for new ray
|
||||||
*/
|
*/
|
||||||
public void reset(HDPerspectiveState ps) {
|
public void reset(HDPerspectiveState ps) {
|
||||||
for(Color c: color)
|
for(int i = 0; i < color.length; i++)
|
||||||
c.setTransparent();
|
color[i].setTransparent();
|
||||||
lastblkid = 0;
|
lastblkid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import java.io.File;
|
|||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.DirectColorModel;
|
import java.awt.image.DirectColorModel;
|
||||||
import java.awt.image.WritableRaster;
|
import java.awt.image.WritableRaster;
|
||||||
@ -141,7 +142,7 @@ public class FileLockManager {
|
|||||||
}
|
}
|
||||||
private static final int MAX_WRITE_RETRIES = 6;
|
private static final int MAX_WRITE_RETRIES = 6;
|
||||||
|
|
||||||
private static ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
private static LinkedList<ByteArrayOutputStream> baoslist = new LinkedList<ByteArrayOutputStream>();
|
||||||
private static Object baos_lock = new Object();
|
private static Object baos_lock = new Object();
|
||||||
/**
|
/**
|
||||||
* Wrapper for IOImage.write - implements retries for busy files
|
* Wrapper for IOImage.write - implements retries for busy files
|
||||||
@ -150,45 +151,55 @@ public class FileLockManager {
|
|||||||
int retrycnt = 0;
|
int retrycnt = 0;
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
byte[] rslt;
|
byte[] rslt;
|
||||||
|
ByteArrayOutputStream baos;
|
||||||
synchronized(baos_lock) {
|
synchronized(baos_lock) {
|
||||||
baos.reset();
|
if(baoslist.isEmpty()) {
|
||||||
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
baos = new ByteArrayOutputStream();
|
||||||
if(fmt.getFileExt().equals("jpg")) {
|
|
||||||
WritableRaster raster = img.getRaster();
|
|
||||||
WritableRaster newRaster = raster.createWritableChild(0, 0, img.getWidth(),
|
|
||||||
img.getHeight(), 0, 0, new int[] {0, 1, 2});
|
|
||||||
DirectColorModel cm = (DirectColorModel)img.getColorModel();
|
|
||||||
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
|
|
||||||
cm.getRedMask(), cm.getGreenMask(), cm.getBlueMask());
|
|
||||||
// now create the new buffer that is used ot write the image:
|
|
||||||
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
|
|
||||||
|
|
||||||
// Find a jpeg writer
|
|
||||||
ImageWriter writer = null;
|
|
||||||
Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
|
|
||||||
if (iter.hasNext()) {
|
|
||||||
writer = (ImageWriter)iter.next();
|
|
||||||
}
|
|
||||||
if(writer == null) {
|
|
||||||
Log.severe("No JPEG ENCODER - Java VM does not support JPEG encoding");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ImageWriteParam iwp = writer.getDefaultWriteParam();
|
|
||||||
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
|
||||||
iwp.setCompressionQuality(fmt.getQuality());
|
|
||||||
|
|
||||||
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
|
|
||||||
writer.setOutput(ios);
|
|
||||||
|
|
||||||
writer.write(null, new IIOImage(rgbBuffer, null, null), iwp);
|
|
||||||
writer.dispose();
|
|
||||||
|
|
||||||
rgbBuffer.flush();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ImageIO.write(img, fmt.getFileExt(), baos); /* Write to byte array stream - prevent bogus I/O errors */
|
baos = baoslist.removeFirst();
|
||||||
|
baos.reset();
|
||||||
}
|
}
|
||||||
rslt = baos.toByteArray();
|
}
|
||||||
|
ImageIO.setUseCache(false); /* Don't use file cache - too small to be worth it */
|
||||||
|
if(fmt.getFileExt().equals("jpg")) {
|
||||||
|
WritableRaster raster = img.getRaster();
|
||||||
|
WritableRaster newRaster = raster.createWritableChild(0, 0, img.getWidth(),
|
||||||
|
img.getHeight(), 0, 0, new int[] {0, 1, 2});
|
||||||
|
DirectColorModel cm = (DirectColorModel)img.getColorModel();
|
||||||
|
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
|
||||||
|
cm.getRedMask(), cm.getGreenMask(), cm.getBlueMask());
|
||||||
|
// now create the new buffer that is used ot write the image:
|
||||||
|
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
|
||||||
|
|
||||||
|
// Find a jpeg writer
|
||||||
|
ImageWriter writer = null;
|
||||||
|
Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
|
||||||
|
if (iter.hasNext()) {
|
||||||
|
writer = (ImageWriter)iter.next();
|
||||||
|
}
|
||||||
|
if(writer == null) {
|
||||||
|
Log.severe("No JPEG ENCODER - Java VM does not support JPEG encoding");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ImageWriteParam iwp = writer.getDefaultWriteParam();
|
||||||
|
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||||
|
iwp.setCompressionQuality(fmt.getQuality());
|
||||||
|
|
||||||
|
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
|
||||||
|
writer.setOutput(ios);
|
||||||
|
|
||||||
|
writer.write(null, new IIOImage(rgbBuffer, null, null), iwp);
|
||||||
|
writer.dispose();
|
||||||
|
|
||||||
|
rgbBuffer.flush();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImageIO.write(img, fmt.getFileExt(), baos); /* Write to byte array stream - prevent bogus I/O errors */
|
||||||
|
}
|
||||||
|
rslt = baos.toByteArray();
|
||||||
|
synchronized(baos_lock) {
|
||||||
|
baoslist.addFirst(baos);
|
||||||
}
|
}
|
||||||
while(!done) {
|
while(!done) {
|
||||||
RandomAccessFile f = null;
|
RandomAccessFile f = null;
|
||||||
|
Loading…
Reference in New Issue
Block a user