I don’t usually fetch all objects but fetch in batches. You need to recycle the EOEditingContext. I tend to bring the array in batches, process, then create a new editing context and repeat.
I have some code included below but I think there is also good batching support in Wonder. The code below fetches raw rows and then converts to an EO when requested. The code below will automatically use a new editing context for each batch. Mark package com.eldrix.snomedct.search; import java.util.Iterator; import org.apache.log4j.Logger; import com.webobjects.eoaccess.EODatabaseContext; import com.webobjects.eoaccess.EOEntity; import com.webobjects.eoaccess.EOSQLExpression; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.eocontrol.EOFetchSpecification; import com.webobjects.eocontrol.EOSortOrdering; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSDictionary; import er.extensions.eof.ERXEC; import er.extensions.eof.ERXEOAccessUtilities; import er.extensions.eof.ERXEOControlUtilities; /** * This is an optimised memory-efficient method of iterating through enterprise objects. * This will iterate through enterprise objects, either returning the primary key, the object or the raw row. * * For example: * <code> * <pre> * for(EOEnterpriseObject eo: IterableBatchEnterpriseObjects.allObjectsOfEntity("Patient", 300) { * // process eo * } * </pre> * </code> * * @author mark * */ @SuppressWarnings("rawtypes") public class IterableBatchEnterpriseObjects implements Iterable<Object> { private static Logger log = Logger.getLogger(IterableBatchEnterpriseObjects.class); private final static int DEFAULT_BATCH_SIZE=50; private EOEditingContext _ec; private EOFetchSpecification _fs; private int _rowCount; private int _start; private int _batchSize; private NSArray _currentBatch; private int _batchPosition; private IterableBatchMode _mode; private boolean _refreshEditingContext = true; // we create a new editing context for each batch by default private enum IterableBatchMode { PRIMARY_KEYS { NSArray resultsInRange(EOEditingContext ec, EOFetchSpecification fs, int start, int end) { return ERXEOControlUtilities.primaryKeyValuesInRange(ec, fs, start, end); } }, OBJECTS { NSArray resultsInRange(EOEditingContext ec, EOFetchSpecification fs, int start, int end) { return ERXEOControlUtilities.objectsInRange(ec, fs, start, end); } }, RAW_ROWS { NSArray resultsInRange(EOEditingContext ec, EOFetchSpecification fs, int start, int end) { return rawRowsInRange(ec, fs, start, end); } }; abstract NSArray resultsInRange(EOEditingContext ec, EOFetchSpecification fs, int start, int end); }; private IterableBatchEnterpriseObjects(EOFetchSpecification fs, int batchSize, IterableBatchMode mode) { _fs = fs; _batchSize = batchSize; _mode = mode; _rowCount = ERXEOAccessUtilities.rowCountForFetchSpecification(editingContext(), _fs); } public static IterableBatchEnterpriseObjects allObjectsOfEntity(String entityName, NSArray<EOSortOrdering> sortOrderings, int batchSize) { EOFetchSpecification fs = new EOFetchSpecification(entityName, null, sortOrderings); return new IterableBatchEnterpriseObjects(fs, batchSize, IterableBatchMode.OBJECTS); } public static IterableBatchEnterpriseObjects allObjectsOfEntity(String entityName, int batchSize) { return allObjectsOfEntity(entityName, sortByPrimaryKey(entityName), batchSize); } public static IterableBatchEnterpriseObjects allObjectsOfEntity(String entityName) { return allObjectsOfEntity(entityName, DEFAULT_BATCH_SIZE); } public static IterableBatchEnterpriseObjects allPrimaryKeysOfEntity(String entityName, NSArray<EOSortOrdering> sortOrderings, int batchSize) { EOFetchSpecification fs = new EOFetchSpecification(entityName, null, sortOrderings); return new IterableBatchEnterpriseObjects(fs, batchSize, IterableBatchMode.PRIMARY_KEYS); } public static IterableBatchEnterpriseObjects allPrimaryKeysOfEntity(String entityName, int batchSize) { return allPrimaryKeysOfEntity(entityName, sortByPrimaryKey(entityName), batchSize); } public static IterableBatchEnterpriseObjects allPrimaryKeysOfEntity(String entityName) { return allPrimaryKeysOfEntity(entityName, DEFAULT_BATCH_SIZE); } public static IterableBatchEnterpriseObjects objects(EOFetchSpecification fs, int batchSize) { return new IterableBatchEnterpriseObjects(fs, batchSize, IterableBatchMode.OBJECTS); } public static IterableBatchEnterpriseObjects primaryKeys(EOFetchSpecification fs, int batchSize) { return new IterableBatchEnterpriseObjects(fs, batchSize, IterableBatchMode.PRIMARY_KEYS); } public static IterableBatchEnterpriseObjects rawRows(EOFetchSpecification fs, int batchSize) { return new IterableBatchEnterpriseObjects(fs, batchSize, IterableBatchMode.RAW_ROWS); } public static NSArray<EOSortOrdering> sortByPrimaryKey(String entityName) { EOEntity entity = ERXEOAccessUtilities.entityNamed(null, entityName); NSArray<String> attrs = entity.primaryKeyAttributeNames(); EOSortOrdering so = EOSortOrdering.sortOrderingWithKey(attrs.get(0), EOSortOrdering.CompareAscending); return new NSArray<EOSortOrdering>(so); } /** * Returns an {@link com.webobjects.foundation.NSArray NSArray} containing the raw rows for the fetch specification. * This is based upon ERXEOControlUtilities.primaryKeyValuesInRange * @param ec * @param spec * @param start * @param end * @see er.extensions.eof.ERXEOControlUtilities#primaryKeyValuesInRange * @return */ public static NSArray rawRowsInRange(EOEditingContext ec, EOFetchSpecification spec, int start, int end) { EOEntity entity = ERXEOAccessUtilities.entityNamed(ec, spec.entityName()); NSArray attributeNames = (NSArray) entity.attributes().valueForKey("name"); spec.setFetchesRawRows(true); spec.setRawRowKeyPaths(attributeNames); EOFetchSpecification clonedFetchSpec = (EOFetchSpecification)spec.clone(); EOSQLExpression sql = ERXEOAccessUtilities.sqlExpressionForFetchSpecification(ec, clonedFetchSpec, start, end); NSDictionary<String, EOSQLExpression> hints = new NSDictionary<String, EOSQLExpression>(sql, EODatabaseContext.CustomQueryExpressionHintKey); clonedFetchSpec.setHints(hints); return ec.objectsWithFetchSpecification(clonedFetchSpec); } public EOEditingContext editingContext() { if (_ec == null) { _ec = ERXEC.newEditingContext(); } return _ec; } public void setEditingContext(EOEditingContext ec) { _ec = ec; _refreshEditingContext = false; } protected EOFetchSpecification fetchSpecification() { return _fs; } protected NSArray currentBatch() { if (_currentBatch == null) { if (_start > _rowCount) return null; int end = _start + _batchSize; if (end > _rowCount) end = _rowCount; log.debug("Fetching batch... start: " + _start + " end: " + end); _currentBatch = _mode.resultsInRange(editingContext(), fetchSpecification(), _start, end); _batchPosition = 0; } return _currentBatch; } /** * Fetch next batch, optionally creating a new editingcontext for this new batch * @return */ protected NSArray nextBatch() { _start += _batchSize; _currentBatch = null; if (refreshEditingContext()==true) _ec = null; return currentBatch(); } public boolean hasNext() { if (_start + _batchPosition >= _rowCount) return false; return true; } public Object next() { Object eo = null; NSArray batch = currentBatch(); if (_batchPosition == batch.size()) { batch = nextBatch(); } if (batch != null) { eo = batch.get(_batchPosition); _batchPosition++ ; } return eo; } public void setRefreshEditingContext(boolean refresh) { _refreshEditingContext = refresh; } public boolean refreshEditingContext() { return _refreshEditingContext; } protected class EnterpriseObjectPrimaryKeyIterator implements Iterator { public boolean hasNext() { return IterableBatchEnterpriseObjects.this.hasNext(); } public Object next() { return IterableBatchEnterpriseObjects.this.next(); } public void remove() { throw new UnsupportedOperationException(); } } public Iterator<Object> iterator() { return new EnterpriseObjectPrimaryKeyIterator(); } } > On 10 Mar 2016, at 10:51, Daniele Corti <ilde...@gmail.com> wrote: > > Hi, > I have a question, about performance while working with LongRequest and many > EO. > > Here's the situation: I've prepared a class that extends > ERXLongResponseTask.DefaultImplementation. > In this class, I operate a database migration, over 10000 record. > Each of them has, at least, 50/60 objects releated. From them, I create > others objects, for a total of 60 new objects for each of the starting 10000 > rows. > > The procedure works fine, but, I experience a difference in speed during the > procedure. At first, 300-400 objects are processed in few seconds, then the > procedure slow down until, from 5000, it processes about 7/8 objects in 5 > seconds. > > The procedure is very simple: > 1. Fetch all objects in a NSArray > 2. Manipulate each object in a for loop, fetching related objects and > creating other objects in every iteration. > > I use just one EOEditingContext, so, I think the slowness begin when it > became really full of elements. > > I would like to know, if there is a way to "clean up" the manipulated objects > from the EC, or if a different approach is preferred. > > One last thing: it is good to use a NSArray of 1000 object in the for loop to > do this? I ask this because, I fetch all the objects and save them in memory > using EOObject.fetchAllObjects(EC) method from the class. > > Thanks in advance! > Daniele C. > _______________________________________________ > Do not post admin requests to the list. They will be ignored. > Webobjects-dev mailing list (Webobjects-dev@lists.apple.com) > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/webobjects-dev/mark%40wardle.org > > This email sent to m...@wardle.org _______________________________________________ Do not post admin requests to the list. They will be ignored. Webobjects-dev mailing list (Webobjects-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com