How can I monitor the rendering time in a browser? - javascript

I work on an internal corporate system that has a web front-end using Tomcat.
How can I monitor the rendering time of specific pages in a browser (IE6)?
I would like to be able to record the results in a log file (separate log file or the Tomcat access log).
EDIT: Ideally, I need to monitor the rendering on the clients accessing the pages.

The Navigation Timing API is available in modern browsers (IE9+) except Safari:
function onLoad() {
var now = new Date().getTime();
var page_load_time = now - performance.timing.navigationStart;
console.log("User-perceived page loading time: " + page_load_time);
}

In case a browser has JavaScript enabled one of the things you could do is to write an inline script and send it first thing in your HTML. The script would do two things:
Record current system time in a JS variable (if you're lucky the time could roughly correspond to the page rendering start time).
Attach JS function to the page onLoad event. This function will then query the current system time once again, subtract the start time from step 1 and send it to the server along with the page location (or some unique ID you could insert into the inline script dynamically on your server).
<script language="JavaScript">
var renderStart = new Date().getTime();
window.onload=function() {
var elapsed = new Date().getTime()-renderStart;
// send the info to the server
alert('Rendered in ' + elapsed + 'ms');
}
</script>
... usual HTML starts here ...
You'd need to make sure that the page doesn’t override onload later in the code, but adds to the event handlers list instead.

As far as non-invasive techniques are concerned, Hammerhead measures complete load time (including JavaScript execution), albeit in Firefox only.
I've seen usable results when a JavaScript snippet could be added globally to measure the start and end of each page load operation.

Have a look at Selenium - they offer a remote control that can automatically start different browsers (e.g. IE6), load pages, test for specific content on the page. At the end reports are generated that also show the rendering times.

Since others are posting answers that use other browsers, I guess I will too. Chrome has a very detailed profiling system that breaks down the rendering time of the page and shows the time it took for each step along the way.
As for IE, you might want to consider writing a plugin. There seems to be few tools like this on the market. Maybe you could sell it.

On Firefox you can use Firebug to monitor load time. With the YSlow plugin you can even get recommendations how to improve the performance.

Related

Force (or ask nicely) to refresh the browser

So I run a site that uses a lot of javascript and ajax. I understand how to make users refresh their browser when the browser loads. But what happens if I need them to refresh their browser after they have loaded the site?
I want to change the ajax that is served to the client to speed up things up, but this is going to cause errors for the users who have not yet refreshed their browser.
The only solution I can come up with is that when a new version of the JavaScript file is required, the site uses a popup that asks the users to force refresh their browsers. (This won't really fix the current version, but would prevent future issues.)
I hate to use a popup for something that I could do automatically. Is there a better way to force updates for the client?
window.location.href = "http://example.com"
replaces the current page with the one pointed to by http://example.com.
You sound like you are having trouble with your JavaScript getting an updated version of the data it loads through Ajax methods, is that correct? For instance, if two Ajax calls try to load 'data.txt', then the second call merely uses the cached version.
You also may be having trouble with loading new versions your script itself.
The way around both of these problems is to add a randomly-generated query string to your script source and your Ajax source.
For example, make one script that loads your main script, like this:
/* loader1.js */
document.write('<script src="mainjavascript.js?.rand=', Math.random(), '"></script>');
And in your HTML, just do
<script src="loader1.js"></script>
The same method works for JavaScript Ajax requests as well. Assuming that "client" is a new XMLHttpRequest() object, and has been properly set up with a readystatechange function and so on, then the you simply append the same query string, like this:
request = client.open('GET', 'data.txt?.rand=' + Math.random(), true);
request.send();
You may be using a library to do your Ajax requests, and so it's even easier then. Just specify the data URL as 'data.txt?.rand=' + Math.random() instead of merely 'data.txt'

Is there any event that fires right before the browser request another resource such as image?

We would like to measure how much time it takes the browser the get a resource from the network.
so for example if my page loads 10 images and 4 scripts I would like to know how much time it took the browser to load those resources from the network.
writing a browser plugin might work, but it's forces us to write different tool for each browser..what else can we do?
Google Speedtracer should give you this information. I believe it shows the start of the request and the total elapsed time.
If you're concerned about browser specific quirks, you'd likely need to do some inline logging with JavaScript.
A pretty basic script such as:
<script type="text/javascript">
var startTime = new Date().getTime();
</script>
<img src="yourimage.jpg" onload="console.log('new Date().getTime() - startTime')" />
ought to do the trick, but it's awfully invasive.

Programmatically check and update only if an image has changed

I have an application which updates an image from time to time. The update interval is not predictable. The image itself is updated atomically on the web server via rename(). That is all this application does and there shall be no change on the Apache side such that the webserver can continue to only serve static files.
There is some AJAX script which displays the content and updates this image when it is changed. This is done using polling. The naive JavaScript version used a counter and updated pulled the image each second or so by adding a query timestamp. However 99% of the time this pulls the image unchanged.
The current not so naive version uses XMLHttpRequest aka. AJAX to check the If-Modified-Since-header, and if a change is detected the update is invoked.
The question now is, is there a better way to archive this effect? Perhaps look at the last paragraph of this text before you dive into this ;)
Here are the core code snippets of the current version. Please note that the code is edited for brevity, so var initialization left away and some lines removed which are not of interest.
First the usual, slightly extended AJAX binding:
// partly stolen at http://snippets.dzone.com/posts/show/2025
function $(e){if(typeof e=='string')e=document.getElementById(e);return e};
ajax={};
ajax.collect=function(a,f){var n=[];for(var i=0;i<a.length;i++){var v=f(a[i]);if(v!=null)n.push(v)}return n};
ajax.x=function(){try{return new XMLHttpRequest()}catch(e){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){return new ActiveXObject('Microsoft.XMLHTTP')}}};
ajax.send=function(u,f,m,a,h){var x=ajax.x();x.open(m,u,true);x.onreadystatechange=function(){if(x.readyState==4)f(x.responseText,x,x.status==0?200:x.status,x.getResponseHeader("Last-Modified"))};if(m=='POST')x.setRequestHeader('Content-type','application/x-www-form-urlencoded');if(h)h(x);x.send(a)};
ajax.get=function(url,func){ajax.send(url,func,'GET')};
ajax.update=function(u,f,lm){ajax.send(u,f,'GET',null,lm?function(x){x.setRequestHeader("If-Modified-Since",lm)}:lm)};
ajax.head=function(u,f,lm){ajax.send(u,f,'HEAD',null,lm?function(x){x.setRequestHeader("If-Modified-Since",lm)}:lm)};
The basic HTML part, it includes 2 images which are flipped after loading, and a third one (not referenced in the code snippets) to display archived versions etc., which prevents flipping the updates as well:
</head><body onload="init()">
<div id="shower"><img id="show0"/><img id="show1"/><img id="show2"/></div>
The initial part includes the timer. It is a bit more to it, to compensate for network delays on slow links, reduce the polling rate etc.:
function init()
{
window.setInterval(timer,500);
for (var a=2; --a>=0; )
{
var o=$("show"+a);
o.onload = loadi;
}
disp(0);
}
function disp(n)
{
shown=n;
window.setTimeout(disp2,10);
}
function disp2()
{
hide("show0");
hide("show1");
hide("show2");
show("show"+shown);
}
function hide(s)
{
$(s).style.display="none";
}
function show(s)
{
$(s).style.display="inline";
}
function timer(e)
{
if (waiti && !--waiti)
dorefresh();
nextrefresh();
}
function nextrefresh()
{
if (sleeps<0)
sleeps = sleeper;
if (!--sleeps)
pendi = true;
if (pendi && !waiti)
dorefresh();
}
From time to time dorefresh() is called to pull the HEAD, tracking If-Modified-Since:
function dorefresh()
{
waiti = 100; // allow 50s for this request to take
ajax.head("test.jpg",checkrefresh,lm);
}
function checkrefresh(e,x,s,l)
{
if(!l)
{
// not modified
lmc++;
waiti = 0;
}
else
{
lmc=0;
lm=l;
$("show"+loadn).src = "test.jpg?"+stamp();
waiti=100;
}
pendi=false;
sleeper++;
if (sleeper>maxsleep)
sleeper = maxsleep;
sleeps=0;
nextrefresh();
}
function stamp()
{
return new Date().getTime();
}
When the image is loaded it is flipped into view. shown usually is 0 or 1:
function loadi()
{
waiti=0;
$("show"+loadn).style.opacity=1;
if (shown<2)
disp(loadn);
loadn=1-loadn;
}
Please note that I only tested this code with Webkit based browsers yet.
Sorry, I cannot provide a working example, as my update source is non-public.
Also please excuse that the code is somewhat quick-n-dirty quality.
Strictly speaking HEAD alone is enough, we could look at the Last-Modified header of course.
But this recipe here also works for GET requests in a non-image situation.
AJAX GET in combination with images makes less sense, as this pulls the image as binary data.
I could convert that into some inline image, of course, but on bigger images (like mine) this will exceed the maximum URL length.
One thing which possibly can be done is using the browser cache.
That is pull the image using an ajax.update and then re-display the image from the cache.
However this depends on the cache strategy of a browser. On mobile devices the image might be too big to be cached, in that case it is transferred twice. This is wrong as usually mobile devices have slow and more important expensive data links.
We could use this method if the webserver would write a text file, like JSON or a JS snippet, which then is used to display the image.
However the nice thing about this code here is, that you do not need to provide additional information.
So no race conditions, no new weird states like in disk full cases, just works.
So one basic idea is to not alter the code on the webserver which generates the picture, just do it on the browser side.
This way all you need is a softlink from the web tree to the image and make sure, the image is atomically updated.
The downside of AJAX is the same origin policy, so AJAX can only check the HEAD of resources from the host which provided the running JavaScript code.
Greasemonkey or Scriptlets can circumvent that, but these cannot be deployed to a broad audience.
So foreign resources (images) sadly cannot be efficiently queried if they were updated or not.
At my side luclily both, the script and the image, originate from the same host.
Having said this all, here are the problems with this code:
The code above adds to the delay. First the HEAD is checked and if this shows that something has changed the update is done.
It would be nice to do both in one request, such that the update of the image does not require an additional roundtrip.
GET can archive that with If-Modified-Since, and it works on my side, however I found no way to properly display the result as an inlined image. It might work for some browsers, but not for all.
The code also is way too complex for my taste. You have to deal with possible network timeouts, not overwhelming limited bandwidth, trying to be friendly to the webserver, being compatible to as many browsers as possible, and so on.
Also I would like to get rid of the hack to use a query parameter just to pull an updated image, as this slowly fills/flushes the cache.
Perhaps there is an - unknown to me - way to "re-trigger" image refresh in the browser?
This way the browser could check with If-Modified-Since directly and update the image.
With JavaScript this could trigger a .load event then or similar.
At my side I even do not need that at all, all I want is to keep the image somewhat current.
I did not experiment with CANVAS yet. Perhaps somebody has an idea using that.
So my question just is, is there any better way (another algorithm) than shown above, except from improving code quality?
From what I understand, you have 2 sources of information on the server: the image itself and time of last update. Your solution polls on both channels and you want to push, right?
Start here: http://en.wikipedia.org/wiki/Comet_(programming), there should be a simple way to let the server update the client on a new image url. In case server and client support websockets it's a shortcut.
However, most simple solution assumes no image url change and runs
image.src = "";
image.src = url;
by using setInterval() and let the browser deal with cache and headers.

External Javascript Timeout

I have a number of tracking scripts and web services installed on my website and I noticed when one of the services goes down, it still tries to call the external javascript file hosted on a different server. In Firefox, Chrome and other new browsers, there doesn't seem to be any issues when one of the services go down. However, in IE7 and IE8, my pages don't load all the way and time out before everything is displayed. Is there any way to add a time out on these javascript calls to prevent them from breaking my pages when they go down?
You can load them dynamically after page load with JS. If the JS files are on a different server, the browser will still show a "browser busy" indicator when you do that, but the original page will load.
If you can fetch the JS from your own site, you can load it with XMLHttpRequest after page load (or with your favorite JS library's helpers, e.g. jQuery's $.ajax(...)) and then eval it. This way the fetching itself won't show the browser-busy indicator.
To fetch the JS from your own site, you can download it from your tracking provider (which won't be officially supported but usually works) - just remember to refetch new versions every once in a while - or you can create a "forwarding" service on your own site that fetches it from the tracking provider and caches it locally for a while. This way your JS won't be in danger of staleness.
Steve Souders has more information about deferred loading of scripts and browser-busy indicators.
Try adding defer="defer"
The defer attribute gives a hint to
the browser that the script does not
create any content so the browser can
optionally defer interpreting the
script. This can improve performance
by delaying execution of scripts until
after the body content is parsed and
rendered.
Edit
This will prevent those scripts from running until the page loads:
function loadjs(filename) {
var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", filename);
}
window.onLoad = function() {
loadJs("http://path.to.js");
loadJs("http://path.to2.js");
...
}
If you need to load external scripts and you want to enforce a timeout limit, to avoid having a busy indicator running for too long, you can use setTimeout() with window.stop() and, the IE equivalent:
http://forums.devshed.com/html-programming-1/does-window-stop-work-in-ie-1311.html
var abort_load = function() {
if(navigator.appName == "Microsoft Internet Explorer") {
window.document.execCommand('Stop');
} else {
window.stop();
}
};
/**
* Ensure browser gives up trying to load JS after 3 seconds.
*/
setTimeout(abort_load, 3000);
Note that window.stop() is the equivalent of the user clicking the stop button on their browser. So typically you'd only want to call setTimeout() after page load, to ensure you don't interrupt the browser while it's still downloading images, css and so on.
This should be combined with the suggestions made by orip, namely to load the scripts dynamically, in order to avoid the worst case of a server that never responds, resulting in a "browser busy" indicator that's active until the browser's timeout (which is often over a minute). With window.stop() in a timer, you effectively specify how long the browser can try to load the script.
Also note that setTimeout()'s interval is not that precisely interpreted by browsers so round up in terms of how much time you want to allow to load a script.
Also, one counter-indication to using window.stop() is if your page does things like scroll to a certain position via js. You might be willing to live with that but in any case you can make the stop() conditional on NOT having already loaded the content you expected. For example if your external JS will define a variable foo, you could do:
var abort_load = function() {
if (typeof(foo) == "undefined") {
if(navigator.appName == "Microsoft Internet Explorer") {
window.document.execCommand('Stop');
} else {
window.stop();
}
}
};
This way, in the happy path case (scripts do load within timeout interval), you don't actually invoke window.stop().

Need to refresh a single ie7 web tab from command line

I need to create a batch file that will stop a process and then refresh a defined tab in internet explorer 7. Just need some help/pointers on the tab refresh part or if it's even possible... I don't want IE to open another tab, and another browser is not an option as the web based program is only compatible with IE. Any ideas? I've experimented with a VBS file with no luck and seeing how it's a web based program I cannot add Java Script to the page...
I know you said you tried VBScript, but it really is the most suitable solution for what you're trying to achieve. See "Hey, Scripting Guy! Blog: How Can I Tell if Any Internet Explorer Windows Are Open to a Particular Web Site?"
See the code:
For i = 0 to objShellWindows.Count - 1
Set objIE = objShellWindows.Item(i)
strURL = objIE.LocationURL
If InStr(strURL, "http://www.microsoft.com/technet/scriptcenter")Then
blnFound = True
End If
Next
Each iteration returns an instance of an open Internet Explorer window's WebBrowser Control. Instead of the blnFound = True try objIE.Refresh2().
You could frame the site, then refresh it from the outer frame with javascript on a timer. This may or may not suit your needs.
This is doable, but it's a little tricky and it requires a constraint: the tab you want to refresh has to have been opened by a Javascript call to window.open and it has to have a name. Let's call that name foo. Then you need to simply load another web page in that same browser session to execute the following Javascript:
window.open('http://other.site.url/etc', 'foo');
This means you need to both know the name of the frame and the target URL. But it's certainly doable.
Doing this from a batch file requires some scripting. In VBScript the code would be something like:
Dim browser
Set browser = CreateObject("SHDocVw.InternetExplorer")
browser.visible = True
browser.navigate("http://mysite.org/refresh.html")
Where refresh.html is the page containing the above Javascript followed by a call to window.close()
Assuming you have control over the web page too...
I'm suprised no one brought up the age old meta refresh.
Rather than do some goofy iframe/javascript magic, or some crazy IE COM object mambo, you could always write a meta refresh tag into your given a certain querystring is passed (or all the time, I don't know what your needs are)
Again, I'm not sure this suits your needs, but it is quick and pretty clean.
put this in your and it will refresh the page once every 60 seconds:
<meta http-equiv="refresh" content="60">

Categories

Resources