I am using razor througout my site. I have a problem that visitors are complaining about the site beeing slow. And when testing it and debugging it i found out the Loading IMacroEnine script takes about 2-3 seconds every time!
What can cause this behaviour? I am using umbraco 4.7.0 and upgrading to 4.7.1 is not in the works right now since many packakes does not work yet (HasAccess).
It does not matter how much information or pictures i have on the sites, it takes very long to load the pages with only text.
"since many packakes does not work yet (HasAccess)." which ones exactly? And what would the problem with HasAccess be exaclty? I'm using it in a site we recently launched and it works perfectly.
I can't remember much about 4.7.0, but I do believe Razor performance has been given a boost in 4.7.1. Ican't imagine that there are many packages actually using Razor and if they are then it would be trivially easy to fix the few upgrade quirks you would have. I think it'd definitely be worth it, if only for the many Razor improvements that you'd be able to take advantage of.
I am sure that it has been given a boost in 4.7.1.
I am running the whole site (4.7.0) locally from a sqlexpress and the pages using razor loads lightning fast.
Production on the other hand the database server is on its own virtual server (Microsoft SQL Server 2008 R2) and the IIS running the site on its own virtual server.
The server is much more powerful than my locally maching of course but still in production i get 2-3 seconds of loadtime and locally virtually no loadtime at all.
Does umbraco do something that i am not aware of when setting up the site on another server from where the site is deployed? That is the only reason that i can think of right now...
I have also chagned the config file of my local site to connect to the production database but it still takes 2-3 seconds..
The macros is cached, but doesn't umbraco only cache code-behind logic, hence no razor will be cached anyway?
Are you sure the Virtual Server is configured OK? I've seen problems with virtual servers not having the correct drivers to interface with the underlying hardware (such as networking or disk controllers) that can cause real slowdowns. Have you tried running traceing on the DB server?
"Does umbraco do something that i am not aware of when setting up the site on another server from where the site is deployed?"
One thing you could do is clear out (delete) the contents of the /App_Data/TEMP folder. This should clear the client dependency and razor cache. Once you've done that try republishing the entire site (right-click main Content node). This should update the umbraco.config file (which is your XML cache of the site).
"The macros is cached, but doesn't umbraco only cache code-behind logic, hence no razor will be cached anyway?"
As far as I understand it, macro cacheing in Umbraco caches the HTML that the macro generates (just like user-control cacehing in ASP.NET). So, once cache, no razor is excecuted - it simply fetches the HTML from the cache that the macro generated when first run.
I just want to jump in quickly and add that if your SQL database server is on another location (the IP address is different from your webserver), I've also seen pretty bad perfomance if it's not configured correctly. However, I don't know how to configure it to fix it. :-)
The ip is different ofc, but the problem is that no one (not even microsoft or HP, hardware of the servers) seems to know where to begin. We have experienced this with other websites and applications aswell. I can try to install a sql express on the web server and set up replication to the real server, but it does not seem right :D
Someone must have experienced the same issue :) Our environment is hyper-v.
I'm afraid I don't know much about configuring VMs - my experience stems from problems I had using one once with slow performance. The IT admin fixed it by installing the right HDD drivers - something to do with disk cacheing on the RAID controller. Don't ask me :)
If your macros are cached then in theory they should never be hitting the database or the XML cache, which is puzzling.
Have you tried adding ?umbDebugShowTrace=true to the end of your URLs? This should give a full trace and maybe help you pinpoint which macros are loading slowy.
It's not the loading of the engine that takes time, it's the execution of the macro itself. The diff you see is from start to when it's done rendering the macro.
Without knowing what is happening inside of the macro it's difficult to give advice.
The thing is, when executing the same macro on my computer locally with sqlexpress it loads lightningsfast. But on the production server that has its own sql sever 2008 r2 and a own server for running the IIS.
Well, there's always differences between machines. If the macro is doing network access, there might be something waiting to time out. If it's doing database access, there might be a problem with that.. I don't know, difficult to give any advice just based on it taking long.
Once when I had a similar problem i turned to windbg and took a dump of what was going on in the process on the server, downloaded it and looked it through locally. Might be an option for you (if you know how to use windbg, quite the opposite of an user friendly tool ;)
Other things you could do is check the event log on the server for any uncaught exceptions, check umbracolog in db, point your connection string on your local machine to the production sql server and check if it makes any difference.
Only thing of note is the $.blogEngine.get("/base/blogengine/posts/tags/@Model.tags/" which looks like it's doing some kind of REST request to get the tags. That may involve network activity followed by DB activity.
Have you tried commenting out parts of the script to see if you can narrow down which (if any) part could be the culprit? The above would be my first guess.
Dan: You are right, but this only occurs if there are any tags connected to the curent page. On pages with no tags it still takes 2-3 seconds. I have alos tried to comment out parts of the code but nothing seems to help. The thing that helped to most is commenting out te @RenderPage at the top, it shaved of 0.5 seconds on the average pageload, and still it comes from the cache...... At least that is what the trace says :)
Barry: I will try this on monday. I think it has something to do with the environment it self. We have a brand new hyper-v environment with resources to house a freakin' searchengine if we wanted to :)
What is bugging me is that the exact same site loads lightning fast on sqlexpress and locally, but when i change the connectionstring to point to the production server it takes up to 2 seconds again. So it has to have something to do with the DB server.
Niether the ping or the tracert showed anything out of the ordinary :(
Right now I am installing an sql express on the production server to se if it speeds it up as my local installation. The 2-3 second lag is to much for the organisation to live with :D
The lag is caused by some configuration issue and I don't know if anybody has been able to figure it out yet. I've seen the same problem numerous times with remote database servers and would love to know how to fix it. I am almost certain that your local sql express instance will solve your problem.
Sebastiaan: I would really really love to know how to fix it :) Installing sqlexpress locally on the production webserver took down the lag from 2.6 seconds per page to 1.3 uncached, and 0.4 seconds cached. This seems ok since the page took over 2 seconds to load even from the cache before. Though locally it still loads faster. I also added gzip compression to the site.
But I would love to solve this mystery since replication does not work in sql express and backup is not the same.
Anyone who has experienced the same issues and has been able to fix it are very welcome to post there answer :D
I have not been able to solve the problem. As of now I have to run the umbraco site with database installed on the same virtual machine. When having the database on a seperate virtual machine the site is almost unworkable. It really sucks not beeing able to seperate servers.
But if you find a better solution be sure to post it!
It seems like I have tracked down the slow page renderings to one razor macro script. And it occurs when it tries to get the macro from disc (loadMacroScript method in macro.cs from the umbraco soruce). I do not have caching set on this macro, but can anyone see if I am doing something really stupid and performance bad in the macro it self?
@using umbraco.MacroEngines
<ul class="sub-menu"> @{ var id = @Model.Id; var node = @Model.NodeById(id); }
var id = @Model.Id; var node = @Model.NodeById(id); @foreach (var level in node.AncestorOrSelf(1).DescendantsOrSelf().Where("Visible")) {
This is a bit weird code. Why not use:
var items = Model.AncestorOrSelf(1).DescendantsOrSelf().Where("Visible")
@foreach (var i in items) ..
if(level.Children.Count() > 0) { foreach(var child in @level.Children.Where("Visible")) {
Here you are looping through the collection twice. the foreach will not run at all if there are no visible children.
if(@level.Parent.Id == @Model.Parent.Id)
No performance impact, but you dont need the @-sign here, when you are in "code mode" you dont need it. However, it is better to put the id in a variable at the top. var parentId = Model.Parent.Id; Since that is in the foreach loop it will look up the parent several times, and going to parent is not cheap.
Still the problem with performance occurs when i change the db to virtual or a physical machine. I can only get the performance down when I have the sql and web on the same virtual machine. Because this macro was the only one that did not use caching, i thought it to be the performance hit.
But i still differs by 2-3 seconds per page load when i switch to the phsyical sql server from the local sql server on the same virtual machine.
Hehe, there is now reason for it really. The reason is that i forgot to put caching on the macro, but it still takes a long time to render the first time.
And fort what I can see it is this macro that is taking the time when getting it from disc.
Haha helt klart, värt att testa iaf. Men ändå, lokalt på min utvecklingspc tar det inte någon tid alls första gången. Men i produktion tar det 2-4 sekunder innan sidan laddas och sedan cachas. Märkligen att det tar 0.5 sekunder lokalt. sqlexpress på båda instanserna så enda skillnaded är att produktion kör på en virtuall maskin.
Loading IMacroEngine script very slow!
Hi,
I am using razor througout my site. I have a problem that visitors are complaining about the site beeing slow. And when testing it and debugging it i found out the Loading IMacroEnine script takes about 2-3 seconds every time!
What can cause this behaviour? I am using umbraco 4.7.0 and upgrading to 4.7.1 is not in the works right now since many packakes does not work yet (HasAccess).
It does not matter how much information or pictures i have on the sites, it takes very long to load the pages with only text.
" since many packakes does not work yet (HasAccess)." which ones exactly? And what would the problem with HasAccess be exaclty? I'm using it in a site we recently launched and it works perfectly.
I can't remember much about 4.7.0, but I do believe Razor performance has been given a boost in 4.7.1. Ican't imagine that there are many packages actually using Razor and if they are then it would be trivially easy to fix the few upgrade quirks you would have. I think it'd definitely be worth it, if only for the many Razor improvements that you'd be able to take advantage of.
Can't understand why you are suffering such a performance hit... But one quick fix is to add cacheing to your Macros.
I am sure that it has been given a boost in 4.7.1.
I am running the whole site (4.7.0) locally from a sqlexpress and the pages using razor loads lightning fast.
Production on the other hand the database server is on its own virtual server (Microsoft SQL Server 2008 R2) and the IIS running the site on its own virtual server.
The server is much more powerful than my locally maching of course but still in production i get 2-3 seconds of loadtime and locally virtually no loadtime at all.
Does umbraco do something that i am not aware of when setting up the site on another server from where the site is deployed? That is the only reason that i can think of right now...
I have also chagned the config file of my local site to connect to the production database but it still takes 2-3 seconds..
The macros is cached, but doesn't umbraco only cache code-behind logic, hence no razor will be cached anyway?
Cheers.
Are you sure the Virtual Server is configured OK? I've seen problems with virtual servers not having the correct drivers to interface with the underlying hardware (such as networking or disk controllers) that can cause real slowdowns. Have you tried running traceing on the DB server?
"Does umbraco do something that i am not aware of when setting up the site on another server from where the site is deployed?"
One thing you could do is clear out (delete) the contents of the /App_Data/TEMP folder. This should clear the client dependency and razor cache. Once you've done that try republishing the entire site (right-click main Content node). This should update the umbraco.config file (which is your XML cache of the site).
"The macros is cached, but doesn't umbraco only cache code-behind logic, hence no razor will be cached anyway?"
As far as I understand it, macro cacheing in Umbraco caches the HTML that the macro generates (just like user-control cacehing in ASP.NET). So, once cache, no razor is excecuted - it simply fetches the HTML from the cache that the macro generated when first run.
Hi Dan,
Thanks for your quick answer.
As far as i know the virtual server is ok, what can you recommend me to check?
The server has a c:, d: (sql data) e: (sql-log), f: (sql-backup) and a z: for system reserved.
There is one network adapter, Microsoft Virtual Machine Bus Network adapter.
Clearing out the TEMP catalog and replublishing the site did not helpt. Still, 2-3 seconds when loading the macros.
I just want to jump in quickly and add that if your SQL database server is on another location (the IP address is different from your webserver), I've also seen pretty bad perfomance if it's not configured correctly. However, I don't know how to configure it to fix it. :-)
The ip is different ofc, but the problem is that no one (not even microsoft or HP, hardware of the servers) seems to know where to begin. We have experienced this with other websites and applications aswell. I can try to install a sql express on the web server and set up replication to the real server, but it does not seem right :D
Someone must have experienced the same issue :) Our environment is hyper-v.
Hi Tommy,
I'm afraid I don't know much about configuring VMs - my experience stems from problems I had using one once with slow performance. The IT admin fixed it by installing the right HDD drivers - something to do with disk cacheing on the RAID controller. Don't ask me :)
If your macros are cached then in theory they should never be hitting the database or the XML cache, which is puzzling.
Have you tried adding ?umbDebugShowTrace=true to the end of your URLs? This should give a full trace and maybe help you pinpoint which macros are loading slowy.
As i wrote above, when doing umbDebugShowTrace=True it is "Loading IMacroEnine script" that takes 2.5 seconds.
Here is a screen from the debug.. http://imageshack.us/photo/my-images/444/traced.png/
It's not the loading of the engine that takes time, it's the execution of the macro itself. The diff you see is from start to when it's done rendering the macro.
Without knowing what is happening inside of the macro it's difficult to give advice.
The thing is, when executing the same macro on my computer locally with sqlexpress it loads lightningsfast. But on the production server that has its own sql sever 2008 r2 and a own server for running the IIS.
That is what is weird.
Well, there's always differences between machines. If the macro is doing network access, there might be something waiting to time out. If it's doing database access, there might be a problem with that.. I don't know, difficult to give any advice just based on it taking long.
Once when I had a similar problem i turned to windbg and took a dump of what was going on in the process on the server, downloaded it and looked it through locally. Might be an option for you (if you know how to use windbg, quite the opposite of an user friendly tool ;)
Other things you could do is check the event log on the server for any uncaught exceptions, check umbracolog in db, point your connection string on your local machine to the production sql server and check if it makes any difference.
I did point the connection string on my local site to the production db, still the same. 2-3 seconds to load the pages..
I can show you guys the razor file.
@using umbraco.MacroEngines
@using MediaProtect.Library
<div class="grid_3">
@RenderPage("Marginalmeny.cshtml")
</div>
<div class="grid_8">
<h2>@Model.Name</h2>
<div class="body">@Model.bodyText</div>
@if (!Model.tags.Equals("")) {
<div class="news">
<h2 id="news-header">Nyheter</h2>
@RenderPage("Nyheter.cshtml")
<a class="news-archive-link" href="/nyheter/arkiv">Se äldre nyheter</a>
<script>
$(function () {
$.blogEngine.get("/base/blogengine/posts/tags/@Model.tags/");
viewModel.take(3);
ko.applyBindings(viewModel);
});
</script>
</div>
}
</div>
<div class="grid_5">
<div class="right-container">
@if(@Model.logoTypes.ToString().Length > 0) {
if(!string.IsNullOrEmpty(@Model.titleForLogotypes)) { <h3>@Model.titleForLogotypes</h3> }
else { <h3>Varumärken</h3> }
<div class="logotypes">@Model.logoTypes</div>
}
<h3>Kontaktuppgifter</h3>
<table class="supplier-info">
<tr>
<td>Kontaktperson: </td><td>@Model.contact</td>
</tr>
<tr>
<td>Telefon: </td><td>@Model.contactPhone</td>
</tr>
<tr>
<td>Mail: </td><td><a href="mailto:@Model.contactEmail">@Model.contactEmail</a></td>
</tr>
<tr>
<td>Order</td>
</tr>
<tr>
<td>Telefon: </td><td>@Model.orderPhone</td>
</tr>
<tr>
<td>Fax: </td><td>@Model.orderFax</td>
</tr>
<tr>
<td>Mail: </td><td><a href="mailto:@Model.orderEmail">@Model.orderEmail</a></td>
</tr>
<tr>
<td>Adress: </td><td>@Model.companyAddress</td>
</tr>
<tr>
<td> </td><td>@Model.companyPostalCode @Model.companyCity</td>
</tr>
<tr>
<td> </td><td>@Model.customerCountly</td>
</tr>
<tr>
<td>Hemsida: </td><td><a href="@Model.companyUrl" target="_blank">@Model.companyUrl</a></td>
</tr>
</table>
<ul class="attachments">
@foreach(dynamic item in @Model.attachments)
{
if (@MediaProtect.Library.Library.HasAccess(@Int32.Parse(item.File.id), @item.File.path))
{
string iconSrc = "";
string ext = @item.File.umbracoExtension;
if (ext == "pdf")
{
dynamic pdfItem = Library.MediaById(1374);
iconSrc = pdfItem.umbracoFile;
}
else if (ext == "doc")
{
dynamic docItem = Library.MediaById(1386);
iconSrc = docItem.umbracoFile;
}
else if (ext == "xls")
{
dynamic xlsIcon = Library.MediaById(1392);
iconSrc = xlsIcon.umbracoFile;
}
else
{
dynamic docItem = Library.MediaById(1386);
iconSrc = docItem.umbracoFile;
}
<li>
<img src="@iconSrc" />
<a href="@item.File.umbracoFile">@item.File.nodeName</a>
<a href="@item.File.umbracoFile">Upplagd @Convert.ToDateTime(item.File.createDate).ToShortDateString()</a>
</li>
}
}
</ul>
</div>
</div>
Only thing of note is the $.blogEngine.get("/base/blogengine/posts/tags/@Model.tags/" which looks like it's doing some kind of REST request to get the tags. That may involve network activity followed by DB activity.
Have you tried commenting out parts of the script to see if you can narrow down which (if any) part could be the culprit? The above would be my first guess.
Try using PING and traceroute from the webserver to the DB server. Sounds like it could be down to some sort of network lag:
http://help.expedient.com/general/ping_traceroute.shtml
Otherwise it could be a resources issue on the DB server itself, I have used the SQL server profiler tool before to check its performance under load.
Dan: You are right, but this only occurs if there are any tags connected to the curent page. On pages with no tags it still takes 2-3 seconds. I have alos tried to comment out parts of the code but nothing seems to help. The thing that helped to most is commenting out te @RenderPage at the top, it shaved of 0.5 seconds on the average pageload, and still it comes from the cache...... At least that is what the trace says :)
Barry: I will try this on monday. I think it has something to do with the environment it self. We have a brand new hyper-v environment with resources to house a freakin' searchengine if we wanted to :)
What is bugging me is that the exact same site loads lightning fast on sqlexpress and locally, but when i change the connectionstring to point to the production server it takes up to 2 seconds again. So it has to have something to do with the DB server.
Thanks for taking the time to answer.
Niether the ping or the tracert showed anything out of the ordinary :(
Right now I am installing an sql express on the production server to se if it speeds it up as my local installation. The 2-3 second lag is to much for the organisation to live with :D
The lag is caused by some configuration issue and I don't know if anybody has been able to figure it out yet. I've seen the same problem numerous times with remote database servers and would love to know how to fix it. I am almost certain that your local sql express instance will solve your problem.
Sebastiaan: I would really really love to know how to fix it :) Installing sqlexpress locally on the production webserver took down the lag from 2.6 seconds per page to 1.3 uncached, and 0.4 seconds cached. This seems ok since the page took over 2 seconds to load even from the cache before. Though locally it still loads faster. I also added gzip compression to the site.
But I would love to solve this mystery since replication does not work in sql express and backup is not the same.
Anyone who has experienced the same issues and has been able to fix it are very welcome to post there answer :D
I did put out a call on twitter earlier, and nobody replied yet, bit of an obscure issue I'm afraid.
If you have solved the problem, please let me know. I have the same problem.
Best regards, Sergey
Hi Sergey,
I have not been able to solve the problem. As of now I have to run the umbraco site with database installed on the same virtual machine. When having the database on a seperate virtual machine the site is almost unworkable. It really sucks not beeing able to seperate servers.
But if you find a better solution be sure to post it!
It seems like I have tracked down the slow page renderings to one razor macro script. And it occurs when it tries to get the macro from disc (loadMacroScript method in macro.cs from the umbraco soruce). I do not have caching set on this macro, but can anyone see if I am doing something really stupid and performance bad in the macro it self?
@using umbraco.MacroEngines
<ul class="sub-menu">
@{
var id = @Model.Id;
var node = @Model.NodeById(id);
}
@foreach (var level in node.AncestorOrSelf(1).DescendantsOrSelf().Where("Visible")) {
if(level.HasAccess)
{
if(@level.NodeTypeAlias == @Model.NodeTypeAlias)
{
if(@level.Parent.Id == @Model.Parent.Id)
{
// Om barn finns = smael eller vitvaror
if(level.Children.Count() > 0)
{
foreach(var child in @level.Children.Where("Visible")) {
if(@level.Id == id) {
<li><a href="@child.Url">@child.Name</a></li>
}
}
}
else if(@level.Id == id)
{
<li class="active"><a href="@level.Url">@level.Name</a></li>
}
else
{
<li><a href="@level.Url">@level.Name</a></li>
}
}
}
}
}
</ul>
Just some pointers:
var id = @Model.Id;
var node = @Model.NodeById(id);
@foreach (var level in node.AncestorOrSelf(1).DescendantsOrSelf().Where("Visible")) {
This is a bit weird code. Why not use:
var items = Model.AncestorOrSelf(1).DescendantsOrSelf().Where("Visible")
@foreach (var i in items) ..
if(level.Children.Count() > 0)
{
foreach(var child in @level.Children.Where("Visible")) {
Here you are looping through the collection twice. the foreach will not run at all if there are no visible children.
if(@level.Parent.Id == @Model.Parent.Id)
No performance impact, but you dont need the @-sign here, when you are in "code mode" you dont need it. However, it is better to put the id in a variable at the top. var parentId = Model.Parent.Id; Since that is in the foreach loop it will look up the parent several times, and going to parent is not cheap.
Still the problem with performance occurs when i change the db to virtual or a physical machine. I can only get the performance down when I have the sql and web on the same virtual machine. Because this macro was the only one that did not use caching, i thought it to be the performance hit.
But i still differs by 2-3 seconds per page load when i switch to the phsyical sql server from the local sql server on the same virtual machine.
It is driving me crazy :)
Yeah, i know. But try my changes, många bäckar små.. ;)
But is there any reason why you cant use caching? I don't see anything in this code that makes it unsuitable for it.
Hehe, there is now reason for it really. The reason is that i forgot to put caching on the macro, but it still takes a long time to render the first time.
And fort what I can see it is this macro that is taking the time when getting it from disc.
Haha helt klart, värt att testa iaf. Men ändå, lokalt på min utvecklingspc tar det inte någon tid alls första gången. Men i produktion tar det 2-4 sekunder innan sidan laddas och sedan cachas. Märkligen att det tar 0.5 sekunder lokalt. sqlexpress på båda instanserna så enda skillnaded är att produktion kör på en virtuall maskin.
is working on a reply...