We have tried an experiment where we are using Razor and XSLT as a test. We have over 2000 nodes in our website and some are tagged with a property from a dropdown list. It is cross promotions. So if the nodes are tagged with the same categories they will show up on each other's pages. We are querying from the root down the tree because no all the property is in multiple DocTypes.
Our issue is, we want to switch our XSLT file to Razor, but when we did that, did the query looking for the property using Razor, etc and we stuck the Macro in the template, all of a sudden out website started lagging and our CPU started spiking at 100%.
So my question is: What is different between the way XSLT is getting the data and nodes and the way Razor is getting the nodes. Because XSLT seems to have no problems rendering it's Macro on the page and the Razor version (using uQuery and Razor) has some severe performance issues. Why might the CPU be spiking when querying with Razor vs XSLT.
Is there something we can do to speed up the query or even keep out CPU from spiking?
My recomendation: Use the Macro Cacheing fetures uf Umbraco. You can set a cache period for how long you want to macro to rebuild itsself. This won't per say speed up the razor macro execution time but it will greatly improve proformance for every user after the first request. The macro timout will affect the preformance and also how long it takes for changes to show up.
NOTE: In your use case your macro is generating different output based on the page that is calling it so be sure to check the Cache by Page option so that each version is cached.
NOTE: You should alwayse use cacheing where available but some thing's won't work in a cache. Reading/writting Session/query string state in .NET code for example wont work becosue the .net code is not being run every time. This could be done in javascript/cookies however. Also Backend calls that talk to a databse will only run the first time themacor is called and the results cached. In this case one could use XML calls to /base in the macro to get the desired cacheing but also have dynamic data.
Hmm, doesn't quite solve our issue. We have actually tried caching the Razor version of the Macro before and the issue still persisted. The thing is, it slows the WHOLE site down, not just the page. What would be the difference in the way the XSLT is executed in Umbraco and Razor? My only guess is that XSLT is executed quicker in Umbraco than in Razor. But I am not certain of this.
It still seemed to really slow the site down anyways. My guess is because of the amount of nodes we have, the execution is much slower with Razor (for some reason).
Ok, is the razor macro running the tree walk differently then the xlt version was, checking more nodes, loading extra property data? If you use the DynamicNode or @Modle.GetNodById methods or creating new Document() calls? If using @Model is should be checking the cache and not hitting the DB to tre walk, maby check the sql server ands see if thats gettign > queries durring the macro.
Are you filtering out trypes of nodes that cant have categories, IE blog posts or other doc types.
This filtering is not much different between the XSLT and the uQuery Razor.
This is what we have for our uQuery code. I looked at the StackTrace and the uQuery Razor code it is taking 3.4 seconds and jacks with the CPU on our server. The XSLT code only takes 1.9 seconds and does barely anything to the CPU. Code examples are below. If anything, I think we are going to just stick with the XSLT version for now.
@{ var mystring = string.Empty; int numberOfResults = int.Parse(@Parameter.numberOfResults); var Category = @Model.crossPromotionCategories; var uRootNode = uQuery.GetRootNode(); var uNodes = uRootNode.GetDescendantNodes().Where(x => x.GetPropertyAsString("crossPromotionCategories") == Category && x.Id != @Model.Id); var lNodes = GetRandomNodesAndShuffle(uNodes.ToList(), numberOfResults).ToList();
if(!String.IsNullOrWhiteSpace(Category)){ if(@uNodes.Count() > 0){ <div id="crossPromoHolder"> @if(@numberOfResults >= 2 && @Model._customPromoBoxTitle == ""){ <h4>YOU MAY ALSO LIKE:</h4> }
private List<Node> ShuffleList(List<Node> inputList,int max) { List<Node> randomList = new List<Node>(); Random r = new Random(); int randomIndex = 0; int counter = inputList.Count; for(int i = 0; i < max; i++) { randomIndex = r.Next(0, counter--); randomList.Add(inputList[randomIndex]); } return randomList; } /// <summary> /// This method takes all of the root nodes, grabs nodes randomly and checks for appropriate qualification, and only returns the necessary number /// </summary> /// <returns></returns> public List<Node> GetRandomNodesAndShuffle(IEnumerable<Node> inputList, int maxCount) { return inputList.RandomOrder().Take(maxCount).ToList(); }
public void testFunction(IEnumerable<Node> inputList) { } }
We found that our site had a lot of items caching. Actually taking the caching off of the Macros sped up the page load. We were also using ImageGen, which in theory should be fine, but seemed to also be slowing down the site. Our site is pretty high traffic with over 2000 pages with tons of images and media, so out theory right now is that there was Macros being called inside other Macros and there was a caching conflict. And ImageGen was doing it's process at the same time (even though it has it's own caching). So we are not sure.
On Monday when we get back to the office, we are giong to go back and try again with the uQuery version, if that still has an issue, we will try just straight Razor and try your way Jeremy.
Razor Performance issue compared to XSLT?
We have tried an experiment where we are using Razor and XSLT as a test. We have over 2000 nodes in our website and some are tagged with a property from a dropdown list. It is cross promotions. So if the nodes are tagged with the same categories they will show up on each other's pages. We are querying from the root down the tree because no all the property is in multiple DocTypes.
Our issue is, we want to switch our XSLT file to Razor, but when we did that, did the query looking for the property using Razor, etc and we stuck the Macro in the template, all of a sudden out website started lagging and our CPU started spiking at 100%.
So my question is: What is different between the way XSLT is getting the data and nodes and the way Razor is getting the nodes. Because XSLT seems to have no problems rendering it's Macro on the page and the Razor version (using uQuery and Razor) has some severe performance issues. Why might the CPU be spiking when querying with Razor vs XSLT.
Is there something we can do to speed up the query or even keep out CPU from spiking?
BTW: we are using 4.7.1.
Thanks in advance.
My recomendation: Use the Macro Cacheing fetures uf Umbraco. You can set a cache period for how long you want to macro to rebuild itsself. This won't per say speed up the razor macro execution time but it will greatly improve proformance for every user after the first request. The macro timout will affect the preformance and also how long it takes for changes to show up.
NOTE: In your use case your macro is generating different output based on the page that is calling it so be sure to check the Cache by Page option so that each version is cached.
NOTE: You should alwayse use cacheing where available but some thing's won't work in a cache. Reading/writting Session/query string state in .NET code for example wont work becosue the .net code is not being run every time. This could be done in javascript/cookies however. Also Backend calls that talk to a databse will only run the first time themacor is called and the results cached. In this case one could use XML calls to /base in the macro to get the desired cacheing but also have dynamic data.
Hmm, doesn't quite solve our issue. We have actually tried caching the Razor version of the Macro before and the issue still persisted. The thing is, it slows the WHOLE site down, not just the page. What would be the difference in the way the XSLT is executed in Umbraco and Razor? My only guess is that XSLT is executed quicker in Umbraco than in Razor. But I am not certain of this.
It still seemed to really slow the site down anyways. My guess is because of the amount of nodes we have, the execution is much slower with Razor (for some reason).
Any other suggestions?
Ok, is the razor macro running the tree walk differently then the xlt version was, checking more nodes, loading extra property data? If you use the DynamicNode or @Modle.GetNodById methods or creating new Document() calls? If using @Model is should be checking the cache and not hitting the DB to tre walk, maby check the sql server ands see if thats gettign > queries durring the macro.
Are you filtering out trypes of nodes that cant have categories, IE blog posts or other doc types.
This filtering is not much different between the XSLT and the uQuery Razor.
This is what we have for our uQuery code. I looked at the StackTrace and the uQuery Razor code it is taking 3.4 seconds and jacks with the CPU on our server. The XSLT code only takes 1.9 seconds and does barely anything to the CPU. Code examples are below. If anything, I think we are going to just stick with the XSLT version for now.
This is our XSLT
You could try this, it may run faster, not sure, but it's not using uQuery.
Thanks for the suggestion. We will give it a try.
We found that our site had a lot of items caching. Actually taking the caching off of the Macros sped up the page load. We were also using ImageGen, which in theory should be fine, but seemed to also be slowing down the site. Our site is pretty high traffic with over 2000 pages with tons of images and media, so out theory right now is that there was Macros being called inside other Macros and there was a caching conflict.
And ImageGen was doing it's process at the same time (even though it has it's own caching). So we are not sure.
On Monday when we get back to the office, we are giong to go back and try again with the uQuery version, if that still has an issue, we will try just straight Razor and try your way Jeremy.
Thanks again.
is working on a reply...