在Tapestry4中使用SoftReference实现ObjectPool
Tapestry4.0.x版本的PagePool实现很简单,只是使用一个map容器作为缓存,高并发的情况下容易导致OutOfMemoryException,下面是邮件列表中的相关内容,里边也提到了相关建议,估计会作为一个bug修改,在未修改之前,我会给出一个简单实现。
PagePool doesnt remove idle pages, heap memory doens't get reallocated
> ----------------------------------------------------------------------
>
> Key: TAPESTRY-1151
> URL: http://issues.apache.org/jira/browse/TAPESTRY-1151
> Project: Tapestry
> Issue Type: Bug
> Components: Framework
> Affects Versions: 4.0
> Environment: java 1.4, apache tomcat 5.0 IBM websphere 5.0
> Reporter: lionel gomez
> Assigned To: Jesse Kuhnert
> Priority: Minor
>
> This may not qualify as a bug since its so easy to provide override using hivemind, but instead an improvement for future releases. Also provided an optional page pool implementation.
> Tapestry 4.0 PagePool implementation doesnt remove idle pages. When having hundred of pages with a lot of components and high user concurrency, tapestry generates many instances of each page. These instances are pooled and never unreferenced and never garbage collected. Our 1GB heap eventually fills up and reduces the memory available to other parts of the application. Eventually causes OutOfMemoryException.
> We ensured caching is enabled and config change made to use unique locale, but still, heap eventually fills up.
> With Hivemind its very easy to override the pagePool and provide different implementation. A page pool that uses softReferences is a good option.
> Acording to java api:
> All soft references to softly-reachable objects are guaranteed to have been cleared before the virtual machine throws an OutOfMemoryError.
> This prevents OEM due to heap filling up.
> New SoftPagePool only changes a couple of lines to use soft references.
> public synchronized Object get(Object key)
> {
> List pooled = (List) _pool.get(key);
> if (pooled == null || pooled.isEmpty())
> return null;
> _count--;
> SoftReference reference = (SoftReference) pooled.remove(0);
> //returns null if has been cleared by GC same as pool where empty
> return reference.get();
> }
> public synchronized void store(Object key, Object value)
> {
> List pooled = (List) _pool.get(key);
> if (pooled == null)
> {
> pooled = new LinkedList();
> _pool.put(key, pooled);
> }
> SoftReference reference = new SoftReference(value);
> pooled.add(reference);
> _count++;
> }
> Additionally the page pool implementation can use a clean idle pages mechanism using same design as Tapestry 3.0 ThreadJanitor or setting a timestamp when storing pages and a TimerTask and Timer wich receives events on registry shutdown. All this by using hivemind overriding features.
java类实现代码:
- public class SoftReferenceObjectPool implements ObjectPool, ResetEventListener,
- ReportStatusListener {
- private String _serviceId;
- private int _count = 0;
- private Map _pool = new HashMap();
- public synchronized Object get(Object key) {
- List pooled = (List) _pool.get(key);
- if (pooled == null || pooled.isEmpty())
- return null;
- _count--;
- SoftReference reference = (SoftReference) pooled.remove(0);
- // returns null if has been cleared by GC same as pool where empty
- return reference.get();
- }
- public synchronized void store(Object key, Object value) {
- List pooled = (List) _pool.get(key);
- if (pooled == null) {
- pooled = new LinkedList();
- _pool.put(key, pooled);
- }
- SoftReference reference = new SoftReference(value);
- pooled.add(reference);
- _count++;
- }
- public synchronized void resetEventDidOccur() {
- _pool.clear();
- _count = 0;
- }
- public synchronized void reportStatus(ReportStatusEvent event) {
- event.title(_serviceId);
- event.property("total count", _count);
- event.section("Count by Key");
- Iterator i = _pool.entrySet().iterator();
- while (i.hasNext()) {
- Map.Entry entry = (Map.Entry) i.next();
- String key = entry.getKey().toString();
- List pooled = (List) entry.getValue();
- event.property(key, pooled.size());
- }
- }
- public void setServiceId(String serviceId) {
- _serviceId = serviceId;
- }
- }
查找了一下hivemind中用到ObjectPool的地方,共有三处,分别替换之。
- <implementation service-id="tapestry.page.PagePool">
- <invoke-factory>
- <construct class="org.edynasty.tapestry.pool.SoftReferenceObjectPool">
- <event-listener service-id="tapestry.ResetEventHub"/>
- <event-listener service-id="tapestry.describe.ReportStatusHub"/>
- </construct>
- </invoke-factory>
- </implementation>
- <implementation service-id="tapestry.GlobalObjectPool">
- <invoke-factory>
- <construct class="org.edynasty.tapestry.pool.SoftReferenceObjectPool">
- <event-listener service-id="tapestry.ResetEventHub"/>
- <event-listener service-id="tapestry.describe.ReportStatusHub"/>
- </construct>
- </invoke-factory>
- </implementation>
- <implementation service-id="tapestry.request.EnginePool">
- <invoke-factory>
- <construct class="org.edynasty.tapestry.pool.SoftReferenceObjectPool">
- <event-listener service-id="tapestry.ResetEventHub"/>
- <event-listener service-id="tapestry.describe.ReportStatusHub"/>
- </construct>
- </invoke-factory>
- </implementation>
发表评论
- 浏览: 91619 次

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
Tapestry5-如何在根目录下 ...
o,是我看的不仔细。不过我都是放在class相对应的资源包中。
-- by KorbenZhang -
Tapestry5-如何在根目录下 ...
文章提到的是组件类的模板,页面类默认是在根目录的。
-- by tapestry -
Tapestry5-如何在根目录下 ...
过时了,T5已经把tml文件放在根目录了。
-- by KorbenZhang -
Tapestry5开发系列:如何 ...
我删掉了依赖,加了servlet还是不行,jetty就是不起来,说没找到logg ...
-- by leegorous -
Tapestry5每日播报(20080 ...
非常支持.
-- by biaoming






评论排行榜