OrchardCMS / Orchard

Orchard is a free, open source, community-focused Content Management System built on the ASP.NET MVC platform.
https://orchardproject.net
BSD 3-Clause "New" or "Revised" License
2.38k stars 1.12k forks source link

Navigation performance problems. #4867

Open orchardbot opened 10 years ago

orchardbot commented 10 years ago

smilliken created: https://orchard.codeplex.com/workitem/21038

Without output caching enabled there are significant performance issues with the current Orchard navigation implementation.

Just adding a Menu widget to a layout causes a marked performance decrease. Adding individual menu items then causes more or less linear performance degradation.

To uncover this issue we were testing against the last stable orchard 1.7 release (1.7.3). Using visual studio load testing we produced the following results. We also performed the same tests against 1.8.1 with similar results.

Test machine configuration

Core i7-3740QM 2.7GHz 24.0 GB RAM

SAMSUNG 840 EVO SSD

Orchard configuration

Database installed locally Output caching feature is disables Default orchard theme

Out of the box install

There are 3 simple content pages in the test, and we are not parsing dependent requests. The tests are configured to run for 5 minutes at a constant rate with 16 users.

Orchard 1.7.3

Baseline performance 218 PPS

1 Nav 0 Menu item(s) 178 PPS (18.35% Decrease) 1 Nav 1 Menu Item(s) 171 PPS (21.56% Decrease) 1 Nav 2 Menu Item(s) 160 PPS (26.61% Decrease) 1 Nav 41 Menu Item(s) 72 PPS (66.74% Decrease)

Orchard 1.8.1

Baseline performance 191 PPS

1 Nav 0 Menu Item(s) 159 PPS (16.75% Decrease) 1 Nav 1 Menu Item(s) 152 PPS (20.42% Decrease) 1 Nav 2 Menu Item(s) 148 PPS (22.51% Decrease) 1 Nav 41 Menu Item(s) 68 PPS (64.40% Decrease)

As you can see from the results there is an initial hit, just enabling a menu, then we see a relatively linear performance decrease as we add menu items.

orchardbot commented 10 years ago

@sebastienros commented:

What kind of menu items are you using, content menu items or custom links ones?

Would you mind having the menu cached? Or is it currently dependent on some context (user, theme, culture, ...)

orchardbot commented 10 years ago

smilliken commented:

In the test we were using custom links.

orchardbot commented 10 years ago

smilliken commented:

Independent caching of the rendered menus would be a fine solution, provided that the cache keys are route aware to allow for menu item highlighting, etc.

orchardbot commented 9 years ago

@jeffolmstead commented:

Why don't you try out my module here: https://navigationcache.codeplex.com/ and let me know if it resolves things for you. We run it on all our websites and have had tremendous success (as have others who also utilize it).

Piedone commented 9 years ago

Those who experience such performance problems: isn't it because of Query Links and breadcrumbs? See: #3537.

jeffolmstead commented 9 years ago

@Piedone yes, for the most part navigationcache shines for those users who have query links and breadcrumbs. Simple menu hierarchies (i.e. 7 or 8 content items linked) don't see much improvement with the navigationcache module (though I think it is still worthwhile, I run it on all my client's regardless). Personally, the other thing I do is that I NEVER use the navigationcache module as a crutch. I don't load up every blog post into the navigational hierarchy just so I can use it in a breadcrumb as this will swamp the system on the "first hit". Instead, the navigation should only contain visible menu items that are needed in dropdowns but not simply breadcrumbs. The "breadcrumbs" you can emulate on the blog post pages by injecting a shape into the same zone where you would have a breadcrumb. This shape renders html that LOOKS like a breadcrumb without the overhead baggage of actually being a part of the navigation. I have examples if there are any users who are interested.

Piedone commented 9 years ago

Yes, please share your examples @jeffolmstead .

I think extensible breadcrumbs with some very efficient implementations as explained in the linked issue could fix most of the perf problems of menus (if you only use Custom Links).

jeffolmstead commented 9 years ago

I was thinking about this and trying to explain how I do things and I now realize this could be fully automated. I believe other users are like myself in that when you visit a blog post page you want to have your breadcrumb rendered something like:

Home > Blog Title > Blog Post Title

Traditionally to get that type of you would do something like this: 2015-06-11_9-48-48

Which of course causes everything to bog down as the number of blog posts grows. So, my current alternative is to not have the Query Link (as I am not using it for a dropdown menu anyway, just for the breadcrumb - if I were using it for a dropdown menu, would want the most recent 10 only anyway otherwise too much data). Instead of having the query link, I inject a shape right from the blog post into the "BeforeMain" - pick your favorite zone - that passes in the title of the current blog post and the title and link of the blog. It then just creates the html markup on it's own. This is a huge performance improvement just by doing this (which when combined with caching means you don't even notice a delay).

So what just hit me is that we could create a new Menu provider that only accepts one parameter, Content Type. Unlike a query though, it would be a non-rendering menu provider except for those instances where it is in a breadcrumb configuration AND on "page" where the primary content is of the same Content Type. It would then render the primary content "DisplayText" (normally Title) and put it in order with the existing buildup (i.e. Home > Blog Title > {Display Text}). This way, the menu provider stays dormant until it is called upon to fulfil a breadcrumb and we should end up staying really efficient due to the dramatically reduced number of query calls on the database.

Is the above thought process understandable? What are your thoughts?

Piedone commented 9 years ago

The issue is that how navigation currently works it needs the full menu tree to be built upfront. This means that unless you change specifically how breadcrumbs are constructed (see my suggestion under #3537) you can't do this from a menu provider unless we deeply change how menus are constructed - I think.

jeffolmstead commented 9 years ago

ok, I see what you mean. Yes the lifecycle is to build it and not analyze it in light of the current "page". So two possibilities:

  1. Use navigation cache and take the hit one time (that is really not one I would argue for, I would argue for using navigation cache module, but NOT to ever take a hit one time).
  2. Fix the usage of large queries by eliminating the need for them (though, to be honest, many users will likely still use them and not understand why things are slow - don't think that can be prevented, maybe warned against like this "Hey, did you know this query returns 300 items? Perhaps you should think of a different approach"

So what I do for my client's fully works but it is manual to inject a shape and construct the html so it matches the breadcrumb markup. This is not really a robust solution for Orchard in general. Here would be one concept that would work for "users like us" but may not be intuitive to a regular person first encountering it. We could expand the breadcrumb widget shape with one additional field called "Content Types to Extend" (and yes, this is sounding more like your generic solution). This way, the traditional navigation hierarchy is compiled and rendered but, when one of the content types to extend are hit, they just append onto the current navigation.

Ok, so that would solve the need for extending by content type BUT I fully agree with you, if we actually modify source to put in an Interface extension point then we could come up with a bunch of scenarios where developers could implement their own extension. In short, I agree, it needs to happen as an extension point (I would still like to see navigation cache incorporated though :) though I can understand the argument for keeping it out as there is one issue with "deep cloning" that I don't think can actually be resolved - I will just use it on all my sites).

Piedone commented 9 years ago

I agree on caching being built-in somehow. And having an extensibility point for breadcrumbs would allow any scenario, where we could implement the most used ones (I'm thinking about content items and their relationships) by default.