Replies: 3 comments 11 replies
-
Solution 1: resolve all messaging components during preparation phase for cachingDuring preparation phase, builders ( interface CompilableBuilder {
public function compile(ReferenceSearchService $referenceSearchService, ChannelResolver $channelResolver): void;
} After "compilation", builders should be locked for changes and immutable. class GatewayProxyBuilder implements InterceptedEndpoint, CompilableBuilder
{
//...
public function build(ReferenceSearchService $referenceSearchService, ChannelResolver $channelResolver) {
$interfaceToCall = $interfaceToCallRegistry->getFor($this->interfaceName, $this->methodName);
if ($this->isCompiled) {
return new Gateway(
$interfaceToCall,
new MethodCallToMessageConverter(
$interfaceToCall,
$this->methodArgumentConverters
),
$this->messageConverters,
new GatewayReplyConverter(
$referenceSearchService->get(ConversionService::REFERENCE_NAME),
$interfaceToCall,
$this->messageConverters,
),
$this->buildGatewayInternalHandler($interfaceToCall, $referenceSearchService, $channelResolver)
);
} else {
// ...
}
}
} This solution would help only on "Messaging system resolution" performance. |
Beta Was this translation helpful? Give feedback.
-
Solution 2: dump a messaging system into a containerContinuing on solution 1, we could think of the class GatewayProxyBuilder implements InterceptedEndpoint, CompilableBuilder
{
//...
public function build(ReferenceSearchService $referenceSearchService, ChannelResolver $channelResolver) {
$interfaceToCallReference = new InterfaceToCallReference($this->interfaceName, $this->methodName)
// All resolutions can be done during this phase
// And then dumped into "definitions"
return new Definition(Gateway::class, [
$interfaceToCallReference,
new Definition(MethodCallToMessageConverter::class, [
$interfaceToCallReference,
array_map($this->methodArgumentConverters, ($converter) => $converter->build())
]),
...
);
}
} With these definitions, we would be able to dump all messaging system components into an highly performant php container. With this solution, we would have:
A proof of concept is #223. |
Beta Was this translation helpful? Give feedback.
-
@jlabedo I would like to see the profiler results after latest changes on I've not yet invested much time into the POC, but I understood the idea. I wonder about what will be performance gains now with the above optimalizations. Is this something you can verify early or we need to wait for POC to be finished to see the benchmarks? |
Beta Was this translation helpful? Give feedback.
-
So let me present my thoughts on performance improvement.
Here is a screenshot of an xdebug profile of ecotone lite "PlaceOrder" benchmark in production, with 100 iterations to avoid autoloader impact, and opcache disabled. The bootstraping of the messaging system is 63%, the execution of the test case is 36% of the time. Fail fast is disabled, so some messaging components are also built during execution.
I see mainly three ways of improving performance
Messaging system resolution
I will take for example the gateway proxy builder that is one of the most time consuming component in the profile (36%).
Looking at the code, a lot of resolutions are taken during build: resolving gateway converters, resolve annotations, sort interceptors, add an interceptor for error channel. A lot of this could be resolved during preparation phase and be cached.
Opcache and messaging system serialization
In one of my previous tests, I tried to export the messaging system configuration as a php file instead of serializing it. The performance gain was more or less 50% with opcache enabled, which should be the case for http requests.
Lazy component creation
Some components are not lazy: for instance all gateways are created on each boot.
Beta Was this translation helpful? Give feedback.
All reactions