I am trying a simple performance test of Activiti engine (5.20).
I created a simple process with four tasks-one task sets up some variables, and invokes a subprocess. The subprocess has 3 tasks-one task creates a random variable, and a gateway uses the value to decide upon one of two branches, each of which has one task, and ends the process.
I am using Postgres for the DB, and run the test on a Centos 7 machine with 4 cores, 8 GB RAM.
I created a driver program, which listens to an HTTP request (using Spark java), and uses the Activiti API to create an instance, and executes it. I am creating one instance of the engine initially.
In my testing, I found that the engine cannot scale beyond 50 concurrent threads. At 1-10 threads, it works fine. At 50 threads, I get errors almost half the time, and at larger number of threads, it just gets worse.
I did not get the impression that this is normal, and so wanted to understand if I am doing something wrong? Or is this to be expected?
50 concurrent threads to start process instance on one server seems a little high. What is your target process creation throughput? Starting a process instance is really fast in Activiti and is done in sub seconds! There are few nice write ups available at
Is your test just starting processes or is it taking a process all the way to its completion like it is done in the above mentioned blog posts?
Also, the performance depends on a lot of factors in your engine configuration such as
I do not understand the difference between starting a process, and taking it to completion. Once started, it will go to completion.
BTW, I do not have events, history, or async job executor enabled, and the standard Type 4 driver for PSQL.
The scenario is a thread starts a process, and returns when the process is complete. There are a configurable number of threads running at a time. It worked fine for 10 threads, but started acting up at 50, and got worse as the number of threads increases. I am using JMeter to drive the tests, and a tiny Sparkjava front end that receives requests from JMeter, and in response, starts a process. The Activiti engine is running in a standalone jar with no additional components. The tasks are all pure Java (noscripting).
Thanks for posting the diagram and that is all synchronous end-2-end. When you mentioned that you have four Tasks, I thought they are User Tasks! Hence I asked the question whether you are completing those tasks as part of your testing!
When you configure Activiti engine, are you configuring a connection pool or using the default MyBatis connection pool settings. By default the max active connections is set to 10 (check here for more configuration options Activiti User Guide). DB connections could be the blocker here, I can only guess without seeing the actual configuration!
I upped the connection pool size to 50, but got no improvement.
Basically, I am using JMeter to manage the load. JMeter makes HTTP requests to a Sparkjava HTTP listener, which creates a process instance, and returns when the process completes. Since the process does have any wait states, it returns (or should return) immediately. The errors I get are from Sparkjava server itself--500 Internal Server Error--even before it gets to creating a process instance. A simple Sparkjava app which just returns a fixed string for each request was also tested, and it scaled easily up to 10000 concurrent requests without issues. So this implies that the Activiti engine is consuming some resources that prevent Sparkjava from even responding.
I have also looked at Postgres, and that seems to be under no undue stress, and there are no locks being held in the DB.
There is no stack trace. The error is in the HTTP response (HTTP code 500).
The code to initialize the process instance is below:
RepositoryService repositoryService = processEngine.getRepositoryService();
RuntimeService runtimeService = processEngine.getRuntimeService();
IdentityService identityService = processEngine.getIdentityService();
TaskService taskService = processEngine.getTaskService();
Map<String, Object> variableMap = new HashMap<String, Object>();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processName, variableMap);