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.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
import java.util.zip.DeflaterOutputStream;
|
|
||||||
|
|
||||||
import javax.servlet.AsyncEvent;
|
import javax.servlet.AsyncEvent;
|
||||||
import javax.servlet.AsyncListener;
|
import javax.servlet.AsyncListener;
|
||||||
|
@ -43,6 +43,7 @@ import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
import org.eclipse.jetty.servlets.gzip.AbstractCompressedStream;
|
import org.eclipse.jetty.servlets.gzip.AbstractCompressedStream;
|
||||||
import org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper;
|
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.servlets.gzip.GzipOutputStream;
|
||||||
import org.eclipse.jetty.util.URIUtil;
|
import org.eclipse.jetty.util.URIUtil;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
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
|
// non-static, as other GzipFilter instances may have different configurations
|
||||||
protected final ThreadLocal<Deflater> _deflater = new ThreadLocal<Deflater>();
|
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 final Set<String> _methods=new HashSet<String>();
|
||||||
protected Set<String> _excludedAgents;
|
protected Set<String> _excludedAgents;
|
||||||
protected Set<Pattern> _excludedAgentPatterns;
|
protected Set<Pattern> _excludedAgentPatterns;
|
||||||
|
@ -464,9 +467,10 @@ public class GzipFilter extends UserAgentFilter
|
||||||
return new AbstractCompressedStream(compressionType,request,this,_vary)
|
return new AbstractCompressedStream(compressionType,request,this,_vary)
|
||||||
{
|
{
|
||||||
private Deflater _allocatedDeflater;
|
private Deflater _allocatedDeflater;
|
||||||
|
private byte[] _allocatedBuffer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DeflaterOutputStream createStream() throws IOException
|
protected OutputStream createStream() throws IOException
|
||||||
{
|
{
|
||||||
if (compressionType == null)
|
if (compressionType == null)
|
||||||
{
|
{
|
||||||
|
@ -483,12 +487,21 @@ public class GzipFilter extends UserAgentFilter
|
||||||
_allocatedDeflater.reset();
|
_allocatedDeflater.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// acquire buffer
|
||||||
|
_allocatedBuffer = _buffer.get();
|
||||||
|
if (_allocatedBuffer==null)
|
||||||
|
_allocatedBuffer = new byte[_bufferSize];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_buffer.remove();
|
||||||
|
}
|
||||||
|
|
||||||
switch (compressionType)
|
switch (compressionType)
|
||||||
{
|
{
|
||||||
case GZIP:
|
case GZIP:
|
||||||
return new GzipOutputStream(_response.getOutputStream(),_allocatedDeflater,_bufferSize);
|
return new GzipOutputStream(_response.getOutputStream(),_allocatedDeflater,_allocatedBuffer);
|
||||||
case DEFLATE:
|
case DEFLATE:
|
||||||
return new DeflaterOutputStream(_response.getOutputStream(),_allocatedDeflater,_bufferSize);
|
return new DeflatedOutputStream(_response.getOutputStream(),_allocatedDeflater,_allocatedBuffer);
|
||||||
}
|
}
|
||||||
throw new IllegalStateException(compressionType + " not supported");
|
throw new IllegalStateException(compressionType + " not supported");
|
||||||
}
|
}
|
||||||
|
@ -501,6 +514,10 @@ public class GzipFilter extends UserAgentFilter
|
||||||
{
|
{
|
||||||
_deflater.set(_allocatedDeflater);
|
_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.OutputStreamWriter;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.zip.DeflaterOutputStream;
|
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.WriteListener;
|
import javax.servlet.WriteListener;
|
||||||
|
@ -46,7 +45,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
protected final HttpServletResponse _response;
|
protected final HttpServletResponse _response;
|
||||||
protected OutputStream _out;
|
protected OutputStream _out;
|
||||||
protected ByteArrayOutputStream2 _bOut;
|
protected ByteArrayOutputStream2 _bOut;
|
||||||
protected DeflaterOutputStream _compressedOutputStream;
|
protected OutputStream _compressedOutputStream;
|
||||||
protected boolean _closed;
|
protected boolean _closed;
|
||||||
protected boolean _doNotCompress;
|
protected boolean _doNotCompress;
|
||||||
|
|
||||||
|
@ -392,7 +391,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* Signals that an I/O exception has occurred.
|
* 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.io.OutputStream;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
import java.util.zip.DeflaterOutputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reimplementation of {@link java.util.zip.GZIPOutputStream} that supports reusing a {@link Deflater} instance.
|
* 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[]
|
private final static byte[] GZIP_HEADER = new byte[]
|
||||||
|
@ -35,9 +34,9 @@ public class GzipOutputStream extends DeflaterOutputStream
|
||||||
|
|
||||||
private final CRC32 _crc = new CRC32();
|
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);
|
out.write(GZIP_HEADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,23 +50,15 @@ public class GzipOutputStream extends DeflaterOutputStream
|
||||||
@Override
|
@Override
|
||||||
public synchronized void finish() throws IOException
|
public synchronized void finish() throws IOException
|
||||||
{
|
{
|
||||||
if (!def.finished())
|
if (!_def.finished())
|
||||||
{
|
{
|
||||||
super.finish();
|
super.finish();
|
||||||
byte[] trailer = new byte[8];
|
byte[] trailer = new byte[8];
|
||||||
writeInt((int)_crc.getValue(),trailer,0);
|
writeInt((int)_crc.getValue(),trailer,0);
|
||||||
writeInt(def.getTotalIn(),trailer,4);
|
writeInt(_def.getTotalIn(),trailer,4);
|
||||||
out.write(trailer);
|
out.write(trailer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void close() throws IOException
|
|
||||||
{
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void writeInt(int i, byte[] buf, int offset)
|
private void writeInt(int i, byte[] buf, int offset)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue