Cannot send concurrent run messages

Hi there.

This is probably a crazy request, but here we go:

I’m working on a new feature for our automation framework to run multiple Gatling simulations at the same time. We already have some simulations that run multiple scenarios, but now we need support for running multiple simulations (which will have different feeders and protocols) at the same time.

Here’s a quick snippet (Groovy) of the proof of concept:

withPool(2) { pool →
Future googleResult = { gatling.drive(“GoogleSimulation”) }.callAsync()
Future redditResult = { gatling.drive(“RedditSimulation”) }.callAsync()

assert googleResult.get()
assert redditResult.get()
}

Basically, the call “gatling.drive(String)” maps to calling “Gatling.fromMap(mutable.Map, None)”. The result is the following ERROR message, then the RedditSimulation runs, and followed by the stack trace below.

16:48:48.026 [ERROR] i.g.c.c.Controller - Shouldn’t happen. Ignore message Run(io.zerocontribution.charge.gatling.simulations.RedditSimulation@5d78424c,redditsimulation,redditsimulation,Timings(None,None,Map())) while waiting for DataWriter to initialize

[RedditSimulation output…]

java.util.concurrent.ExecutionException: akka.pattern.AskTimeoutException: Timed out
at jsr166y.ForkJoinTask.get(ForkJoinTask.java:913)
at io.zerocontribution.charge.tests.GuiceSpec.Concurrent Gatling tests_closure1(GuiceSpec.groovy:52)
at groovyx.gpars.GParsPool.withExistingPool_closure1(GParsPool.groovy:171)
at groovyx.gpars.GParsPool.withExistingPool_closure1(GParsPool.groovy)
at groovy.lang.Closure.call(Closure.java:423)
at groovy.lang.Closure.call(Closure.java:417)
at groovyx.gpars.GParsPool.withExistingPool(GParsPool.groovy:170)
at groovyx.gpars.GParsPool.withPool(GParsPool.groovy:142)
at groovyx.gpars.GParsPool.withPool(GParsPool.groovy:118)
at io.zerocontribution.charge.tests.GuiceSpec.Concurrent Gatling tests(GuiceSpec.groovy:48)
Caused by: akka.pattern.AskTimeoutException: Timed out
at akka.pattern.PromiseActorRef$$anonfun$1.apply$mcV$sp(AskSupport.scala:334)
at akka.actor.Scheduler$$anon$11.run(Scheduler.scala:118)
at akka.actor.LightArrayRevolverScheduler$TaskHolder.run(Scheduler.scala:464)
at akka.actor.LightArrayRevolverScheduler$$anonfun$close$1.apply(Scheduler.scala:281)
at akka.actor.LightArrayRevolverScheduler$$anonfun$close$1.apply(Scheduler.scala:280)
at scala.collection.Iterator$class.foreach(Iterator.scala:727)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
at akka.actor.LightArrayRevolverScheduler.close(Scheduler.scala:279)
at akka.actor.ActorSystemImpl.stopScheduler(ActorSystem.scala:630)
at akka.actor.ActorSystemImpl$$anonfun$_start$1.apply$mcV$sp(ActorSystem.scala:582)
at akka.actor.ActorSystemImpl$$anonfun$_start$1.apply(ActorSystem.scala:582)
at akka.actor.ActorSystemImpl$$anonfun$_start$1.apply(ActorSystem.scala:582)
at akka.actor.ActorSystemImpl$$anon$3.run(ActorSystem.scala:596)
at akka.actor.ActorSystemImpl$TerminationCallbacks$$anonfun$run$1.runNext$1(ActorSystem.scala:750)
at akka.actor.ActorSystemImpl$TerminationCallbacks$$anonfun$run$1.apply$mcV$sp(ActorSystem.scala:753)
at akka.actor.ActorSystemImpl$TerminationCallbacks$$anonfun$run$1.apply(ActorSystem.scala:746)
at akka.actor.ActorSystemImpl$TerminationCallbacks$$anonfun$run$1.apply(ActorSystem.scala:746)
at akka.util.ReentrantGuard.withGuard(LockUtil.scala:15)
at akka.actor.ActorSystemImpl$TerminationCallbacks.run(ActorSystem.scala:746)
at akka.actor.ActorSystemImpl$$anonfun$terminationCallbacks$1.apply(ActorSystem.scala:593)
at akka.actor.ActorSystemImpl$$anonfun$terminationCallbacks$1.apply(ActorSystem.scala:593)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:67)
at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:82)
at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:59)
at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:59)
at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
at akka.dispatch.BatchingExecutor$Batch.run(BatchingExecutor.scala:58)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:39)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:385)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

Looks like this is a known issue given the ERROR log, but I’d like to see what it’d take to run multiple Gatling simulations at the same time from the same process. In the short-term, it looks like I’ll be forced to ship out the bundled Gatling package and then invoke it in subprocesses, then grab the outputs once they’re done?

CONFIDENTIAL COMMUNICATION:

This email may contain confidential or legally privileged material, and is for the sole use of the intended recipient. Use or distribution by an unintended recipient is prohibited, and may be a violation of law. If you believe that you received this email in error, please do not read, forward, print or copy this email or any attachments. Please delete the email and all attachments, and inform the sender that you have deleted the email and all attachments. Thank you.

The code of Gatling has singletons which makes it possible for now to have concurrent execution.
We are considering changing that, but it won’t happen before the 2.0 release.

cheers
Nicolas

Sorry, for clarification:

Do you mean it’s unlikely it will come before 2.0 stable (e.g. not until Gatling 3), or that it could come in a 2.0 snapshot? Any way I can help get rid of all the singletons, I’d love to.

We can try again to remove the singletons in 2.1, but IIRC, it created an implicit hell all over the place…
Anyway, can’t you just fork multiple JVMs?

Looks like that’s what I’ll have to do. I used to do this, but passing the amount of data the simulations need from the framework by system properties is pretty inelegant. Maybe I’ll just serialize it all to a temp JSON file. :slight_smile:

Yep, I guess that’s the best way to go for now… :slight_smile: