Various performance and concurrency optimizations

This commit is contained in:
Mike Primm 2011-12-10 14:14:52 +08:00 committed by mikeprimm
parent fd887b47b4
commit 05aa0960f2
6 changed files with 115 additions and 74 deletions

View File

@ -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) {

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;