diff --git a/src/main/java/bdv/server/CellHandler.java b/src/main/java/bdv/server/CellHandler.java index e11e818b58c19fd702512d886fe9f6a2e694fa2b..0ebdcf0082b43ddfb5f6a0e34685493a33516894 100644 --- a/src/main/java/bdv/server/CellHandler.java +++ b/src/main/java/bdv/server/CellHandler.java @@ -46,6 +46,8 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Stack; +import java.util.concurrent.locks.ReentrantLock; public class CellHandler extends ContextHandler { private long transferedDataSize = 0; @@ -99,9 +101,10 @@ public class CellHandler extends ContextHandler { * Compression stuff. */ private final CompressionOptions compressionParams; - private ICacheFile compressionCacheFile = null; private ImageCompressor compressor = null; - private MemoryOutputStream cachedCompressionStream = null; + private Stack<MemoryOutputStream> cachedBuffers = null; + private ICacheFile compressionCacheFile = null; + private final int INITIAL_BUFFER_SIZE = 2048; public CellHandler(final String baseUrl, final String xmlFilename, final String datasetName, final String thumbnailsDirectory, final CompressionOptions compressionParams) throws SpimDataException, IOException { @@ -143,8 +146,27 @@ public class CellHandler extends ContextHandler { LOG.info("CellHandler loaded codebook cache file. '" + compressionCacheFile + "'"); System.out.println("\u001b[33mCellHandler::initializeCompression() loaded codebook cache file for: " + baseFilename + "\u001b[0m"); + final int initialCompressionCacheSize = 10; + compressor = new ImageCompressor(compressionParams, compressionCacheFile); - cachedCompressionStream = new MemoryOutputStream(4096); + cachedBuffers = new Stack<>(); + for (int i = 0; i < initialCompressionCacheSize; i++) { + cachedBuffers.push(new MemoryOutputStream(INITIAL_BUFFER_SIZE)); + } + } + + + private synchronized MemoryOutputStream getCachedCompressionBuffer() { + if (!cachedBuffers.empty()) { + return cachedBuffers.pop(); + } else { + return new MemoryOutputStream(INITIAL_BUFFER_SIZE); + } + } + + private synchronized void returnBufferForReuse(MemoryOutputStream buffer) { + buffer.reset(); + cachedBuffers.push(buffer); } private short[] getCachedVolatileCellData(final String[] parts, final int[] cellDims) { @@ -227,19 +249,31 @@ public class CellHandler extends ContextHandler { final short[] data = getCachedVolatileCellData(parts, cellDims); assert (compressor != null); - compressor.setInputData(createInputDataObject(data, cellDims)); - cachedCompressionStream.reset(); - final int compressedContentLength = compressor.streamCompressChunk(cachedCompressionStream); + final FlatBufferInputData inputData = createInputDataObject(data, cellDims); + + MemoryOutputStream cellCompressionStream = getCachedCompressionBuffer(); + final int compressedContentLength = compressor.streamCompressChunk(cellCompressionStream, inputData); response.setContentLength(compressedContentLength); try (OutputStream responseStream = response.getOutputStream()) { - responseStream.write(cachedCompressionStream.getBuffer(), 0, cachedCompressionStream.getCurrentBufferLength()); + responseStream.write(cellCompressionStream.getBuffer(), 0, cellCompressionStream.getCurrentBufferLength()); } + assert (cellCompressionStream.getCurrentBufferLength() == compressedContentLength) : + "compressor.streamCompressChunk() is not equal to cachedCompressionStream.getCurrentBufferLength()"; + + if (cellCompressionStream.getCurrentBufferLength() != compressedContentLength) { + System.err.printf("stream size\t%d\nreported size\t%d\n\n", + cellCompressionStream.getCurrentBufferLength(), + compressedContentLength); + } + + response.setContentType("application/octet-stream"); response.setStatus(HttpServletResponse.SC_OK); baseRequest.setHandled(true); + returnBufferForReuse(cellCompressionStream); } else if (parts[0].equals("init")) { respondWithString(baseRequest, response, "application/json", metadataJson); } else if (parts[0].equals("init_qcmp")) {