Upgrade
Sign In : Sign Up : Blog : Search: Language : Help :
This website is now frozen, please migrate your content to BotLibre.com or BotLibre.biz
Java Persistence Performance

Bulk inserts cause OOM even if done in batches

by pranahata posted Nov 26 2014, 23:38

We are using EL with JTA on glassfish

We are trying to insert about 1M records

At the moment, we are using a @Stateless ejb with BEAN managed tx and we are doing 10K inserts per tx

something like

@TransactionManagement(TransactionManagementType.BEAN)
@Slf4j
public class LandgateSyncBatchServiceImpl implements FeatureProcessor, LandgateSyncBatchService {

    @Inject
    @Yam
    private EntityManager em;

    @Inject
    private UserTransaction tx;


while (...) {
  tx.begin();
  10K times em.persist(entity);
  tx.commit();
  em.clear();
}

We are getting OOM errors and we can see that all entities touched by persist are retained by the entity manager in RepeatableUnitOfWork objects. looks like one per transaction. When profiling, we see the 300K objects we have inserted so far still in memory

We have set the entity as

@Cacheable(false)
@org.eclipse.persistence.annotations.Cache(size = 0, isolation = CacheIsolationType.ISOLATED, type = CacheType.NONE)

And we have also tried adding

em.getEntityManagerFactory().getCache().evict(entity.getClass());

after clear

Still, looks like all entities are retained in L1 cache even if the tx where they were involved has finished and clear has been called.

How can we make the entity manager "forget" entities that were part of a tx that has already been commited and free up memory


by jamesssss posted Nov 27 2014, 5:45
The root of your problem is that something is holding onto the old EntityManagers. After the end of the transaction the container should be releasing references to them and they should be free to garbage collect, so it should not matter what they reference.

Ensure that nothing in your app references any of the entity objects, as they can hold a reference to their entity manager and prevent gc. Also what is the @Yam annotation, check that it is not holding a reference. Try using a memory profiler to determine what is holding onto the objects.

Your em.clear() after the commit will do nothing, as for a JTA managed EntityManager you will get a new EntityManager after the end of the transaction, so calling em.clear() after commit will only create a new EntityManager.

You can clear the EntityManager before the commit by first calling flush.
i.e.
em.flush();
em.clear();
em.commit();

That should resolve your issue, but you should find the root of what is holding onto your EntityManagers.

Thumbs up: 0, thumbs down: 0, stars: 0.0
Views: 1741, today: 2, week: 3, month: 15

by pranahata posted Dec 13 2014, 21:14
James,

Thank you for your help.

It turned out to be a a really interesting problem.

We had a detached entity called Locality.

As part of the transactions we were doing something like:

xxxEntity.setLocality(theDetachedLocality)

It turns out to be that whenever we invoked this method, theDetachedLocality entity keep a reference to the xxxEntity in its ChangeTracking attributes (added to locality via change weaving), therefore all our xxxEntity objects (1 Million) stayed in memory.

The funny thing is that xxxEntity.locality was a uni directional @ManyToOne so i had never thought that by doing xxxEntity.setLocality(theDetachedLocality) any of the ChangeTracking attributes of theDetachedLocality would ever keep track of changes on the xxxEntity but it dead

we found it analyzing a heap dump

Just out of interest, do you know why EL does this?

Thanks again for your help.

Updated: Dec 13 2014, 21:18
Thumbs up: 0, thumbs down: 0, stars: 0.0
Views: 1659, today: 3, week: 10, month: 24

by jamesssss posted Dec 14 2014, 17:18
I would assume you have a @OneToMany in the Locality that is holding the reference and changes. I can't see it recording changes otherwise. What attribute in the ObjectChangeSet is it under?

If it is still tracking changes, then it doesn't know it is detached. You may want to clone it or copy it to force it to be detached. (em.detach(), doesn't really do anything).

Thumbs up: 0, thumbs down: 0, stars: 0.0
Views: 1667, today: 4, week: 6, month: 15

Id: 326049
Tags: memory, glassfish, jta, jpa, eclipselink
Posted: Nov 26 2014, 23:38
Updated: Nov 27 2014, 5:45
Replies: 3
Views: 1933, today: 2, week: 5, month: 13
I'm sure
Flag graphic as offensive, or in violation of site rules