I saw some other method of measure with using trace, but I just wonder this method measure correctly...
I overrided each execution of the following:
PreInit
Init
InitComplete
PreLoad
Load
LoadComplete
PreRender
PreRenderComplete
SaveStateComplete
Unload
Then I store the time when the handler execute with using DateTime.Now.Tick...
At the end of Unload I will print out each of their execution time....
So the time above should be the time server spent to generate the page?
I am asking is because I notice some page took like 879ms in total above, but until my browser actually see the page is take few more seconds.
Those few more seconds should be the time that takes to download the page from server?
Thanks in advance.
in global.asax
namespace aaaaa
{
public class Global : System.Web.HttpApplication
{
private Stopwatch sw = null;
protected void Application_BeginRequest(object sender, EventArgs e)
{
sw = Stopwatch.StartNew();
}
protected void Application_EndRequest(object sender, EventArgs e)
{
if (sw != null)
{
sw.Stop();
Response.Write("took " + sw.Elapsed.TotalSeconds.ToString("0.#######") + " seconds to generate this page");
}
}
}
}
Yes, there's time for the code to run and the time for the browser to get the response from the server and output it to the screen. You can measure the front-end work using a variety of measuring sites:
Pingdom Tools
WebWait
Web page Test
To determine the timing for processing of the code, I would use the StopWatch class instead of using DateTime. DateTime is more precise to the decimal point, but less accurate. StopWatch is designed exactly for that and would be better to use to calculate the timing. Avoid calling it a lot though, as that itself will add overhead to the page processing. I would create a new StopWatch() then call Start at the very beginning, then call stop at the very end. Then spit out the elapsed time after.
StopWatch class
Precise Run Time Measurements with Stopwatch
If you are just looking for overall time, why not just look at the time-taken value in your IIS logs?
The extra time in the browser could be a lot of things. Fetching, Images, CSS, javascript files, javascript running in the page, and the client rendering of the HTML itself. If you want to get a better feel for what is actually happening and when fire up Fiddler and then reload your page and look at what happened in Fiddler.
Related
I have the latest version of CefSharp installed and when I call ViewSource(), it opens up a notepad window with the source code. But when I call GetSourceAsync() the code is very different and missing the HTML I need in the var html that is shown in the Notepad window. The only work around would be to somehow copy the contents of the code in Notepad into my app and use it. Does anyone know how to get the html as shown in the NotePad window? I'm running the application in the Windows 7 Pro operating system using Visual Studio 2017 Express. Here is my code...
private void WebBrowserFrameLoadEndedAsync(object sender, FrameLoadEndEventArgs e)
{
chromeBrowser.ViewSource();
chromeBrowser.GetSourceAsync().ContinueWith(taskHtml =>
{
var html = taskHtml.Result;
});
}
}
Here is the web page that the browser goes to...
chromeBrowser = new ChromiumWebBrowser("https://www.amazon.com/product-reviews/B084RCFDJ3/ref=acr_search_hist_5?ie=UTF8&filterByStar=five_star&reviewerType=all_reviews#reviews-filter-bar");
It turns out, I was searching the source for the wrong phrase. So now I just call the following...
string source = await chromeBrowser.GetBrowser().MainFrame.GetSourceAsync();
I've gone into detail on the difference between GetSource and ViewSource further down.
Some important things to note about FrameLoadEnd.
Is called for every frame, if your page has multiple frames then it will be called multiple times
It's called when the initial resources have finished loading, if your website is dynamically created/rendered then your call maybe happening too early.
//FrameLoadEnd is called for every frame, if your page has multiple frames then it will be called multiple times.
private async void BrowserFrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
var frame = e.Frame;
var source = await frame.GetSourceAsync();
}
//To only get the main frame source
private async void BrowserFrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
var frame = e.Frame;
if (frame.IsMain)
{
var source = await frame.GetSourceAsync();
}
}
// If your website dynamically generates content then you might need to wait a
// little longer for it to render. Introduce a fixed wait period, this can be
// problematic for a number of reasons.
private async void BrowserFrameLoadEnd(object sender, FrameLoadEndEventArgs e)
{
var frame = e.Frame;
if (frame.IsMain)
{
// Wait a little bit of time for the page to load
await System.Threading.Tasks.Task.Delay(500);
var source = await frame.GetSourceAsync();
}
}
Explanation of the difference in behaviour
Firstly ViewSource() returns immediately, Notepad is being launched after the GetSourceAsync call has completed.
Both methods send a GetSource message to the render process which returns a ReadOnlySharedMemoryRegion. When you read the data from the shared memory section ends up with a different snapshot in time.
void CefFrameHostImpl::ViewSource() {
SendCommandWithResponse(
"GetSource",
base::BindOnce(&ViewTextCallback, CefRefPtr<CefFrameHostImpl>(this)));
}
void CefFrameHostImpl::GetSource(CefRefPtr<CefStringVisitor> visitor) {
SendCommandWithResponse("GetSource",
base::BindOnce(&StringVisitCallback, visitor));
}
CEF Source reference.
The CefFrameHostImpl::GetSource method which GetSourceAsync calls completes very quickly as it simply creates a string from the shared memory section.
The CefFrameHostImpl::ViewSource method whilst returns immediately is much slower and takes additional processing to create a file on disk, write that string, spawn notepad.
HTML Source is always a snapshot of source for a given point in time. For static web pages, time makes no difference, for dynamically rendered/updated websites a few hundred milliseconds can mean you get entirely different source.
When the shared ReadOnlySharedMemoryRegion is converted into a string means there is a subtle difference in the source you end up getting.
Can anyone explain the following behaviour of an ASP.net webform on IIS. When I have a page and start it 4 times, the pages are served synchroniously. In other words if this page takes about 10 seconds to build, I see the first page appear at around 10sec, 2nd at 20sec, 3rd at 30sec, 4th at 40sec. When asking the threadnumber I usually see 2 threadnumbers, which makes me think IIS/ASP.net is only having two threads in IIS per application pool?
Small example:
protected void Page_Load(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(10000);
this.Label1.Text = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
}
When I look for suggestions on the internet I find that I should program asynchroniously and for example use await Task.Delay to not block the thread, but I still have the same result when I use this Page_Load:
protected async void Page_Load(object sender, EventArgs e)
{
await System.Threading.Tasks.Task.Delay(10000);
this.Label1.Text = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
}
Can anyone explain me this behaviour? First of all if there are two threads I would expect two pages being served at 10sec and the 3rd and 4th at 20sec. But even when I run the code with async it doesn't really make much/any difference. How can I circumvent this blocking of threads with an easy solution?
Best regards,
Rémy Samulski
EDIT: I was calling the website from the same browser and the same URL. This caused the issue. Thx to Richard for helping me figuring out my mistake.
Whenever I update my web app on IIS, any user who currently using it, will see the page be unresponsive and it won't work again until they refresh the browser. (The update process last for about 30 seconds)
I would like to show up a notification, such as a javascript alert, for user to know that the page is being udpated and please try to refresh the page after 30 seconds, etc.
I tried to catch the Exception in Global.ascx but no exception was thrown in this case.
Consider using app_offline.htm. It is a page that will cause clients to see your IIS app as being down. When you're through updating, just remove the page.
You could create a FileSystemWatcher in global.ascx then bubble up (update a js for instance) an exception when a file is updated. You could start with this:
using System.IO;
namespace WebApplication1
{
public class Global : System.Web.HttpApplication
{
FileSystemWatcher watcher;
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
watcher = new FileSystemWatcher(this.Context.Server.MapPath("/"));
watcher.Changed += new FileSystemEventHandler(watcher_Changed);
}
void watcher_Changed(object sender, FileSystemEventArgs e)
{
//set a value in js file
FileInfo jsFilesChanged = new FileInfo(Path.Combine(this.Context.Server.MapPath("/"), "scripts", "files_changed.js"));
using (StreamWriter jsWriter = (!jsFilesChanged.Exists) ? new StreamWriter(jsFilesChanged.Create()) : new StreamWriter(jsFilesChanged.FullName, false))
{
jsWriter.WriteLine("var changed_file = \"" + e.Name + "\";");
}
}
//.......
}
}
Then in client code include files_changed.js and create a periodic timeout call to check the var changed_file. Also, make sure watcher doesn't get garbage collected.
Some references:
http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
http://www.developerfusion.com/article/84362/extending-filesystemwatcher-to-aspnet/
How the big boys do this:
You need to have a way of posting an alert on a page. Typically this is done by having a table in your database for these alerts. Basically you are just storing some text in there like "hey, the site is going down for maintenance between 8:00am and 8:01am"..
On each page load, you check that table and display any messages found in a conspicuous place (like the top).
Prior to pushing an update you add the alert, while giving them enough time to wrap up whatever it is that they are doing.
After the push is complete you clear out the alerts table.
Honestly the main issue you have is simply one of scheduling updates and communicating to the users what's about to happen. You want to do so in a way that isn't a surprise. That said, you might consider enabling the optimizeCompilations flag in order to try and speed up the compilation time of your website when it is first hit after pushing an update.
I won't go into the boring details of why I need this, it's part of an internal analytics package, but my goal is to create an ASP.NET page that returns a redirect after 2 seconds.
The problem I'm seeing is that using Thread.Sleep(2000); is going to hold up one of my ASP.NET ThreadPool threads. As I understand it, this is pretty wasteful as thread creation isn't cheap and I need this server to handle as many possible simultaneous connections as possible.
So, what's the best way to have HTTP GETs to my page return after at least 2 seconds (over 2 seconds is no problem, it just can't be under).
protected void Page_Load(object sender, EventArgs e)
{
Thread.Sleep(2000);
Response.Redirect(RedirectUri);
}
EDIT
I should clarify, the requested page is actually requested as an image, so returning HTML isn't possible. It'll be used like so:
<img src="http://hostname/record.aspx"/>
The redirect to an actual image should take 2 seconds.
You can do this on the markup itself, you can put something like:
<head>
<meta http-equiv="refresh" content="3; URL=otherpage.aspx">
</head>
You could implement IHttpAsyncHandler. See MSDN.
Do it in JS:
setTimeout(function() {
$.ajax({url: './script.aspx'});
},2000);
There is no way simple way to delay program execution without holding up a thread. You could in theory set up a a delay at the other server where the Re-Direct is occurring, but if you are just trying to cause a delay or timeout prior to the Redirect, you'll have to pay the penalty of a waiting thread.
commonly on say PHP or other web frameworks getting the total response time is easy, just start the timer at the top of the file and stop it at the end.
In ASP.Net there is the whole Page Lifecycle bit though so I'm not sure how to do this. I would like for this response time recording to take place in a master page and the response time show up in the footer of pages. What would be the best way of doing this? Is there something built in to ASP.Net for it? Is it even possible to include the OnRender time?
You can do it on the Global.asax, take a look at this article
void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Items["renderStartTime"] = DateTime.Now;
}
void Application_EndRequest(object sender, EventArgs e)
{
DateTime start = (DateTime) HttpContext.Current.Items["renderStartTime"];
TimeSpan renderTime = DateTime.Now - start;
HttpContext.Current.Response.Write("<!-- Render Time: " + renderTime + " -->");
}
You can either use
Application begin_request and end_request in global.asax
Use Firebug at client side to check the time it takes to load the page
Use Tracing features
Some information available at:
Measure ASP.NET page load time
If you're running Visual Studio Team System (perhaps other versions too now) you can also use the Visual Studio Profiler (http://msdn.microsoft.com/en-us/magazine/cc337887.aspx) to profile what is taking the most time.