423005 reuse gzipfilter buffers
This commit is contained in:
parent
9c39b2e631
commit
e9df551352
|
@ -20,13 +20,13 @@ package org.eclipse.jetty.servlets;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.AsyncListener;
|
||||
|
@ -43,6 +43,7 @@ import org.eclipse.jetty.http.HttpMethod;
|
|||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.servlets.gzip.AbstractCompressedStream;
|
||||
import org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.servlets.gzip.DeflatedOutputStream;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipOutputStream;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -142,6 +143,8 @@ public class GzipFilter extends UserAgentFilter
|
|||
// non-static, as other GzipFilter instances may have different configurations
|
||||
protected final ThreadLocal<Deflater> _deflater = new ThreadLocal<Deflater>();
|
||||
|
||||
protected final static ThreadLocal<byte[]> _buffer= new ThreadLocal<byte[]>();
|
||||
|
||||
protected final Set<String> _methods=new HashSet<String>();
|
||||
protected Set<String> _excludedAgents;
|
||||
protected Set<Pattern> _excludedAgentPatterns;
|
||||
|
@ -464,9 +467,10 @@ public class GzipFilter extends UserAgentFilter
|
|||
return new AbstractCompressedStream(compressionType,request,this,_vary)
|
||||
{
|
||||
private Deflater _allocatedDeflater;
|
||||
private byte[] _allocatedBuffer;
|
||||
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
protected OutputStream createStream() throws IOException
|
||||
{
|
||||
if (compressionType == null)
|
||||
{
|
||||
|
@ -483,12 +487,21 @@ public class GzipFilter extends UserAgentFilter
|
|||
_allocatedDeflater.reset();
|
||||
}
|
||||
|
||||
// acquire buffer
|
||||
_allocatedBuffer = _buffer.get();
|
||||
if (_allocatedBuffer==null)
|
||||
_allocatedBuffer = new byte[_bufferSize];
|
||||
else
|
||||
{
|
||||
_buffer.remove();
|
||||
}
|
||||
|
||||
switch (compressionType)
|
||||
{
|
||||
case GZIP:
|
||||
return new GzipOutputStream(_response.getOutputStream(),_allocatedDeflater,_bufferSize);
|
||||
return new GzipOutputStream(_response.getOutputStream(),_allocatedDeflater,_allocatedBuffer);
|
||||
case DEFLATE:
|
||||
return new DeflaterOutputStream(_response.getOutputStream(),_allocatedDeflater,_bufferSize);
|
||||
return new DeflatedOutputStream(_response.getOutputStream(),_allocatedDeflater,_allocatedBuffer);
|
||||
}
|
||||
throw new IllegalStateException(compressionType + " not supported");
|
||||
}
|
||||
|
@ -501,6 +514,10 @@ public class GzipFilter extends UserAgentFilter
|
|||
{
|
||||
_deflater.set(_allocatedDeflater);
|
||||
}
|
||||
if (_allocatedBuffer != null && _buffer.get() == null)
|
||||
{
|
||||
_buffer.set(_allocatedBuffer);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.io.OutputStream;
|
|||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
|
@ -46,7 +45,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
protected final HttpServletResponse _response;
|
||||
protected OutputStream _out;
|
||||
protected ByteArrayOutputStream2 _bOut;
|
||||
protected DeflaterOutputStream _compressedOutputStream;
|
||||
protected OutputStream _compressedOutputStream;
|
||||
protected boolean _closed;
|
||||
protected boolean _doNotCompress;
|
||||
|
||||
|
@ -392,7 +391,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
protected abstract DeflaterOutputStream createStream() throws IOException;
|
||||
protected abstract OutputStream createStream() throws IOException;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
package org.eclipse.jetty.servlets.gzip;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
/**
|
||||
* Reimplementation of {@link java.util.zip.DeflaterOutputStream} that supports reusing the buffer.
|
||||
*/
|
||||
public class DeflatedOutputStream extends FilterOutputStream
|
||||
{
|
||||
protected final Deflater _def;
|
||||
protected final byte[] _buf;
|
||||
protected boolean closed = false;
|
||||
|
||||
public DeflatedOutputStream(OutputStream out, Deflater deflater, byte[] buffer)
|
||||
{
|
||||
super(out);
|
||||
_def = deflater;
|
||||
_buf = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
byte[] buf = new byte[1];
|
||||
buf[0] = (byte)(b & 0xff);
|
||||
write(buf,0,1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
if (_def.finished())
|
||||
throw new IOException("Stream already finished");
|
||||
if ((off | len | (off + len) | (b.length - (off + len))) < 0)
|
||||
throw new IndexOutOfBoundsException();
|
||||
if (len == 0)
|
||||
return;
|
||||
if (!_def.finished())
|
||||
{
|
||||
_def.setInput(b,off,len);
|
||||
while (!_def.needsInput())
|
||||
{
|
||||
deflate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deflate() throws IOException
|
||||
{
|
||||
int len = _def.deflate(_buf,0,_buf.length);
|
||||
if (len > 0)
|
||||
{
|
||||
out.write(_buf,0,len);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void finish() throws IOException
|
||||
{
|
||||
if (!_def.finished())
|
||||
{
|
||||
_def.finish();
|
||||
while (!_def.finished())
|
||||
{
|
||||
deflate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws IOException
|
||||
{
|
||||
if (!closed)
|
||||
{
|
||||
finish();
|
||||
out.close();
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -22,12 +22,11 @@ import java.io.IOException;
|
|||
import java.io.OutputStream;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
/**
|
||||
* Reimplementation of {@link java.util.zip.GZIPOutputStream} that supports reusing a {@link Deflater} instance.
|
||||
*/
|
||||
public class GzipOutputStream extends DeflaterOutputStream
|
||||
public class GzipOutputStream extends DeflatedOutputStream
|
||||
{
|
||||
|
||||
private final static byte[] GZIP_HEADER = new byte[]
|
||||
|
@ -35,9 +34,9 @@ public class GzipOutputStream extends DeflaterOutputStream
|
|||
|
||||
private final CRC32 _crc = new CRC32();
|
||||
|
||||
public GzipOutputStream(OutputStream out, Deflater deflater, int size) throws IOException
|
||||
public GzipOutputStream(OutputStream out, Deflater deflater, byte[] buffer) throws IOException
|
||||
{
|
||||
super(out,deflater,size);
|
||||
super(out,deflater,buffer);
|
||||
out.write(GZIP_HEADER);
|
||||
}
|
||||
|
||||
|
@ -51,24 +50,16 @@ public class GzipOutputStream extends DeflaterOutputStream
|
|||
@Override
|
||||
public synchronized void finish() throws IOException
|
||||
{
|
||||
if (!def.finished())
|
||||
if (!_def.finished())
|
||||
{
|
||||
super.finish();
|
||||
byte[] trailer = new byte[8];
|
||||
writeInt((int)_crc.getValue(),trailer,0);
|
||||
writeInt(def.getTotalIn(),trailer,4);
|
||||
writeInt(_def.getTotalIn(),trailer,4);
|
||||
out.write(trailer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws IOException
|
||||
{
|
||||
super.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void writeInt(int i, byte[] buf, int offset)
|
||||
{
|
||||
int o = offset;
|
||||
|
|
Loading…
Reference in New Issue