4 Replies Latest reply on Feb 14, 2014 2:18 AM by Dragos Sinca

    Executing process instances in parallel on a thread pool

    Dragos Sinca Newbie

      Hello.

       

      I set up a benchmark to measure the performance of the jBPM engine (6.0.0), trying to execute 100/1000/10000 process instances (just mock-ups, no code behind invoked items).

      The engine seems to be really fast, but I find out that session.startProcess() calls are synchronous; furthermore, even if I set up more threads to start process instances, the engine will still execute each process sequentially, on a single thread.

       

      I tried to set up the executor pool size (System.setProperty("org.kie.executor.pool.size", "10")) but nothing seems to change, and I may be going the wrong way around this...

      I need to illustrate that the throughput(#proces instances executed per second) increases when using parallel execution on a thread pool.

       

      What would be the proper way to set this up? I assume the engine can run on more than one thread, although I couldn't find any example on that...

      Dragos

        • 1. Re: Executing process instances in parallel on a thread pool
          Maciej Swiderski Master

          you should use different strategy for runtime manager - by default it's singleton as you noticed it will synchronize on the session to execute in sequence. Try using per request or per process instance strategy for runtime manager and you should see a gain in performance.

           

          HTH

          1 of 1 people found this helpful
          • 2. Re: Executing process instances in parallel on a thread pool
            Dragos Sinca Newbie

            That did the trick - I was able to get some interesting results using the default H2 database.

            However, when using Oracle persistence it runs into a deadlock - stack trace below.

             

            I'm using 11g XE version, with Oracle10gDialect Hibernate dialect configured in persistence.xml.

             

            Do I need to set any persistence parameter for this?

            Anything in particular when using Oracle database?

             

            Thank you

            Dragos

             

            ERROR: ORA-00060: deadlock detected while waiting for resource

             

            bitronix.tm.internal.BitronixRollbackException: RuntimeException thrown during beforeCompletion cycle caused transaction rollback

              at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:241)

              at bitronix.tm.BitronixTransactionManager.commit(BitronixTransactionManager.java:143)

              at bpm.poc.elster.BenchmarkProcessExecutor.run(BenchmarkProcessExecutor.java:104)

              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

              at java.lang.Thread.run(Thread.java:744)

            Caused by: javax.persistence.PersistenceException: org.hibernate.exception.LockAcquisitionException: could not execute statement

              at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)

              at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)

              at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1316)

              at org.hibernate.ejb.AbstractEntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1510)

              at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:117)

              at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)

              at bitronix.tm.BitronixTransaction.fireBeforeCompletionEvent(BitronixTransaction.java:532)

              at bitronix.tm.BitronixTransaction.commit(BitronixTransaction.java:235)

              ... 5 more

            Caused by: org.hibernate.exception.LockAcquisitionException: could not execute statement

              at org.hibernate.dialect.Oracle8iDialect$2.convert(Oracle8iDialect.java:449)

              at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)

              at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)

              at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)

              at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:136)

              at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3336)

              at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3536)

              at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:100)

              at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)

              at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)

              at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:280)

              at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:328)

              at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)

              at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1233)

              at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:403)

              at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:112)

              ... 8 more

            Caused by: java.sql.SQLException: ORA-00060: deadlock detected while waiting for resource

            ...

            • 3. Re: Executing process instances in parallel on a thread pool
              Maciej Swiderski Master

              you need to add following index for oracle:

               

              CREATE INDEX IDX_EVENTTYPES ON EVENTTYPES (INSTANCEID);

               

              and what do you mean by interesting results? Good or bad?

               

              HTH

              • 4. Re: Executing process instances in parallel on a thread pool
                Dragos Sinca Newbie

                Thank you, Macej!

                Once I ran that query and created the index you mentioned, i was able to run my test on Oracle too.

                 

                The results are good enough, they can probably be better, but that's all I could do at this point.

                 

                Consider this simple parallel process:

                PerformanceTest.PT3.png

                 

                I find that when executing the test on a single thread on my machine (Intel i3, 2 physical cores + 2 logical cores, 8GB RAM):

                1. RuntimeEngine processEngine = runtimeManager.getRuntimeEngine(ProcessInstanceIdContext.get()); - this call takes about 25-30ms, calling it for every process instance increases the average execution time a bit (was not needed for singleton manager)

                2. the actual execution takes a lot less - on a process event listener registered on each session, time between beforeProcessStarted and afterProcessCompleted is also aound 30ms

                3. takes another 20ms between afterProcessCompleted and the completion of processSession.startProcess - i guess it has to do with the persistence

                Overall, the execution duration averages around 80-90ms, and the throughput is around 40.000 instances/hour.

                 

                When running it on 10 parallel threads though, the average duration of a single execution goes up to 200-300ms (due to threads synchronization probably), but the throughput goes up around 100.000 instances/hour.

                 

                I think I could improve on these results, I'm just getting familiar with jBPM, so my test may not do things the best way, but they are good enough anyway for our purpose.

                And with a better machine, the results will probably get much better too.

                 

                Thank you again for your support, i couldn't have done without it.

                Dragos