JavaScript Threading - Part 1 (Timers)



In the first part of this series we're going to have a look at timers (setTimeout and setInterval functions).

Technically these functions are actually pseudo-threaded (looks like a dog, smells like a dog, barks like a dog, humps like a dog, not a dog) - they don't spawn new threads, but instead they cleverly get executed/queued on a single thread (along with other asynchronous events).

The first function we're going to look at is the setInterval function. This function accepts three arguments, of which the first one is a callback, the second an interval (in milliseconds) of when the callback will be executed.

The third argument is optional and sets the language (of the callback script I guess ?) - I've personally never used this argument, and can't see why any sane person would want to, can somebody enlighten us ? My guess is it's got something to do with the client-side vbscript days, allowing one to mix vbscript and JavaScript in Internet Explorer (puuuuukkkke) ?

In the following snippet we use the setInterval function to display the current time and update it every second (a basic time ticker).

Snippet 1
<div id="currentTime"></div>
<script type="text/javascript">
var timer = setInterval(
	function() 
	{
		var time = new Date().toLocaleTimeString();
		$('#currentTime').html(time); // assuming you're using jQuery
	}, 1000
);
</script>

Note that the value returned by this function can be used to stop the timer using the clearInterval function, e.g. "clearInterval(timer)".

It's also prudent to point out that our callback will automatically get re-executed irrespective of when/if the previous callback finished executing, so take care when putting code in your callback that can potentially exceed your interval, which brings me to our next timer function - setTimeout.

The setTimeout function has the exact same arguments as the setInterval function, the only difference however is that this function doesn't automatically continuously call its callback - which gives us a bit more control over our timer.

In the following snippet we use the setTimeout function to populate a div on our page via an ajax request (using jQuery).

Snippet 2
<div id="results"></div>
<script type="text/javascript">
 
	function GetResults() 
	{
		var timeout = 1000;	// 1 second
		$.ajax(
			{
				url: 'http://cstruter.localhost/tests/timers/results.php',
				cache: false
			}				
		).done(function(data) {
			$('#results').html(data);
			setTimeout(GetResults, timeout); // only call the function again once we're done
		}).fail(function(jqXHR, textStatus, errorThrown) {
			if (confirm("Error sending request, try again?")) {
				setTimeout(GetResults, timeout); // try call the function again	
			}
		});
	}
 
	GetResults();
 
</script>

You'll notice that we only set our delayed callback as soon as we had a succesful response back from our server, when something goes wrong with our response, we prompt the user to try again.

Note that like the setInterval function, we've got a function to stop our setTimeout as well - clearTimeout.

Now in the beginning of this post I mentioned that these functions are actually pseudo-threaded in that it runs on the same thread. To demonstrate the problem with this (from a threading perspective) you need to run the following snippet along with snippet 1.

Snippet 3
setInterval(
	function ()
	{	
		var j = 0;
		for (var i = 0; i < 1000000000; i++) { j++; } // simulate some intensive work
	}, 1000);


You will notice that now instead of getting a nice smooth time ticker, the ticker starts to lag behind a bit, skipping seconds. Which is obviously not the ideal behavior we're looking for but obvious seeing that we're doing everything on one thread.

Wouldn't it be nice if we could put the problem function in its own isolated thread? Leaving the UI thread open for all things UI?

In the next part we're going to have a look at doing exactly that using web workers.




Post/View comments
 

MS SQL: Parameter Sniffing



A while ago one of our clients reported a bit of a peculiar performance problem when accessing a certain report in one of their systems. Generally they could retrieve the report in no time, but all of a sudden it took about 3 minutes to retrieve a relatively small amount of data.

Strangely enough the older entries for this report could still be retrieved almost instantly.

So I went through all the motions to find a solution and analyzed the database, found it to be terribly designed and poorly maintained. The developer didn't even bother to create indexes for any of the foreign keys.

Like a good Jedi I added the appropriate indexes for the appropriate fields, but that just made things worse, it now oddly enough even took longer to retrieve data.

I decided to have a look at the guilty stored procedure only to astonishingly find that the stored procedure runs super fast within SSMS (SQL Server Management Studio).

At this point I got up and phoned an exorcist, they came out and prayed over the source code and anointed the server while a bunch of scary looking evil spirits seeped out of the sides of the server box like toxic gases.



Unfortunately that didn't solve the problem at all (fixed an unusual buzzing sound I've been hearing lately though), but all of a sudden I heard the voice of my old master Obi-Wan Kenobi telling me to use the force (google).

I opened my browser and did some research using Google and found the real reason - parameter sniffing.

Uhm okay, maybe I stretched the truth a bit in the last few paragraphs (they're complete BS, except for the google part).

What is parameter sniffing all about?

When sending parameters to a stored procedure for the first time, SQL generates an execution plan based on those parameters and stores it for reuse (generating these plans can be resource intensive & lengthy at times, therefore storing it will improve performance).

Note that we wont necessarily only have one execution plan for a stored procedure, SQL will generate multiple plans based on various settings.

Now sometimes it happens that the stored execution plan sucks, so instead of being efficient it might turn out to be terribly inefficient.

So how do we solve this problem?

One popular solution is to reassign parameters to local variables like seen below (theory being that SQL won't/can't create a cached execution plan thanks to the local variables).

 
CREATE PROCEDURE [dbo].[ProcedureName]
  @Param1 DATETIME, 
  @Param2 DATETIME
AS
BEGIN
	DECLARE @LocalParam1 DATETIME
	DECLARE @LocalParam2 DATETIME
 
	SET @LocalParam1 = @Param1
	SET @LocalParam2 = @Param2
 
	-- Logic
END
 


Another option is to disable parameter sniffing alltogether for a stored procedure by creating it using the "WITH RECOMPILE" option like seen in the next snippet.

 
CREATE PROCEDURE [dbo].[ProcedureName]
  @Param1 DATETIME, 
  @Param2 DATETIME
WITH RECOMPILE
AS
BEGIN
	-- Logic
END
 


One can also disable sniffing per query using OPTION (RECOMPILE).

 
CREATE PROCEDURE [dbo].[ProcedureName]
  @Param1 DATETIME, 
  @Param2 DATETIME
AS
BEGIN
	SELECT * FROM SometTable
	WHERE SomeDate BETWEEN @Param1 AND @Param2
	OPTION (RECOMPILE)
END
 


Or optimize for a typical parameter value.

 
CREATE PROCEDURE [dbo].[ProcedureName]
  @Param1 DATETIME, 
  @Param2 DATETIME
AS
BEGIN
	SELECT * FROM SometTable
	WHERE SomeDate BETWEEN @Param1 AND @Param2
	OPTION (OPTIMIZE FOR (@Param1 = '2012/02/02'))
END
 


As of MSSQL 2008 its possible to use the optimize for "UNKNOWN" hint which instructs the query optimizer to use statistical data instead of the initial values for all local variables when the query is compiled and optimized.

 
CREATE PROCEDURE [dbo].[ProcedureName]
  @Param1 DATETIME, 
  @Param2 DATETIME
AS
BEGIN
	SELECT * FROM SometTable
	WHERE SomeDate BETWEEN @Param1 AND @Param2
	OPTION (OPTIMIZE FOR (@Param1 UNKNOWN, @Param2 UNKNOWN))
END
 


I am not going to go into too much detail about the pros/cons of each solution, but you can read a lot more about this issue over here.




Post/View comments
 
First 1 2 3 4 5 6 7 8 9 10 Last / 65 Pages (130 Entries)

Latest Posts

MS SQL: Parameter Sniffing


2012-05-21 22:38:48

Be the best stalker you can be


2011-12-13 22:33:54

Top 5 posts

Moving items between listboxes in ASP.net/PHP example


Move items between two listboxes in ASP.net(C#, VB.NET) and PHP
2008-06-12 17:07:43

Simple WYSIWYG Editor


Creating a WYSIWYG textbox for your website is actually quite simple.
2007-02-01 12:00:00

C# YouTube : Google API


Post on how to integrate with YouTube using the Google Data API
2011-03-12 08:37:51

Populate a TreeView Control C#


Populate a TreeView control in a windows application.
2009-08-27 16:01:03

Cross Browser Issues: Firefox Word Wrapping


Firefox word wrapping issues
2008-06-09 09:51:21