You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by "Nils Verheyen (JIRA)" <ji...@apache.org> on 2012/12/03 12:17:58 UTC
[jira] [Created] (CAY-1776) OutOfMemory during lifecycle events
Nils Verheyen created CAY-1776:
----------------------------------
Summary: OutOfMemory during lifecycle events
Key: CAY-1776
URL: https://issues.apache.org/jira/browse/CAY-1776
Project: Cayenne
Issue Type: Improvement
Components: Lifecycle Extensions
Affects Versions: 3.1B1, 3.0.2
Environment: Linux x64, Mac OS X Lion
Reporter: Nils Verheyen
Priority: Minor
Inside EventManager.java in Cayenne 3.0.2 and DefaultEventManager in Cayenne 3.1 there is the inner class Dispatch with the following code:
synchronized (eventQueue) {
eventQueue.add(new InvocationDispatch(
eventArgument,
subject,
invocation));
eventQueue.notifyAll();
}
Inside my code a event listener is added once, but inside the eventQueue multiple InvocationDispatch objects are created and never thrown away. When persisting thousands of objects the eventQueue is filled up leading to OutOfMemory exceptions.
Regards,
Nils
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Commented] (CAY-1776) OutOfMemory during lifecycle events
Posted by "Nils Verheyen (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/CAY-1776?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13510345#comment-13510345 ]
Nils Verheyen commented on CAY-1776:
------------------------------------
Hi Andrus, the application is quite complicated so i hope the following explanation is enough.
Inside the application some image processing is performed inside threads. I'm using a fixed thread pool of a maximum of 8 threads besides the main thread (Executors.newFixedThreadPool(8)). Each thread (main thread and the 8 worker threads) contains one ObjectContext created when an instance is initialized. This is done via DataContext.createDataContext();. Only in the main thread one single listener is added to the object context.
void addFlickrPhotoPostSizePersistListener(Object listener, String methodName) {
LifecycleCallbackRegistry registry = objectContext.getEntityResolver().getCallbackRegistry();
registry.addListener(LifecycleEvent.POST_PERSIST, PhotoSize.class, listener, methodName);
}
The method is called only once! The ObjectContext on the main thread is created during application launch and exists until the application is shut down.
Inside one of the 8 worker threads 256 Objects are created through one ObjectContext at max and persisted to the database (mysql at the moment). After a worker is done the context is not used anymore.
Inside the main thread thousands of Photo, PhotoSize and ProcessingJob objects are created and persisted to db.
At the moment I use Cayennes stable release 3.0.2. I'll try the different approaches beginning with #1.
I hope the explanation is enough, otherwise I try to extract some code.
Thank for the help,
Nils
> OutOfMemory during lifecycle events
> -----------------------------------
>
> Key: CAY-1776
> URL: https://issues.apache.org/jira/browse/CAY-1776
> Project: Cayenne
> Issue Type: Improvement
> Components: Lifecycle Extensions
> Affects Versions: 3.0.2, 3.1B1
> Environment: Linux x64, Mac OS X Lion
> Reporter: Nils Verheyen
> Priority: Minor
>
> Inside EventManager.java in Cayenne 3.0.2 and DefaultEventManager in Cayenne 3.1 there is the inner class Dispatch with the following code:
> synchronized (eventQueue) {
> eventQueue.add(new InvocationDispatch(
> eventArgument,
> subject,
> invocation));
> eventQueue.notifyAll();
> }
> Inside my code a event listener is added once, but inside the eventQueue multiple InvocationDispatch objects are created and never thrown away. When persisting thousands of objects the eventQueue is filled up leading to OutOfMemory exceptions.
> Regards,
> Nils
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Comment Edited] (CAY-1776) OutOfMemory during lifecycle
events
Posted by "Nils Verheyen (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/CAY-1776?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13510345#comment-13510345 ]
Nils Verheyen edited comment on CAY-1776 at 12/5/12 8:02 AM:
-------------------------------------------------------------
Hi Andrus, the application is quite complicated so i hope the following explanation is enough.
First of all, there is no special EventManager or configuration.
Inside the application some image processing is performed inside threads. I'm using a fixed thread pool of a maximum of 8 threads besides the main thread (Executors.newFixedThreadPool(8)). Each thread (main thread and the 8 worker threads) contains one ObjectContext created when an instance is initialized. This is done via DataContext.createDataContext();. Only in the main thread one single listener is added to the object context.
void addFlickrPhotoPostSizePersistListener(Object listener, String methodName) {
LifecycleCallbackRegistry registry = objectContext.getEntityResolver().getCallbackRegistry();
registry.addListener(LifecycleEvent.POST_PERSIST, PhotoSize.class, listener, methodName);
}
The method is called only once! The ObjectContext on the main thread is created during application launch and exists until the application is shut down.
Inside one of the 8 worker threads 256 Objects are created through one ObjectContext at max and persisted to the database (mysql at the moment). After a worker is done the context is not used anymore.
Inside the main thread thousands of Photo, PhotoSize and ProcessingJob objects are created and persisted to db.
At the moment I use Cayennes stable release 3.0.2. I'll try the different approaches beginning with #1.
I hope the explanation is enough, otherwise I try to extract some code.
Thank for the help,
Nils
was (Author: ude-nils):
Hi Andrus, the application is quite complicated so i hope the following explanation is enough.
Inside the application some image processing is performed inside threads. I'm using a fixed thread pool of a maximum of 8 threads besides the main thread (Executors.newFixedThreadPool(8)). Each thread (main thread and the 8 worker threads) contains one ObjectContext created when an instance is initialized. This is done via DataContext.createDataContext();. Only in the main thread one single listener is added to the object context.
void addFlickrPhotoPostSizePersistListener(Object listener, String methodName) {
LifecycleCallbackRegistry registry = objectContext.getEntityResolver().getCallbackRegistry();
registry.addListener(LifecycleEvent.POST_PERSIST, PhotoSize.class, listener, methodName);
}
The method is called only once! The ObjectContext on the main thread is created during application launch and exists until the application is shut down.
Inside one of the 8 worker threads 256 Objects are created through one ObjectContext at max and persisted to the database (mysql at the moment). After a worker is done the context is not used anymore.
Inside the main thread thousands of Photo, PhotoSize and ProcessingJob objects are created and persisted to db.
At the moment I use Cayennes stable release 3.0.2. I'll try the different approaches beginning with #1.
I hope the explanation is enough, otherwise I try to extract some code.
Thank for the help,
Nils
> OutOfMemory during lifecycle events
> -----------------------------------
>
> Key: CAY-1776
> URL: https://issues.apache.org/jira/browse/CAY-1776
> Project: Cayenne
> Issue Type: Improvement
> Components: Lifecycle Extensions
> Affects Versions: 3.0.2, 3.1B1
> Environment: Linux x64, Mac OS X Lion
> Reporter: Nils Verheyen
> Priority: Minor
>
> Inside EventManager.java in Cayenne 3.0.2 and DefaultEventManager in Cayenne 3.1 there is the inner class Dispatch with the following code:
> synchronized (eventQueue) {
> eventQueue.add(new InvocationDispatch(
> eventArgument,
> subject,
> invocation));
> eventQueue.notifyAll();
> }
> Inside my code a event listener is added once, but inside the eventQueue multiple InvocationDispatch objects are created and never thrown away. When persisting thousands of objects the eventQueue is filled up leading to OutOfMemory exceptions.
> Regards,
> Nils
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira
[jira] [Commented] (CAY-1776) OutOfMemory during lifecycle events
Posted by "Andrus Adamchik (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/CAY-1776?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13509944#comment-13509944 ]
Andrus Adamchik commented on CAY-1776:
--------------------------------------
Hi Nils, Thanks for the Jira.. Normally events added to the queue, are thereafter removed from the queue by DispatchThreads and dispatched to the listeners (DispatchThread.run()). "notifyAll" in your code example serves the the purpose of waking up dispatch threads and start processing the queue...
So either you have a special EventManager configuration that prevents this from happening (could you elaborate on "Inside my code a event listener is added once,"? do you have a custom listener?), or indeed your app is so active that dispatch threads compete with commit threads and the queue grows faster than it can be drained.
If the later is the case, (meaning you have a lot of DataContexts, all committing in parallel), there are a few ways you can approach a solution:
1. (Under 3.1) Set "cayenne.server.contexts_sync_strategy" (aka Constants.SERVER_CONTEXTS_SYNC_PROPERTY) to "false" (see "Changing Properties of Existing Services" here: http://cayenne.apache.org/docs/3.1/cayenne-guide/customizing-cayenne-runtime.html on how to set Cayenne properties). This will not disable the event dispatch, but it will prevent peer contexts from listening to each other's events, so queue will be drained much faster.
2. (3.0 and 3.1) You can increase the number of dispatch threads. However this may still hit the wall under higher load.
3. If nothing works, provide your own EventManager implementation that does nothing.
I'd go with #1. It explicitly acknowledges that synchronizing the state of N peer DataContexts does not scale to large values of N. So the solution is not a hack, but a conscious design decision.
I;ll be curious to hear if the suggestions above fixed your issue (and please confirm, do you actually have many parallel contexts committing?)
> OutOfMemory during lifecycle events
> -----------------------------------
>
> Key: CAY-1776
> URL: https://issues.apache.org/jira/browse/CAY-1776
> Project: Cayenne
> Issue Type: Improvement
> Components: Lifecycle Extensions
> Affects Versions: 3.0.2, 3.1B1
> Environment: Linux x64, Mac OS X Lion
> Reporter: Nils Verheyen
> Priority: Minor
>
> Inside EventManager.java in Cayenne 3.0.2 and DefaultEventManager in Cayenne 3.1 there is the inner class Dispatch with the following code:
> synchronized (eventQueue) {
> eventQueue.add(new InvocationDispatch(
> eventArgument,
> subject,
> invocation));
> eventQueue.notifyAll();
> }
> Inside my code a event listener is added once, but inside the eventQueue multiple InvocationDispatch objects are created and never thrown away. When persisting thousands of objects the eventQueue is filled up leading to OutOfMemory exceptions.
> Regards,
> Nils
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira