.Net
4 December 2007 in .Net & Code & Tools | Comments (5)
After yesterdays post I thought I should write up a basic sample to test the effectiveness of the Parallel Extensions. Admittedly it is a contrived example and you are unlikely to see this sort of performance increase in a real world since your applications are unlikely to be this primitive.
My sample iterates through a number sequence from 0 upwards and works out if the value is a prime number. There are two implementations, one using a standard loop and the other using a Parallel.For(). Of course, to try and ride out any spikes I iterate the tests 25 times and then average the outcome. This test is of course not run in a clean environment but does give a roughly indicative result of using the Parallel Extensions.
Using a dual core system, checking the numbers up to 100, 000 and running 25 iterations of each run I had the following outcome:
Using a normal for() loop: 3104 milliseconds average per run
Using a Parallel.For() loop: 1607 milliseconds average per run
This speed up is acceptable and, as you can imagine, these sorts of results are only going to become more impressive as we move to 8, 16, 32 core systems.
A few things to consider in a real world application (consider this my “don’t blame me if you think this will solve all your problems” line! :
- Often slowness is caused by some slow resource – a web connection, a database call etc. The parallel extensions library will default to spinning up as many threads as there are cores and therefore if you have a slow dependent resource you may wish to investigate bumping up the thread count or writing your own threading code.
- The architecture of a solution is more likely to impact the overall performance of the application. Improving the speed of a few loops and LINQ queries will not improve performance by any order of magnitude.
- Amdahl’s Law applies – effectively this law states that the maximum parallel improvement that is possible for an application is limited by the amount of sequential code remaining. For example, if I can only make 10% of the code run in parallel then even with infinitive parallel processes running I’m still running slow sequential code 80% of the time – this feeds back to the previous point.
Download my sample application here (with source)
Note: You will need .Net 3.5 framework installed + the Parallel Extensions Library installed
– JD
3 December 2007 in .Net & Code & Microsoft & Tools | Comments (0)
Just an FYI for anyone that is keeping up parallel computing, Microsoft has released the December CTP of the Parallel Extensions Library.
From my work with it I’ve found it to generally be quite usable however the documentation and general install quality is a little weak at the moment. Even when trying to respond via the email link in the documentation with some suggested documentation changes I found the email was bounced back – not an overly good look but it is early days
The extensions provide parallelisation helpers for both general tasks (e.g. making a for loop parallel) as well as providing PLINQ (one quess for what the “P” stands for!). PLINQ, from my reading, applies only to LINQ to Objects but is a useful start. So far my interest has been in the tasks support.
As a simple example of how to make a loop run using all your cores, here is our original code:
foreach(MyClass c in data) { DoHardStuff(c); }
Here is our code using the Parallel Extensions:
Parallel.ForEach(data, delegate(MyClass c) { DoHardStuff(c); });
As you can see, the extensions make it easy enough to start getting some elementary parallelism working.
The tide is changing
I haven’t heard developers discussing parallelism all that much yet and that concerns me slightly given the impending dependence on parallelisation that high performance software solutions are going to have in the coming years. I wonder if perhaps this is because Microsoft hasn’t released anything specific about it yet (present post topic excluded) and therefore many in the .NET space simply have ignored the parallelisation issues. Certainly some developers are looking at languages such as Erlang which is designed with parallel development in mind and enables the creation of massively parallel software.
A key thing to remember is that parallisation is not a solved problem. Simply dropping in a Microsoft assembly is not going to mean that your solutions are going to run a lot better all the time, hence my advice that developers everywhere should be sharpening their saw and rediscovering exactly what the long bearded lecturer in their computer science concurrency class was babbling about.
I would urge every developer to, at the very least, do some reading up on threading, concurrency and even perhaps try the Parallel Extensions.
– JD
3 November 2007 in .Net & Microsoft | Comments (0)
I’ve just finished my session at Bootcamp in Christchurch, the topic being “C# 3.0 Language Enhancements”. Thanks to everyone who came along, I’m consistently impressed by how laid back things feel when presenting in Christchurch.
As promised, here are my slides and demo’s for download: C# 3.0 Language Enhancements Presentation
Keep in mind that these demo’s are built against Beta 2 of the .NET 3.5 runtime (Orcas Beta 2).
John-Daniel
8 September 2007 in .Net & Code & Windows | Comments (2)
I’m posting this because it escaped my attention initially and I’ve been meaning to post it for any other WPF developers out there who have issues with their bindings.
Whenever doing WPF development make sure that you pay attention to the “output” pane in Visual Studio (or better yet, drag the pane to a second monitor while running the application). Here you will see any errors that are occurring with your WPF bindings. You may even spot some you didn’t know were having problems.
Anybody working with WPF will be using the rich binding capabilities and I’m sure, like me, you get annoyed when things just seem to fail silently behind the scenes. Now you can see what’s really going on.
Hope that helps,
John-Daniel Trask
27 August 2007 in .Net | Comments (9)
I’ve been having an issue with creating a custom re-usable UI for a WPF application I’ve been working on. After creating a UserControl and then placing a ContentPresenter control on it I found that I couldn’t name the elements that I placed within the control when used on a Window. For example:
<Window>
<Controls:MyControl>
<Button x:Name="MyButton"/>
</Controls:MyControl>
</Window>
Doing so would throw an error similar to:
Cannot set Name attribute value 'MyButton' on element 'Button'. 'Button' is under the scope of element 'MyControl', which already had a name registered when it was defined in another scope.
After spending some time on the issue and not spotting a resolution online I finally worked out what was going on. The issue arises because I created a normal UserControl in Visual Studio – the type that has a class file and a xaml file. That’s the deal breaker right there – at least in the current versions of WPF, this technique is not supported in that fashion. You must only have a class file when wanting to display named child content inside your UserControl (This applies to custom Windows as well).
This means we need to get rid of the .xaml file and add all the controls in the class file. I chose to override the OnInitialized event, create the chrome of my UserControl, assign the Content of the control to the Content property of the ContentPresenter and then assign the root UIElement I had created to the Content of the UserControl – simple as pie
And for a code example:
public class MyControl: UserControl { protected override void OnInitialized(EventArgs e) { base.OnInitialized(e); Border border = new Border(); border.VerticalAlignment = VerticalAlignment.Stretch; border.HorizontalAlignment = HorizontalAlignment.Stretch; Grid grid = new Grid(); ContentPresenter content = new ContentPresenter(); content.Content = Content; grid.Children.Add(content); border.Child = grid; Content = border; } }
Now if we used the code at the start of this post on a Window we would get no errors and it would work perfectly.
Hope that helps,
John-Daniel Trask
12 June 2007 in .Net & Code & Mindscape & Tools | Comments (2)
In my previous post about LightSpeed I discussed setting up a very basic LightSpeed instance but didn’t go into any detail about working with the data once we had configured it. In this post we’ll have a look at some basic ways of performing CRUD actions on our database through LightSpeed.
Creating Objects
To create an object we simply need to create an instance of our model class and assign the properties that we want set. This isn’t complicated and not LightSpeed specific so this isn’t a difficult mechanism to understand.
ConfigurationItem item = new ConfigurationItem(); item.ReferenceName = referenceName; item.ValueType = type; item.DisplayName = displayName; item.Description = description; item.Value = value; Repository.Add(item); Repository.CompleteUnitOfWork();
The important part here is at the end where we add the item to the repository and then tell the repository to complete the associated unit of work.
Retrieving Objects
There are many ways to retrieve objects in LightSpeed but I will detail two basic queries here. Retrieving my primary key and retrieving by a single field.
// Find the configuration item that has a primary key of 2 ConfigurationItem configItem = Repository.Find<ConfigurationItem>(2);
Here is a query by the DisplayName property which is just a normal property, not a primary key.
// Create a query to get an entity where the property "DisplayName" is equal to "Example" QueryExpression query = Entity.Attribute("DisplayName") == "Example"; // Get a collection of items that match that query from the database IList<ConfigurationItem> items = Repository.Find<ConfigurationItem>(query);
Queries certainly are a breeze when working with LightSpeed. In later posts we will look at more advanced queries that have multiple criteria.
Updating Objects
Updating an object with LightSpeed is an easy operation of just updating one or many properties on your entity and telling the repository to save those changes.
// Retrieve an object ConfigurationItem configItem= Repository.Find<ConfigurationItem>(2); // Update the display name configItem.DisplayName = "My Updated Display Name" // Save the changes to the database Repository.CompleteUnitOfWork();
Deleting Objects
Last but not least we occasionally need to delete data from our database.
// Get a configuration item of primary key 2 ConfigurationItem configItem = Repository.Find<ConfigurationItem>(2); // Mark the entity as deleted Repository.Remove(configItem); // Save the change, actually commiting the delete to the database Repository.CompleteUnitOfWork();
Now we have walked through CRUD interactions through LightSpeed.
Hope that helps,
– JD
11 June 2007 in .Net & Code & Mindscape & Tools | Comments (2)
In the weekend I was reworking a prototype of something I’m working on and I wanted to use LightSpeed to manage the data access and thought it would be appropriate as a code example of how to quickly and easily get started with LightSpeed. To clarify, I only needed LightSpeed for the persistence mechanism as opposed to the full domain modeling capability at this stage of my project.
The Problem
My application needed a mechanism for persisting configuration. The configuration this application stores is extensible and ideally will be extended by 3rd party plug-ins which means I needed to expose a service that can be used by these 3rd parties to store their custom configuration in a manner that will give access both to their plug-in as well as our application.
I’m also a staunch hater of >300KB XML configuration files and it’s early days in the prototype
Step 1: Create your model classes
I have a simple configuration entity that I wanted to be able to persist to a SQLite database (LightSpeed supports many different database engines by the way). At this stage of my prototype I’m effectively only storing a key/value pair, a human readable name and description and a type (e.g. string, color, int). In this code example you will need to reference LightSpeed in your project to gain access to the Entity<> class that we are inheriting off.
Note that LightSpeed takes care of the enum as well and will happily convert it to an int at the database level Too easy.
using System; using Mindscape.LightSpeed; namespace Mindscape.Carbon.Core.Configuration { public class ConfigurationItem: Entity<guid> { public enum ConfigValueType { STRING, INT, COLOR } private string _referenceName; private string _value; private ConfigValueType _valueType; private string _displayName; private string _description; public string ReferenceName { get { return _referenceName; } set { Set(ref _referenceName, value, "ReferenceName"); } } public string Value { get { return _value; } set { Set(ref _value, value, "Value"); } } public ConfigValueType ValueType { get { return _valueType; } set { Set(ref _valueType, value, "ValueType"); } } public string DisplayName { get { return _displayName; } set { Set(ref _displayName, value, "DisplayName"); } } public string Description { get { return _description; } set { Set(ref _description, value, "Description"); } } } }
Step 2: Create your database
Currently you create your database manually however we are working on tools to do this for you. Note that I’m using a GUID as the primary key on this table and we didn’t need to add it to the model object in the previous step, LightSpeed does this for you. You only need to supply the primary key type in Entity
In my case I was using SQLite and just used a simple create table command:
CREATE TABLE ConfigurationItem( Id GUID NOT NULL PRIMARY KEY, ReferenceName NVARCHAR(50) NOT NULL UNIQUE, Value NVARCHAR(100) NOT NULL, ValueType INT NOT NULL, DisplayName NVARCHAR(100) NOT NULL, Description NVARCHAR(1024) NOT NULL);
Step 3: Add LightSpeed to your configuration
We need to tell our application about the database that LightSpeed should be working with and we can do this in code or in the .config file for our project. In this example I’ve elected to put it into the app.config of my project.
<configSections> <section name="LightSpeed" type="Mindscape.LightSpeed.Configuration.LightSpeedConfigurationSection, Mindscape.LightSpeed" /> </configSections> <connectionStrings> <add name="ConfigDB" connectionString="Data Source=MyDatabase.db3"/> </connectionStrings> <LightSpeed dataProvider="SQLite3" connectionStringName="ConfigDB" identityMethod="Guid"/>
Step 4: Work with your data
That’s it! All the configuration work has been completed and there is no heavy XML mapping file or complex setup to tell LightSpeed about the database. The whole philosophy behind LightSpeed is to help developers get work done quickly and I hope this example and your own work with LightSpeed proves that. In following posts I will provide detail about working with your data however here is a taster of how easy it is to now put new objects into the database:
ConfigurationItem item = new ConfigurationItem(); item.ReferenceName = "MyRefName"; item.ValueType = ConfigurationItem.ConfigValueType.STRING; item.DisplayName = "Example Config"; item.Description = "This is an example configuration key"; item.Value = "example"; Repository.Add(item); Repository.CompleteUnitOfWork();
In this example I had an extremely simple model however you can appreciate that there is significantly less leg work required to get a LightSpeed solution up and running. I will post more advanced real world examples to help you gain more from working with LightSpeed in the near future. Also please leave any comments or questions you have on my blog regarding LightSpeed.
How can you use LightSpeed?
We currently are in late beta with an RTM of LightSpeed just around the corner. You can grab the download of LightSpeed from the Mindscape EAP site. You can also post in the forums to discuss any challenges that you have or to ask questions. We welcome any feedback.
Update: LightSpeed was released and is now available to play with here: http://www.mindscape.co.nz/products/LightSpeed/
Hope that helps,
– JD
7 June 2007 in .Net & Code | Comments (31)
Last night I had the opportunity to speak to the Christchurch .NET User Group about web standards and took the opportunity to add some discussion about testing using a tool called WatiN (pronounced “what-in”, horrible I know). From the feedback I’ve received so far the WatiN demo captured everyone’s imagination. I had a great time as well, very friendly folks in Christchurch
WatiN effectively allows you to script interactions with Internet Explorer and do things like fill out forms, click through and test the results that come back. This makes testing things such as a process flow really easy to do in a repeatable manner and included in your unit tests which ideally are being executed as part of your continuous integration processes.
Examples:
The example I demonstrated last night was just doing a simple test of the BackgroundMotion search engine. You can probably understand what is going on just from the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 | [Test] public void TestSearchWithNoResult() { IE ie = new IE(); ie.GoTo("http://backgroundmotion/"); ie.TextField(Find.ById("ctl00_SearchBox")).Click(); ie.TextField(Find.ById("ctl00_SearchBox")).TypeText("beach"); ie.Button("ctl00_Search").Click(); Assert.IsTrue(ie.ContainsText("No results found")); ie.Close(); } |
Automated Validation is a hot topic for me as I really hate working on a project and then remembering to validate well after I wrote the HTML only to find I have a lot of work ahead of me. I wrote the following test code to allow automated posting of web content to the W3C validation service for checking:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | private static bool IsValidPage(string url) { string rawHtml = GetFile(url); IE ie = new IE("http://validator.w3.org/fragment-upload.html"); ie.GoTo("http://validator.w3.org/fragment-upload.html"); ie.TextField(Find.ByName("fragment")).Click(); ie.TextField(Find.ByName("fragment")).Value = rawHtml; ie.Button(Find.ByValue("Validate this document")).Click(); return ie.ContainsText("Is Valid"); } public static string GetFile(string url) { WebRequest myWebRequest = WebRequest.Create(url); WebResponse myWebResponse = myWebRequest.GetResponse(); Stream ReceiveStream = myWebResponse.GetResponseStream(); Encoding encode = Encoding.GetEncoding("utf-8"); StreamReader readStream = new StreamReader(ReceiveStream, encode); string response = readStream.ReadToEnd(); readStream.Close(); myWebResponse.Close(); return response; } |
With these two methods you can do write a test per page to validate the content:
1 2 3 4 5 | [Test] public void TestValidHTML() { Assert.IsTrue(IsValidPage("http://www.mysite.com/mypage.aspx")); } |
Note that this code doesn’t take into account subtle changes with the use of AJAX, it simply gets the raw content from the request. WatiN does however support handling AJAX changes quite nicely so upgrading to support a richer website would not present much of an issue. The interesting thing with the raw request is we could change the agent-type on the request to ensure that we’re getting valid HTML for various browsers despite being called from one central location. This can be great if you’re working with ASP.NET where the server controls will be rendered differently based on the agent type by default.
The code also doesn’t take account of potential network connectivity issues and was more for showing the sort of things that you might want to do with WatiN. WatiN is certainly a useful tool to have in your toolbox. If you want to learn more about WatiN just pull it down and also grab one of the few WatiN recorders as the one listed below and get a kick start in scripting your site interactions.
The Tools
WatiN: http://sourceforge.net/projects/watin/
WatiN Recorder: http://watintestrecord.sourceforge.net/
Hope that helps,
- JD