On a few projects, I've seen some issues with Ditto where it seems to be slowing the site down a bit.
My theory is that this is because Ditto is deferring the execution of the processors (i.e., to lazy load the values), and that it's not memoizing the result. The thought is that it's running the same code multiple times.
For example, I use Ditto to map out widgets for the page. When I render the widgets, that's one iteration over the collection. When I extract data from the widgets (e.g., to construct some schema.org for the page), that's another iteration over the collection. There may be additional iterations too.
To get around this, my quick hack is to serialize and then deserialize the object mapped by Ditto, which seems to remove the Ditto magic so they're simple objects. It's not an ideal solution, as it causes lots of other weirdness (e.g., private members don't serialize by default, so some things have to be reengineered).
Is this a known issue? Is there some way to get around it?
My theory is that Ditto is subclassing my classes with dynamically generated classes to allow for the lazy loading (I would guess either out of necessity or as a form of optimization that is backfiring); is that the case?
My theory is that this is because Ditto is deferring the execution of the processors (i.e., to lazy load the values), and that it's not memoizing the result.
Do you mean that you think the lazy properties are reevaluating the property value on each request?
I'm afraid not.
The LazyInterceptor injected into your dynamic proxy class that intercepts the get/set properties stores a Dictionary<string, Lazy<object>> for getters which runs the process only once per property per class instance.
You mean the proxy class type , not the individual instances yeah?
When an instance of a proxy class is first created by the ProxyFactory the type is memoized also so the dynamic code generation is no longer required. Subsequent instances are constructed from that known type.
(I'm back from vacation, hence my delay in replying)...
I don't think the repeated execution is related to the dynamically generated proxy classes, (which are used when you explicit configure Ditto for lazy-loading properties).
I suspect it happens due to how IEnumerable<T> works with deferred execution. As in it will only compute the enumerable when the result is being used. It's possible that Ditto (or its Processors) are doing this.
I had noticed this on a couple of websites I'd done with Ditto, but I couldn't pinpoint it exactly. Strangely I've had Ditto websites where it doesn't happen.
Deferred Execution Causing Repeat Execution?
On a few projects, I've seen some issues with Ditto where it seems to be slowing the site down a bit.
My theory is that this is because Ditto is deferring the execution of the processors (i.e., to lazy load the values), and that it's not memoizing the result. The thought is that it's running the same code multiple times.
For example, I use Ditto to map out widgets for the page. When I render the widgets, that's one iteration over the collection. When I extract data from the widgets (e.g., to construct some schema.org for the page), that's another iteration over the collection. There may be additional iterations too.
To get around this, my quick hack is to serialize and then deserialize the object mapped by Ditto, which seems to remove the Ditto magic so they're simple objects. It's not an ideal solution, as it causes lots of other weirdness (e.g., private members don't serialize by default, so some things have to be reengineered).
Is this a known issue? Is there some way to get around it?
My theory is that Ditto is subclassing my classes with dynamically generated classes to allow for the lazy loading (I would guess either out of necessity or as a form of optimization that is backfiring); is that the case?
Do you mean that you think the lazy properties are reevaluating the property value on each request?
I'm afraid not.
The LazyInterceptor injected into your dynamic proxy class that intercepts the get/set properties stores a
Dictionary<string, Lazy<object>>
for getters which runs the process only once per property per class instance.Hi James,
Thanks for the insight. That helps. It at least lets me know what the issue isn't. I'll have to keep hunting.
Do you happen to remember how classes are instantiated and whether or not they're memoized (just as properties are memoized)?
You mean the proxy class type , not the individual instances yeah?
When an instance of a proxy class is first created by the ProxyFactory the type is memoized also so the dynamic code generation is no longer required. Subsequent instances are constructed from that known type.
Hi Nicholas,
(I'm back from vacation, hence my delay in replying)...
I don't think the repeated execution is related to the dynamically generated proxy classes, (which are used when you explicit configure Ditto for lazy-loading properties).
I suspect it happens due to how
IEnumerable<T>
works with deferred execution. As in it will only compute the enumerable when the result is being used. It's possible that Ditto (or its Processors) are doing this.I had noticed this on a couple of websites I'd done with Ditto, but I couldn't pinpoint it exactly. Strangely I've had Ditto websites where it doesn't happen.
Sorry I don't have a concrete answer for this.
Cheers,
- Lee
Yeah, I've definitely seen a few instances of some Ditto processors having deferred execution issues due to how
IEnumerable<T>
is managed. In fact, I created anUndeferAttribute
Ditto processor to deal with this in some specific cases: https://github.com/rhythmagency/rhythm.umbraco.ditto/blob/master/src/Rhythm.Umbraco.Ditto/Processors/UndeferCollectionAttribute.csMaybe I'll poke around the Ditto source code one of these days to see if I can find some places to toss
.ToArray()
or.ToList()
on.Thanks for your insights James and Lee.
FYI, I started a pull request for some issues I noticed: https://github.com/umco/umbraco-ditto/pull/243
Haven't tested the impact, but has some good potential to fix some issues I've seen.
is working on a reply...