Issue #300 - rework of inflater and deflater pools
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
e41906fbdb
commit
e8115268d4
|
@ -21,7 +21,7 @@ package org.eclipse.jetty.server.jmh;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import org.eclipse.jetty.util.DeflaterPool;
|
||||
import org.eclipse.jetty.util.compression.DeflaterPool;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Level;
|
||||
|
|
|
@ -26,15 +26,21 @@ import java.util.ListIterator;
|
|||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.*;
|
||||
import org.eclipse.jetty.http.CompressedContentFormat;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.pathmap.PathSpecSet;
|
||||
import org.eclipse.jetty.util.DeflaterPool;
|
||||
import org.eclipse.jetty.server.HttpOutput;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
|
@ -42,6 +48,7 @@ import org.eclipse.jetty.util.IncludeExclude;
|
|||
import org.eclipse.jetty.util.RegexSet;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.compression.DeflaterPool;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
|
|
@ -91,10 +91,6 @@
|
|||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-pool</groupId>
|
||||
<artifactId>commons-pool</artifactId>
|
||||
</dependency>
|
||||
<!--
|
||||
This dependency is used to test Slf4jLog.
|
||||
Due to the introduction of src/test/resource/jetty-logging.properties (and the Log.static{} block)
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import org.apache.commons.pool.ObjectPool;
|
||||
import org.apache.commons.pool.PoolUtils;
|
||||
import org.apache.commons.pool.PoolableObjectFactory;
|
||||
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
public class CompressionPool
|
||||
{
|
||||
private CompressionPool()
|
||||
{
|
||||
}
|
||||
|
||||
public static ObjectPool<Inflater> limitedInflaterPool(int capacity, boolean nowrap)
|
||||
{
|
||||
return new GenericObjectPool<>(new InflaterPoolFactory(nowrap), blockingBorrowPoolConfig(capacity));
|
||||
}
|
||||
|
||||
public static ObjectPool<Inflater> growingInflaterPool(boolean nowrap)
|
||||
{
|
||||
GenericObjectPool<Inflater> objectPool = new GenericObjectPool<>(
|
||||
new InflaterPoolFactory(nowrap), growingPoolConfig());
|
||||
|
||||
return PoolUtils.erodingPool(objectPool);
|
||||
}
|
||||
|
||||
public static ObjectPool<Deflater> limitedDeflaterPool(int capacity, int compressionLevel, boolean nowrap)
|
||||
{
|
||||
return new GenericObjectPool<>(new DeflaterPoolFactory(compressionLevel, nowrap),
|
||||
blockingBorrowPoolConfig(capacity));
|
||||
}
|
||||
|
||||
public static ObjectPool<Deflater> growingDeflaterPool(int compressionLevel, boolean nowrap)
|
||||
{
|
||||
GenericObjectPool<Deflater> objectPool = new GenericObjectPool<>(
|
||||
new DeflaterPoolFactory(compressionLevel, nowrap), growingPoolConfig());
|
||||
|
||||
return PoolUtils.erodingPool(objectPool);
|
||||
}
|
||||
|
||||
private static GenericObjectPool.Config blockingBorrowPoolConfig(int capacity)
|
||||
{
|
||||
GenericObjectPool.Config config = new GenericObjectPool.Config();
|
||||
|
||||
config.maxActive = capacity;
|
||||
config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
|
||||
config.minEvictableIdleTimeMillis = TimeUnit.SECONDS.toMillis(1);
|
||||
config.timeBetweenEvictionRunsMillis = TimeUnit.SECONDS.toMillis(5);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
private static GenericObjectPool.Config growingPoolConfig()
|
||||
{
|
||||
GenericObjectPool.Config config = new GenericObjectPool.Config();
|
||||
config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
private static class DeflaterPoolFactory implements PoolableObjectFactory<Deflater>
|
||||
{
|
||||
private final int compressionLevel;
|
||||
private final boolean nowrap;
|
||||
|
||||
DeflaterPoolFactory(int compressionLevel, boolean nowrap)
|
||||
{
|
||||
this.compressionLevel = compressionLevel;
|
||||
this.nowrap = nowrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Deflater makeObject() throws Exception
|
||||
{
|
||||
return new Deflater(compressionLevel, nowrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyObject(Deflater obj) throws Exception
|
||||
{
|
||||
obj.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateObject(Deflater obj)
|
||||
{
|
||||
// currently it's not possible to understand if deflater had been finalized.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateObject(Deflater obj) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivateObject(Deflater obj) throws Exception
|
||||
{
|
||||
obj.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class InflaterPoolFactory implements PoolableObjectFactory<Inflater>
|
||||
{
|
||||
private final boolean nowrap;
|
||||
|
||||
InflaterPoolFactory(boolean nowrap)
|
||||
{
|
||||
this.nowrap = nowrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inflater makeObject() throws Exception
|
||||
{
|
||||
return new Inflater(nowrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyObject(Inflater obj) throws Exception
|
||||
{
|
||||
obj.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateObject(Inflater obj)
|
||||
{
|
||||
// currently it's not possible to understand if inflater had been finalized.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateObject(Inflater obj) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passivateObject(Inflater obj) throws Exception
|
||||
{
|
||||
obj.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.util.compression;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class CompressionPool<T>
|
||||
{
|
||||
private final Queue<T> _pool;
|
||||
private final AtomicInteger _numObjects = new AtomicInteger(0);
|
||||
private final int _capacity;
|
||||
|
||||
/**
|
||||
* Create a Pool of {@link T} instances.
|
||||
*
|
||||
* If given a capacity equal to zero the Objects will not be pooled
|
||||
* and will be created on acquire and ended on release.
|
||||
* If given a negative capacity equal to zero there will be no size restrictions on the Pool
|
||||
*
|
||||
* @param capacity maximum number of Objects which can be contained in the pool
|
||||
*/
|
||||
public CompressionPool(int capacity)
|
||||
{
|
||||
_capacity = capacity;
|
||||
_pool = (_capacity==0) ? null : new ConcurrentLinkedQueue<>();
|
||||
}
|
||||
|
||||
abstract protected T newObject();
|
||||
|
||||
abstract protected void end(T object);
|
||||
|
||||
abstract protected void reset(T object);
|
||||
|
||||
/**
|
||||
* @return Object taken from the pool if it is not empty or a newly created Object
|
||||
*/
|
||||
public T acquire()
|
||||
{
|
||||
T object;
|
||||
|
||||
if (_capacity == 0)
|
||||
object = newObject();
|
||||
else if (_capacity < 0)
|
||||
{
|
||||
object = _pool.poll();
|
||||
if (object == null)
|
||||
object = newObject();
|
||||
}
|
||||
else
|
||||
{
|
||||
object = _pool.poll();
|
||||
if (object == null)
|
||||
object = newObject();
|
||||
else
|
||||
_numObjects.decrementAndGet();
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object returns this Object to the pool or calls {@link #end(T)} if the pool is full.
|
||||
*/
|
||||
public void release(T object)
|
||||
{
|
||||
if (object == null)
|
||||
return;
|
||||
|
||||
if (_capacity == 0)
|
||||
{
|
||||
end(object);
|
||||
return;
|
||||
}
|
||||
else if (_capacity < 0)
|
||||
{
|
||||
reset(object);
|
||||
_pool.add(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int d = _numObjects.get();
|
||||
|
||||
if (d >= _capacity)
|
||||
{
|
||||
end(object);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_numObjects.compareAndSet(d, d + 1))
|
||||
{
|
||||
reset(object);
|
||||
_pool.add(object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,15 +16,14 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import org.apache.commons.pool.ObjectPool;
|
||||
package org.eclipse.jetty.util.compression;
|
||||
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
public class DeflaterPool
|
||||
public class DeflaterPool extends CompressionPool<Deflater>
|
||||
{
|
||||
private final ObjectPool<Deflater> deflaterPool;
|
||||
private final int compressionLevel;
|
||||
private final boolean nowrap;
|
||||
|
||||
/**
|
||||
* Create a Pool of {@link Deflater} instances.
|
||||
|
@ -39,41 +38,26 @@ public class DeflaterPool
|
|||
*/
|
||||
public DeflaterPool(int capacity, int compressionLevel, boolean nowrap)
|
||||
{
|
||||
deflaterPool = capacity <= 0
|
||||
? CompressionPool.growingDeflaterPool(compressionLevel, nowrap)
|
||||
: CompressionPool.limitedDeflaterPool(capacity, compressionLevel, nowrap);
|
||||
super(capacity);
|
||||
this.compressionLevel = compressionLevel;
|
||||
this.nowrap = nowrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Deflater taken from the pool if it is not empty or a newly created Deflater
|
||||
*/
|
||||
public Deflater acquire()
|
||||
@Override
|
||||
protected Deflater newObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return deflaterPool.borrowObject();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new Deflater(compressionLevel, nowrap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param deflater returns this Deflater to the pool or calls deflater.end() if the pool is full.
|
||||
*/
|
||||
public void release(Deflater deflater)
|
||||
@Override
|
||||
protected void end(Deflater deflater)
|
||||
{
|
||||
if (deflater == null)
|
||||
return;
|
||||
deflater.end();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
deflaterPool.returnObject(deflater);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@Override
|
||||
protected void reset(Deflater deflater)
|
||||
{
|
||||
deflater.reset();
|
||||
}
|
||||
}
|
|
@ -16,16 +16,13 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import org.apache.commons.pool.ObjectPool;
|
||||
package org.eclipse.jetty.util.compression;
|
||||
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
public class InflaterPool
|
||||
public class InflaterPool extends CompressionPool<Inflater>
|
||||
{
|
||||
|
||||
private final ObjectPool<Inflater> inflaterPool;
|
||||
private final boolean nowrap;
|
||||
|
||||
/**
|
||||
* Create a Pool of {@link Inflater} instances.
|
||||
|
@ -39,38 +36,25 @@ public class InflaterPool
|
|||
*/
|
||||
public InflaterPool(int capacity, boolean nowrap)
|
||||
{
|
||||
inflaterPool = (capacity <= 0)
|
||||
? CompressionPool.growingInflaterPool(nowrap)
|
||||
: CompressionPool.limitedInflaterPool(capacity, nowrap);
|
||||
super(capacity);
|
||||
this.nowrap = nowrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Inflater taken from the pool if it is not empty or a newly created Inflater
|
||||
*/
|
||||
public Inflater acquire()
|
||||
@Override
|
||||
protected Inflater newObject()
|
||||
{
|
||||
try
|
||||
{
|
||||
return inflaterPool.borrowObject();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new Inflater(nowrap);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inflater returns this Inflater to the pool or calls inflater.end() if the pool is full.
|
||||
*/
|
||||
public void release(Inflater inflater)
|
||||
@Override
|
||||
protected void end(Inflater inflater)
|
||||
{
|
||||
try
|
||||
{
|
||||
inflaterPool.returnObject(inflater);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
inflater.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reset(Inflater inflater)
|
||||
{
|
||||
inflater.reset();
|
||||
}
|
||||
}
|
|
@ -29,9 +29,9 @@ import java.util.zip.Inflater;
|
|||
import java.util.zip.ZipException;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.DeflaterPool;
|
||||
import org.eclipse.jetty.util.InflaterPool;
|
||||
import org.eclipse.jetty.util.IteratingCallback;
|
||||
import org.eclipse.jetty.util.compression.DeflaterPool;
|
||||
import org.eclipse.jetty.util.compression.InflaterPool;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.BatchMode;
|
||||
|
|
Loading…
Reference in New Issue