-
Notifications
You must be signed in to change notification settings - Fork 473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GetEdmModel Performance Issue #2743
Comments
20 seconds definitely sounds excessive. Is the |
So this actually gets called twice during startup as there are different groups of APIs (this is using Sitecore Commerce, not something I can control). But it still doesn't make sense why it takes so long to run the command in v7 vs v6, other than the new nested complex types logic exists, which does this recursive call. |
@caviyacht by any chance, would it be possible to share the model classes that were used to generate the |
@habbes , unfortunately I cannot share them as most are not mine (Sitecore Commerce) and the rest are inherited on those. Also, there are ~1200 of them that make up the model (out-of-the-box + custom). Below are some of the core classes that the system uses, and most inherit from these.
This makes up around ~703 of the objects added to the Edm model. The other ~500 are just normal classes that do not inherit from these, but could have these as nested properties. Let me know if there is something else I can try to provide. |
Hi @caviyacht Thanks for sharing the additional information. I've gone through the implementations of the methods in the call stack you shared to try and understand what the issue could be, and I have the following follow-up questions:
I think at first glance caching the results of The other potential issue I've observed is that we can visit the same type multiple times. There's code to ensure that we don't process the same type twice if it occurs in the same subgraph to avoid infinite recursions, but there's not code to ensure we don't visit the same type more than once in separate subgraphs. And looking at the code, this appears to be intentional. Let me elaborate more in the next comment. |
Let's assume we have a model based on the following classes: public class EntityA
{
public int Id { get; set; }
public EntityB EntityB { get; set; }
public ComplexA ComplexA { get; set; }
public ComplexB ComplexB { get; set; }
}
public class EntityB
{
public int Id { get; set; }
}
public class ComplexA
{
public ComplexB ComplexB { get; set; }
}
public class ComplexB
{
public EntityB EntityB { get; set; }
public ComplexA ComplexA { get; set; }
} Now the To make it concrete, let's consider the code will handle the different complex and navigation properties of The The The
And finally, we visit property
So, the final result will have, the following
We see that This means we can't simply cache the navigation properties on each complex type and add them to the result when we visit the type. We have to keep track of the path from the complex type to the navigation property. Then we visit the complex property we combine the path from the root entity to the current property with the path from the complex type to the navigation property. If we create a cache, we'd have to balance between storing too much and computing too much. For may have to use a hybrid of lists and linked list nodes to store the cached navigation properties as well as their paths. Each complex type will need an efficient cache of its navigation properties as well as those of its the nested complex properties, and it will need to prepend the nested properties to the property paths of its deeply nested navigation property. However, we go about this, we should be able to save the cost of looking up deeply nested complex property chains which don't have navigation properties (these will be efficient to cache since the results are empty). |
The cache idea in the previous comment may not be beneficial if your model has many complex types but no nesting of complex types. In such case it would probably even make things worse. I don't whether the issue you experience is due to deep nesting or just many complex types in a flat schema. For this reason, I propose we first try caching and optimizing the I don't have bandwidth to implement this at the moment so I can't provide an ETA. But once it's properly assigned in the backlog, we'll get to it. Alternatively, if you're in a position to contribute an optimization, we'll be happy to review your PR @caviyacht |
Very slow performance when calling
GetEdmModel()
, specifically in theApplyNavigationSourceConventions()
method. This was not a problem when using v6.0.0-alpha1 (pre-recursive complex support).Assemblies affected
Microsoft.AspetNetCore.OData, v7.6.3
Reproduce steps
I'm not sure how to reproduce the issue exactly, but this seems to be happening because of the nesting logic that was added. The same size that is being used is:
Expected result
The
GetEdmModel()
call takes less than 5s (or faster) vs taking 20s+.Actual result
The
GetEdmModel()
call is taking upwards of 20s to execute.Additional detail
Below shows the time spent in the
ApplyNavigationSourceConventions()
method.The text was updated successfully, but these errors were encountered: