Open tomas1885 opened 1 year ago
/cc @evanchooly (kotlin,mongodb), @geoand (kotlin), @loicmathieu (mongodb)
@tomas1885 thanks a lot for reporting.
It would be super useful to us if you either:
cc @cescoffier @franz1981
I tried using the AsyncProfiler but I don't think this is the profile you're looking for, do you have any specific modes (profiler flags) you want me to use? Because providing a sample app would require filling a local MongoDB with lot's of data
If the difference in the two styles is so large,I would assume that a simple CPU profile would show it (and I am pretty sure a memory profile would also show huge allocations of Mutiny types).
That said, @franz1981 is the expert at async-profiler settings :)
profiling.zip Here's a Zip containing the profile html (I followed the instructions) of the reactive and blocking calls accordingly, If you want it in a different format please let me know
Got a couple of questions:
I suppose it is using macOS but should still able to observer the issue, correct?
I did add these JVM args, I also didn't see much valuable information there, so I took the time to write a simple reproducer. Attached here as a zip file, there are 3 endpoint, one for blocking, one for reactive and another one with the hacky workaround. You can clearly see the issue. mongoreproducer.zip
Thanks a lot, I'll have when I can.
(Adding @jponge)
Thanks for this report. The mongo facade was implemented a very long time ago (before we had mutiny, actually). Many improvements can be done, and I think you found one. Using emitOn
and using a trampoline would provide much better performances.
WDYT @jponge ?
Perhaps ContextAwareScheduler could be used to simplify pushing back execution on the correct Vert.x duplicated context
Ah my bad, this doesn't require a scheduler 🤦
FYI, for now, as a workaround replace aggregate and find calls with something like this:
var collection =db.unwrap.getCollection(PayoutsMongoRepository.COLLECTION); Context context = Vertx.currentContext(); if (context != null) { return Multi.createBy().replaying() .ofMulti(Multi.createFrom().publisher(AdaptersToFlow.publisher(collection.aggregate(pipeline,clazz)))) .emitOn(cmd->context.runOnContext(x->cmd.run())); } else { return Multi.createFrom().publisher(AdaptersToFlow.publisher(collection.aggregate(pipeline,clazz))); }
This doesn't seem to impact the performance and the item emission still happens on the same calling Vertx Context
Describe the bug
When using ReactiveMongoClient for getting large result sets there's a huge performance penalty (orders of magnitude) compared to using the blocking client.
The issue stems from the usage of
io.quarkus.mongodb.impl.Wrappers#toMulti, since it executes each
onItem` on the current Vertx context if possible.The difference for our use case is 2s vs 28s. I understand the need to emit each item on the calling Vertx context, we need to find a different way as the overhead is just too high. Simple using
AdaptersToFlow.publisher
without the call to vertx results in low latency but the item is not emitted on the calling Vertx context. The only way I found to be able to keep the item emitting on the Vertx Context without suffering from the performance penalty is to useAdaptersToFlow.publisher
and wrap it in a replying Multi with emitOn either aMutinyHelper.executor(currentContext)
or simplyemitOn(cmd->ctx.runOnContext(cmd))
. I'm not sure if there are any side effects and there might be better ways of solving this issue, but for now we're stuck on using the underlaying MongoClient (unwrap) with this custom solution.Any help would be appreciated
Expected behavior
ReactiveMongoClient performance should be up par with the blocking client or with using the Reactive Mongo driver from mongodb.
Actual behavior
The performance for large result set is worse by orders of magnitude.
How to Reproduce?
Query a large collection with large result set.
Output of
uname -a
orver
Darwin Kernel Version 22.6.0: Fri Sep 15 13:41:28 PDT 2023; root:xnu-8796.141.3.700.8~1/RELEASE_ARM64_T6020 arm64
Output of
java -version
openjdk version "17.0.7" 2023-04-18
GraalVM version (if different from Java)
No response
Quarkus version or git rev
3.3.3
Build tool (ie. output of
mvnw --version
orgradlew --version
)Build time: 2023-08-17 07:06:47 UTC Revision: 8afbf24b469158b714b36e84c6f4d4976c86fcd5 Kotlin: 1.9.0 Groovy: 3.0.17 Ant: Apache Ant(TM) version 1.10.13 compiled on January 4 2023 JVM: 17.0.7 (Eclipse Adoptium 17.0.7+7) OS: Mac OS X 13.6 aarch64
Additional information
No response