Agneta Walterscheidt created FOP-2606: -----------------------------------------
Summary: Save memory by clearing Markers Key: FOP-2606 URL: https://issues.apache.org/jira/browse/FOP-2606 Project: FOP Issue Type: Improvement Components: fo/page Affects Versions: 2.1 Environment: all Reporter: Agneta Walterscheidt Priority: Minor When one of my fop transformations went out of memory I inspected the heap dump and found many instances of PageViewport.pageMarkers. These markers are kept for all pages although - as far as I see - for processed pages only the "last-within-page" markers are needed. Moreover the processed pages are searched from back to front which means that it would be sufficient to keep one marker instance for the page-sequence (=> throw away when a new page-sequence starts) and one instance for the document (=> never throw away) and there replace older markers with newer markers. I have implemented these changes on the trunk files and executed the build including the tests. You find a patch below. I think the best implementation depends on some decisions, for instance where the markers should be kept. Therefore could you please either integrate my changes or implement a similar solution? Index: area/AreaTreeModel.java =================================================================== --- area/AreaTreeModel.java (revision 1742452) +++ area/AreaTreeModel.java (working copy) @@ -27,6 +27,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.fo.flow.AbstractRetrieveMarker; +import org.apache.fop.fo.flow.Marker; +import org.apache.fop.fo.flow.Markers; +import org.apache.fop.fo.flow.RetrieveMarker; /** * This is the model for the area tree object. @@ -42,6 +46,11 @@ /** the current page sequence */ protected PageSequence currentPageSequence; + + Markers documentMarkers = new Markers(); + + Markers pageSequenceMarkers; + /** logger instance */ protected static final Log log = LogFactory.getLog(AreaTreeModel.class); @@ -64,6 +73,7 @@ currentPageIndex += currentPageSequence.getPageCount(); } this.currentPageSequence = pageSequence; + pageSequenceMarkers = null; pageSequenceList.add(currentPageSequence); } @@ -77,7 +87,29 @@ + currentPageSequence.getPageCount() - 1); page.setPageSequence(currentPageSequence); } + + public void addMarkers(Markers markers) { + if (markers != null) { + if (pageSequenceMarkers == null) { + pageSequenceMarkers = markers; + } else { + pageSequenceMarkers.add(markers); + } + documentMarkers.add(markers); + } + } + public Marker resolveMarker(AbstractRetrieveMarker arm, boolean doc) { + Marker mark = null; + if (pageSequenceMarkers != null) { + mark = pageSequenceMarkers.resolve(arm); + } + if (mark == null && doc) { + mark = documentMarkers.resolve(arm); + } + return mark; + } + /** * Handle an OffDocumentItem * @param ext the extension to handle Index: area/PageViewport.java =================================================================== --- area/PageViewport.java (revision 1742452) +++ area/PageViewport.java (working copy) @@ -538,4 +538,13 @@ } } + public Markers removeMarkers() { + if (pageMarkers == null) { + return null; + } + Markers markers = pageMarkers.createLastMarkers(); + pageMarkers = null; + return markers; + } + } Index: fo/flow/Markers.java =================================================================== --- fo/flow/Markers.java (revision 1742452) +++ fo/flow/Markers.java (working copy) @@ -213,4 +213,51 @@ } } + public Markers createLastMarkers() { + Markers markers = null; + if (lastQualifyingIsAny != null) { + markers = new Markers(); + markers.lastQualifyingIsAny = new HashMap<String, Marker>(lastQualifyingIsAny); + + if (lastQualifyingIsLast != null) { + markers.lastQualifyingIsAny.putAll(lastQualifyingIsLast); + } + } + return markers; + } + + public void add(Markers markers) { + if (markers.firstQualifyingIsFirst != null) { + if (firstQualifyingIsFirst == null) { + firstQualifyingIsFirst = new HashMap<String, Marker>(); + } + firstQualifyingIsFirst.putAll(markers.firstQualifyingIsFirst); + } + if (markers.firstQualifyingIsAny != null) { + if (firstQualifyingIsAny == null) { + firstQualifyingIsAny = new HashMap<String, Marker>(); + } + firstQualifyingIsAny.putAll(markers.firstQualifyingIsAny); + } + if (markers.lastQualifyingIsFirst != null) { + if (lastQualifyingIsFirst == null) { + lastQualifyingIsFirst = new HashMap<String, Marker>(); + } + lastQualifyingIsFirst.putAll(markers.lastQualifyingIsFirst); + } + if (markers.lastQualifyingIsLast != null) { + if (lastQualifyingIsLast == null) { + lastQualifyingIsLast = new HashMap<String, Marker>(); + } + lastQualifyingIsLast.putAll(markers.lastQualifyingIsLast); + } + if (markers.lastQualifyingIsAny != null) { + if (lastQualifyingIsAny == null) { + lastQualifyingIsAny = new HashMap<String, Marker>(); + } + lastQualifyingIsAny.putAll(markers.lastQualifyingIsAny); + } + + } + } Index: layoutmgr/AbstractPageSequenceLayoutManager.java =================================================================== --- layoutmgr/AbstractPageSequenceLayoutManager.java (revision 1742452) +++ layoutmgr/AbstractPageSequenceLayoutManager.java (working copy) @@ -32,6 +32,7 @@ import org.apache.fop.datatypes.Numeric; import org.apache.fop.fo.Constants; import org.apache.fop.fo.flow.Marker; +import org.apache.fop.fo.flow.Markers; import org.apache.fop.fo.flow.RetrieveMarker; import org.apache.fop.fo.pagination.AbstractPageSequence; @@ -231,31 +232,36 @@ // get marker from the current markers on area tree Marker mark = getCurrentPV().resolveMarker(rm); if (mark == null && boundary != EN_PAGE) { + boolean doc = (boundary == EN_DOCUMENT); + int originalPosition = rm.getPosition(); + rm.changePositionTo(Constants.EN_LEWP); + mark = areaTreeModel.resolveMarker(rm, doc); + rm.changePositionTo(originalPosition); + // go back over pages until mark found // if document boundary then keep going - boolean doc = (boundary == EN_DOCUMENT); - int seq = areaTreeModel.getPageSequenceCount(); - int page = areaTreeModel.getPageCount(seq) - 1; - while (page < 0 && doc && seq > 1) { - seq--; - page = areaTreeModel.getPageCount(seq) - 1; - } - while (page >= 0) { - PageViewport pv = areaTreeModel.getPage(seq, page); - int originalPosition = rm.getPosition(); - rm.changePositionTo(Constants.EN_LEWP); - mark = pv.resolveMarker(rm); - // this is probably not necessary since the RM will not be used again, but to be safe... - rm.changePositionTo(originalPosition); - if (mark != null) { - break; - } - page--; - if (page < 0 && doc && seq > 1) { - seq--; - page = areaTreeModel.getPageCount(seq) - 1; - } - } +// int seq = areaTreeModel.getPageSequenceCount(); +// int page = areaTreeModel.getPageCount(seq) - 1; +// while (page < 0 && doc && seq > 1) { +// seq--; +// page = areaTreeModel.getPageCount(seq) - 1; +// } +// while (page >= 0) { +// PageViewport pv = areaTreeModel.getPage(seq, page); +// int originalPosition = rm.getPosition(); +// rm.changePositionTo(Constants.EN_LEWP); +// mark = pv.resolveMarker(rm); +// // this is probably not necessary since the RM will not be used again, but to be safe... +// rm.changePositionTo(originalPosition); +// if (mark != null) { +// break; +// } +// page--; +// if (page < 0 && doc && seq > 1) { +// seq--; +// page = areaTreeModel.getPageCount(seq) - 1; +// } +// } } if (mark == null) { @@ -317,6 +323,10 @@ log.debug("page finished: " + curPage.getPageViewport().getPageNumberString() + ", current num: " + currentPageNum); } + Markers markers = curPage.getPageViewport().removeMarkers(); + if (markers != null) { + areaTreeHandler.getAreaTreeModel().addMarkers(markers); + } curPage = null; } -- This message was sent by Atlassian JIRA (v6.3.4#6332)