April 2007 - Posts

Beginning ASP.NET AJAX Book Cover
Saturday, April 28, 2007 6:07 PM

Wally thought he might offer some suggestions as to what our new book cover should be (due out very soon). You can see them here and in addition, Julie Lerman has also offered some alternatives here.

Can't say they appeal to me that much so I thought I'd offer one of my own. Hows this? I think you'll agree that the picture of Wally (far left) is much more apealing than the original.

WCF Client Performance
Saturday, April 21, 2007 6:22 PM

One of the easiest performance traps when using WCF services is constant creation of new client proxies when accessing those services. In WSE land, this was common place:

MyProxy prox = new MyProxy();
prox.CallServiceMethod();

For example, you might have a class with some instance methods, and in each method, instantiate a proxy, call the service method, life is good.

However, doing this in WCF can incur some performance penalty. Ideally, you should create a proxy class once and open it, then use that same proxy class in all your methods (note: this is a contrived example) so that you dont have to re-create and open the proxy.

Its not the creation of the proxy itself that is the issue, its when you call the "Open" method on the proxy, which opens the corresponding channel, and typically initiates a secure conversation (when using this feature) and this costs quite a bit.

Now in ASP.NET, the constant creation of proxy objects, opening and calling of methods is pretty common, especially given that at the end of each request, most resources are discarded, ready for the next request (generally speaking).

I found this issue somewhat odd as its an easy thing to miss, again especially in the ASP.NET world where creation, usage and destruction of objects is common place.

So, I have been tinkering with the concept of a traditional object pool of proxies ready to use, managed for you by an underlying object pool mechanism, much like the thread pool. I tried maintaining a proxy pool but found this to be not very beneficial and harder than I had liked. What I have settled on is an actual Channel pool that underlies the proxy itself. Initial tests (only using wsHttpBinding at this stage) show an approximate 25%-50% speed improvement over traditional methods, with hardly any extra work.

In WCF you might create a proxy like so:

public class MyProxy : ClientBase<ISomeInterface>, ISomeInterface
{
   public void MyInterfaceMethod(string s)
   {
      Channel.MyInterfaceMethod(s);
   }
}

Using my Channel pool implementation, you simply do:

public class MyProxy : ClientBasePool<ISomeInterface>, ISomeInterface
{
   public void MyInterfaceMethod(string s)
   {
      Channel.MyInterfaceMethod(s);
   }
}

And you use it as you normally would:

MyProxy prox = new MyProxy();
prox.MyInterfaceMethod("Hello");
prox.Close();

Behind the scenes, a pool of channels are kept ready, opened, and ready to use. The pool is refilled asynchronously in the background at a oredefined trigger point.

Here are some very initial and totally unscientific performance tests:

The tests themselves are really basic and the services are those generated by the default "create WCF service" project template (with a few mods). This first screen shot shows the tests being run for 50 iterations and also are being run twice so that the second set of results is probably the more realistic ones (everything has been jitted, warmed up etc....)

You'll see the ClientPoolBase tests have executed in half the time.

You'll also notice I include the same series of tests but using only 1 proxy object for comparison (and as expected, its much faster).

Here are the same tests run for 2000 iterations.

Again, another 50% approximate improvement.

I am pretty happy with the results thus far but need to do a lot more testing under various conditions. Initially it may be restricted to only the wsHttp binding as I haven't tested at all with netTCP but ofcourse, its a faster protocol anyway so it may not be necessary. Also, I need to ensure that it is reliable when unused for long periods (take into account timeouts) and so forth. We shall see.

I will post the code for this soon if anybody is at all interested once I get a chance to put it through some more tests.

WCF Atomic Transactions - GUI Configuration
Thursday, April 12, 2007 11:28 PM

If you play with WCF and would like an easy, graphical way to enable and configure basic options of the the WS-Atomic transaction support of WCF, you can do the following:

(Note: I did this recently as I had to rebuild a new laptop so I thought I'd mention it here for the benefit of anyone else).

I am running this within Vista, although it should be "similar" for other OS flavours.

1. Install the .Net 3.0 (Vista) SDK.

2. As an administrative user, go to a .Net command prompt and navigate to "C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin"

3. Type 'regasm /codebase wsatui.dll'

4. Now load up the Component Services management console. You can do this by going to 'Start --> Run --> MMC'

5. Once the MMC console is up, select 'File --> Add/Remove Snap-In --> Component Services'. Cick 'Add' button, then click OK.

6. Expand out the tree until you find the 'Local DTC' node as shown below, right click on it and select 'Properties':

7. Select the 'WS-AT' tab and there you have all your WS-Atomic Transaction settings. (Note that I dont have the DTC access allowed at the moment so the options are greyed out).

Windows Easy Transfer
Thursday, April 12, 2007 10:50 PM

I just got me a new Dell XPS M1710 with all the bells and whistles. I thought this would be a good opportunity to try out the Windows Easy Transfer as my old Dell had Windows Vista already installed on it.

I must say, it was quite painless and pretty damn easy. Backed up to a USb removable drive, then did some basic setup on my new laptop, such as joining my work domai. I had 2 users, a local user and my domain user, both of which had the same account names as on my old laptop.

On the new laptop, I fired up easy transfer and pointed it at the backup images performed previously. It recognised my 2 accounts on my current laptop and matched them up with the profiles on the backup images. I hit transfer to grab all the data and let it run.

It all migrated perfectly, including desktop icons, Outlook accounts, one note settings. It was quite nice to not have to do all that. The backup and restore process did seem quite slow though, but if I had to do it all manually, it probably would have taken somewhat longer, with considerably more effort.

All in all, I was pretty impressed by the feature.

Want an XBox 360?
Saturday, April 7, 2007 1:18 PM

Sonu Kapoor asked I mention a competition he has running on his DotNetSlackers site. All you have to do is write an article, and your automatically in the running to win an Xbox 360 Core system!

Sounds easy enough right? Well head on over to here and start writing....

Industrial Strength WPF
Thursday, April 5, 2007 7:20 PM

readify, the people that feed my kids and keep me off the streets, are putting on another high quality Industrial Strength course around Windows Presentation Foundation.

One of the industry gurus around this topic, Ian Griffiths is running this 4 day extravaganza.

I was lucky enough to attend the WCF Industrial Strength course which was run by Juval Lowy of IDesign, and that was absolutely brilliant for in depth fast track learning.

I encourage you to jump on over to here and have a look at what the course offers. Its a good opportunity to get in early and get some real in depth knowledge on using this technology.

CodeCampOz 2007 AJAX Demo
Thursday, April 5, 2007 5:58 PM

As part of CodeCampOz 2007, Damien and myself co-delivered a presentation on real life experiences with ASP.NET AJAX. Damien has already posted some content on what he delivered and so I thought I'd do the same.

The demo code I used can be download from here.

My demo was fairly simple, and showed a basic way of achieving a partial page load of the pages content to maximise what I like to call "data entry dead time". Basically this is just where the user is performing some form of data entry, particularly on pages with a reasonable amount of fields to deal with. During this time, it provides a good opportunity to load other parts of the page for display and data entry.

In this way, you can load a very small portion of the page, and have the rest of the content load while the user is busy entering away. In the situation I used this it worked well as the link was quite poor and allowed a smaller first portion of the page to load, then the subsequent sections. This occured without interruption to the user and allowed data entry to contine on the page.

So on first page load, you get an initial set of data entry fields.

Then as you type, you get more....

And finally.....

The markup required to do this is quite simple. 1 initial panel for the data entry, and 2 subsequent panels whose Visible=False is initial set, and which are contained within UpdatePanels. The first UpdatePanel has a timer enabled which acts as a trigger for its UpdatePanel. The second UpdatePanel also has a timer, but its initially disabled. When the first timer triggers its panel, in the code behind, the timer disables itself, sets the panels visibility to true, and enables the next timer. The next timer, when triggered, disables itself within the code behind, sets its corresponding panel visibility to true.

The markup is:

 

<asp:Panel ID="Panel1" runat="server"> <h4>Section 1</h4> <label id="Label20">Entry field 1:</label><asp:TextBox ID="TextBox18" runat="server"></asp:TextBox> <label id="Label21">Entry field 2:</label><asp:TextBox ID="TextBox19" runat="server"></asp:TextBox><br /> <label id="Label22">Entry field 3:</label><asp:TextBox ID="TextBox20" runat="server"></asp:TextBox> <label id="Label23">Entry field 4:</label><asp:TextBox ID="TextBox21" runat="server"></asp:TextBox><br /> <label id="Label24">Entry field 5:</label><asp:TextBox ID="TextBox22" runat="server"></asp:TextBox> <label id="Label25">Entry field 6:</label><asp:TextBox ID="TextBox23" runat="server"></asp:TextBox><br /> </asp:Panel>

 

<asp:UpdatePanel ID="up2" runat="server" UpdateMode="Conditional" > <ContentTemplate> <asp:Panel ID="pnl2" runat="server" Visible="false" EnableViewState="false" > <h4>Section 2</h4> <label id="Label3">Entry field 1:</label><asp:TextBox ID="TextBox3" runat="server"></asp:TextBox> <label id="Label4">Entry field 2:</label><asp:TextBox ID="TextBox4" runat="server"></asp:TextBox><br /> <label id="Label5">Entry field 3:</label><asp:TextBox ID="TextBox5" runat="server"></asp:TextBox> <label id="Label12">Entry field 4:</label><asp:TextBox ID="TextBox12" runat="server"></asp:TextBox><br /> <label id="Label13">Entry field 5:</label><asp:TextBox ID="TextBox13" runat="server"></asp:TextBox> <label id="Label14">Entry field 6:</label><asp:TextBox ID="TextBox14" runat="server"></asp:TextBox><br /> </asp:Panel> <asp:Timer ID="tmr1" runat="server" Interval="1000" Enabled="true" OnTick="tmr1_tick" /> </ContentTemplate> </asp:UpdatePanel> <hr /> <asp:UpdatePanel ID="up3" runat="server" UpdateMode="Conditional" > <ContentTemplate> <asp:Panel ID="pnl3" runat="server" Visible="false" EnableViewState="false"> <h4>Section 3</h4> <label id="Label6">Entry field 1:</label><asp:TextBox ID="TextBox6" runat="server"></asp:TextBox> <label id="Label7">Entry field 2:</label><asp:TextBox ID="TextBox7" runat="server"></asp:TextBox><br /> <label id="Label8">Entry field 3:</label><asp:TextBox ID="TextBox8" runat="server"></asp:TextBox> <label id="Label15">Entry field 4:</label><asp:TextBox ID="TextBox15" runat="server"></asp:TextBox><br /> <label id="Label16">Entry field 5:</label><asp:TextBox ID="TextBox16" runat="server"></asp:TextBox> <label id="Label17">Entry field 6:</label><asp:TextBox ID="TextBox17" runat="server"></asp:TextBox><br /> </asp:Panel> <asp:Timer ID="tmr2" runat="server" Interval="1000" Enabled="false" OnTick="tmr2_tick" /> </ContentTemplate> </asp:UpdatePanel>

And the codebehind is:

protected void tmr1_tick(object sender, EventArgs e) { System.Threading.Thread.Sleep(5000); tmr1.Enabled = false; tmr2.Enabled = true; pnl2.Visible = true; } protected void tmr2_tick(object sender, EventArgs e) { System.Threading.Thread.Sleep(5000); tmr1.Enabled = false; tmr2.Enabled = false; pnl3.Visible = true; }

And thats it. Sorry for the lengthy post.

Now the wierdness happens when you disable ViewState on the page OR you EnableEventValidation, which causes the page to throw an exception whenever a normal or async postback occurs.

The EventValidation error occurs because you are dynamically enabling more input controls than what the page is expecting to receive as submitted data. So when the page is submitted, it compares what it receives, to what it calculated as part of the EvenValidatin signature when the page was initially rendered and because we are enabling more controls to be submitted than originally rendered, an error occurs.

As to the viewstate issues, thats a post for another day.

WCF Performance Whitepaper - realistic?
Thursday, April 5, 2007 12:00 AM

I recently looked through a WCF Performance whitepaper published by Microsoft and was a little puzzled by some of the comparisons.

It seems a little skewed towards presentation of graphs showing WCF superiority in performance over current communication and service methods. Now I am confident that WCF is faster in almost every scenario, however a number of things stood out as being a little odd.

Namely:

  • Use of WSE v2 instead of WSE v3. The article states "The comparison in this case is with WSE 2.0 but it should be noted that the performance of WSE 2.0 and 3.0 are similar for this payload." That maybe so, but why wouldn't you use WSE v3?. Surely this is far more comparable than WSE v2 ?
  • When comparing WS-Security performance, the basicHttpBinding with MessageCredentials was also included as part of the comparison, which I dont consider a valid comparison as the equivalent was not done with WSE. Obviously, the basicHttpBinding is much faster (and shows a nice comparitive graph as a result) but it seems this was done so that a much larger graph could be included in the report.
  • Again, when comparing WSE and WCF performance, no mention was made of how the clients were used. It is reasonably well known that if you re-create the proxies for each request (or set of requests) with WSE, there is not much of a perf hit, however with WCF, if you re-create the proxies, there is a considerable performance hit and can cause the WCF performance to degrade overall (Note: Not the ability of the service to deal with the request but the whole client -> server -> back to client trip). I assume the tests did not re-create the proxies, however it is not clear and I think this should at least be noted and mentioned.

Like I said, I know that WCF is faster, but I'd like to see:

  • A more detailed breakdown of the various scenarios
  • More detail around the test specifics like client access methods, proxy creation etc...
  • Valid comparitive technologies ie. not WSE v2 but using WSE v3.
by Glav | 3 comment(s)
Filed under: , , , ,
Its an MVP Frenzy
Monday, April 2, 2007 12:27 PM

I'd like to congratulate my fellow readify colleagues and all round good guys for receiving MVP Awards this year:

Paul Stovell: MVP in Visual Client Application Development

Grant Holliday: MVP in Visual Developer Team System

Philip Beadle: MVP in Visual Developer ASP/ASP.NET

Congratulations guys, well deserved.

by Glav | with no comments
More Posts

This Blog

Syndication