Pages

Monday 9 November 2009

Windows 7 and the Press

I was replacing Windows 7 beta with Windows 7 Release Candidate on my laptop a few months ago... And I was joking with colleagues about the future success of this new version. Having used Vista for two years
Windows 7 didn't strike me as an earth-shattering evolution. Yet we predicted that people would rush on Windows 7 like bees on cupcakes for two main reasons:
  • the press was very positive about Windows 7 after it slaughtered Vista
  • the Release Candidate was as good as the final thing and free to use until March 2010. In other words people could use a fully working OS for free for 10 months.
I don't think Vista deserved the bad press it received. I used it for two years: RC1 and RC2 on an old PC then the RTM 32-bit and eventually 64-bit on my main machine.
Driver issues? A bit at the beginning but nothing that couldn't be overcome.
Speed issues? Desktop: nothing that I could notice on a 4GB dual-processor Dell with raid-striped 15000rpm SAS drives. Laptop: browsing the web was fine, Visual studio was slow. After I moved to Windows 7 browsing the web was still fine and Visual Studio still slow.

When I removed Vista 32-bit from my Vaio and installed Windows 7 RC, it indeed felt a bit snappier. But again, ANY version of Windows feels snappier after a fresh install.

Whether you run XP, Vista or Windows 7 the OS you're running on a machine does not matter as much as the following factors:
- how fresh the install is: re-install your OS often, with a bit of organisation it can be quick.
- the amount of RAM: install more than you think you'll need.
- the hard drive speed: one 15000rpm drive is good, two are better.


I might oversimplify a bit, still I think there are mostly two reasons why you want to upgrade to a new OS:
  • the untold one: it looks better than the previous version.
  • the one you tell people to look clever: the OS is faster, contains bug fixes and new useful features.
Thanks to unbalanced press opinions Windows 7 at last gives people an excuse to cave in to the first reason while being covered by the second.

Monday 2 November 2009

Books I currently flip through #7

Technology
Methods
  • Apprenticeship Patterns, 1st Edition
    image
Finance
  • The (Mis)behaviour of Markets (Benoit Mandelbrot)
    image
 
Others
  • Blink (Malcolm Gladwell)
    image
  • The Black Swan (Nassim Nicholas Thaleb)
    image

Sunday 1 November 2009

Trying out TeamCity and CruiseControl

A few teams use Cruise Control at work. It seems to be a fairly standard choice when it comes to continuous integration. Roy Osherove recommends TeamCity over CruiseControl because he doesn't like getting his hands dirty with XML configuration (can't blame him).

I tried both to get a feel of what you can do with them. I ran TeamCity of my main machine and CruiseControl on a VM to avoid clashes.

I managed to get a build running in TeamCity without too much difficulty. I installed the tray notifier.

CruiseControl is a bit more tricky. After I edited the config files I kept getting exceptions when trying to startup ccnet.exe. Had to go through several install iterations before getting something running.

Installing TeamCity:
  • Install Tortoise SVN
  • Install VisualSVN Server
  • Run the TeamCity installer
  • Start the build agent manually (rather than through a Windows service).
  • Install the TeamCity Windows tray notifier


Installing Cruise Control inside a virtual machine.
  • Windows Virtual PC RC, wich is a new version of Virtual PC for Windows 7.
  • Install Virtual Server 2008
  • Install SVN command line  
  • Edit the ccnet.config file
  • Get the Web Dashboard working:
    • Install IIS: under Windows Server 2008, it's not a Windows feature any more, it's a server role. You have to go to Server Manager > Roles > Add Roles and follow the wizard to add IIS.
    • Run the CruiseControl.Net installer
    • Create a new application in IIS for the ccnet webdashboard. In Server Manager, go Roles > Web Server (IIS) > Internet Information Services, open Sites > Default Web Site. Right-click Default Web Site and choose Add Application. Set Application Pool to Classic .NET AppPool.







Saturday 31 October 2009

How to re-build your PC in less than 2 hours

Pre-requisites:
  • Your data on D:, the OS on C:
  • Your backup ready (nothing to do because you have an automatic full D-drive incremental back-up scheduled to run every day )
  • Your CD case with all legally acquired original CDs for software and drivers
  • Access to the spreadsheet where you carefully store all serials for the above.
Go:
  1. Boot from DVD
  2. Format C:.
  3. Click Next, OK, next, Ok, I agree, OK, Next, London GMT
  4. Install your favorite software. For me it is:
    1. Kaspersky
    2. Office
    3. Chrome, Firefox
    4. Skype, Live Messenger
    5. Visual Studio
  5. Check the time: if it took you more than 2 hours, start all over again.

Sunday 27 September 2009

Reading the SQL Server Execution Plan

We're having a pretty good weather in London: still sunny and about 18C. I took the bicycle to Hampstead Heath with the VAIO in the rucksack and started looking into SQL performance tuning, as you do.

Went through SQL Server 2008 Query Performance Tuning Distilled in Safari.

Here are a few reading notes...

What are the different types of joins?
  • nested loop join: the most intuitive one. This is the sort of join you would write if you were to code it in C++: iterate over the smallest table first and for each row, look for a match in the other table. Efficient only if the first input is small, and the second is large and indexed.
  • hash join: used if the largest input is not indexed. This is done in two steps:
step 1: builds a hash table with the smallest of both inputs. This hash table uses a hash function to associate a value in the joined column with an index to a bucket. Go through the whole input row by row and add each row to its appropriate bucket using the hash function.
step 2: go through the second input row by row. For each value in the joined column, work out the index to the bucket in the hash table using the hash function. If a row is present, then there is a match and the row is kept in the result set.
  • merge join: used if an index exists on the join columns of both tables. The join columns are sorted in both tables using the indexes. Then comparing columns is relatively fast because it takes advantage of the ordering.
What is a RID Lookup?
  • If a table does not have a clustered index, data pages are on the heap.
  • If a table has a clustered index, they are inside the clustered index.
Non clustered indexes contain pointers to table rows: this pointer is either
  • a RID (Row ID) if the table is on the heap
  • or a clustered index key if the table has a clustered index.

A RID lookup takes place on a heap table (table without clustered index). In order to locate data using a non clustered index SQL Server uses the RID to locate the data row in the heap. A RID lookup is costly because it involves an extra page read (on top of the page read needed for the non clustered index). You wouldn't get this extra page read with a clustered index.

How to see the execution plan directly from the SQL profiler?
This is very handy! No need to try and re-run a slow query in SSMS. Simply track the event ShowPlan XML in SQL Profiler under the Performance group. When you run the trace you can see the actual execution plan of any statement. The plan is displayed in a graphical way as in SSMS.
Warning, not to be used in production! It slows down the performance of the database quite a lot.

More about indexes:
Index Analysis
Index Design Recommendations 

Other resources:
Checklist for analysing slow-running queries




Thursday 18 June 2009

XPath

XPath came handy lately as I needed to look-up an in-memory XML document.
I know it's probably smoother with Linq to Xml but my project had to compile under VS2005 so I used the .NET 2.0 library which does not contain Linq but contains XPath.

Starting from the following xml file:

<?xml version="1.0" encoding="utf-8"?>
<pigs>
  <piggy infected="false" name="bob"/>
  <piggy infected="false" name="alfred"/>
  <piggy infected="true" name ="rodrigo">
    <disease name="swine flu"/>
    <disease name="boredom"/>
    <disease name="pig blues"/>
    <address>confidential</address>
    <phonenumber>01234546576</phonenumber>
  </piggy>
</pigs>


To load the XML in memory:

XmlDocument doc = new XmlDocument();

try

{

doc.Load("piggy.xml");

}

catch (XmlException e)

{

Console.WriteLine("Could not load the file. Detail: " + e.Message);

}



To query elements based on their name:

XmlNodeList allPigs = doc.SelectNodes("/pigs/piggy"); // Returns all nodes called 'piggy' located inside the root-level node called 'pigs'.

foreach (XmlNode node in allPigs)

Console.WriteLine(node.Name + " " + node.Attributes["name"].Value);



To query elements based on their attribute name:

// Returns only infected pigs

XmlNodeList infectedPigs = doc.SelectNodes("/pigs/piggy[@infected='true']");

foreach (XmlNode node in infectedPigs)

Console.WriteLine(node.Name + " " + node.Attributes["name"].Value);


To return a single node (same query as above but only one node is expected):


// Returns the single infected pig

XmlNode infectedPig = doc.SelectSingleNode("/pigs/piggy[@infected='true']");

if (infectedPig != null)

Console.WriteLine(infectedPig.Name + " " + infectedPig.Attributes["name"].Value);


To do a query relative to the current node:
All queries above were made relative to the top of the document. But it you call SelectNodes against an XmlNode, you can do a query relative to that node. Just ommit the '/':

// Query relative to the current node. Returns all diseases for the infected pig

XmlNodeList diseases = infectedPig.SelectNodes("disease");

foreach (XmlNode node in diseases)

Console.WriteLine(node.Name + " " + node.Attributes["name"].Value);



Resources:
MSDN: XPath Syntax
LINQ to XML queries
XML Support in SQL Server 2005

Monday 1 June 2009

Webforms vs MVC (London .NET User Group)

100 people listened to Sebastien Lambla and Phil Wistanley at the Microsoft customer centre in Victoria. They talked for 2 hours without a break. Two hours is a long time but the formula they adopted was entertaining and fun. Seb was supporting MVC, Phil Webforms. They kept rotating at the mike, going through humorous slides, throwing jokes at each other and interacting with the audience. Seb:
  • Webforms has a tendency to hide HTML and actually generates a lot of goo.
  • MVC relies on you knowing HTML but once you learn it, things get pretty easy.
  • Webform's page lifecycle is complex
  • Webforms is for morons.
Phil:
  • MVC is too complicated,
  • Webforms has a lot of ready-made controls, lots of 3rd party vendors
  • Uses a familiar event model
  • MVC is for hippies.
To sum it up, Webforms is for building apps quickly (better suited for the financial world), MVC is good if you need a high level of quality and testability.

Friday 15 May 2009

C++/CLI Cheat Sheet

My C++/CLI pocket reference...
  • Declare a string

System::String^ myString = "";

  • Declare a null reference

System::String^ myString = nullptr;

  • Pass a string by reference to a method (the reference to the string will be modified, not the string itself since strings are immutable). Use %:

void MyMethod(System::String^% myString)

{

}

  • Declare an array of strings
    cli::array<System::String^>^ stringArray = gcnew cli::array<System::String^>{"Skype","Blogger"};
  • Declare a managed member inside a native class
class IAmNative
{
    gcroot<IAmManaged^ > managedMember;
 
public:
    IAmNative():managedMember(gcnew IAmManaged())
    {
 
    }
};

  • Declare a managed member that will self destroy
#include <msclr\auto_gcroot.h> 
 
class IAmStillNative
{
    msclr::auto_gcroot<IAmStillManaged^> managedMember; // Will be disposed when IAmStillNative is destroyed
 
public:
    IAmStillNative():managedMember(gcnew IAmStillManaged())
    {
    }
};
  • Convert a native STL string to a managed string
System::String^ ToManaged(const std::string& nativeString)
{
    return gcnew System::String(nativeString.c_str());
}
  • The same backwards:

std::string ToNative(System::String^ managedString)
{
   char* str = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(managedString).ToPointer();
 
   std::string result(str);
 
   System::Runtime::InteropServices::Marshal::FreeHGlobal((System::IntPtr)str);
   return result;
}
Things you can do
  • Instantiate managed types, call managed methods from native code provided it compiles with /CLR.
  • Instantiate native types, call native methods from managed code
  • Link to the native types of a mixed static lib (/clr)
  • Declare managed methods that have native types in their signature
Things you can't do
  • Link to the managed types of a mixed static lib
  • Link to managed types in a DLL if those managed types have methods with native types in their signature.

Wednesday 29 April 2009

First Contact with DevExpress

Recently I had the opportunity to use DevExpress controls for WinForms. Overall I wouldn't say those controls save you time if you compare with regular Windows Forms controls. The time you save in coding you spend it reading documentation and experimenting with the controls. However the results are definitely superior to WinForms: better looking and with plenty of niceties that come for free (grouping, sorting, customizing, dragging and dropping, advanced tooltips, etc...) The controls I used to far:
  • GridControl
  • VGridControl
  • PropertyGridControl
  • TreeList
GridControl Comes with plenty of default features such as very powerful grouping and filtering options accessible to users at runtime. To populate it, simply set its DataSource to a DataTable or an IList.
  • If all you do is setting the DataSource then the control doesn't know anything about the data layer, which is good.
  • However if you add columns from the designer (either manually or from a datasource) then you create a tight coupling with the data layer, which might be ok depending in the type of app you're creating. I find the designer is great for discovering functionality but when given a choice, it is better to write code: this avoids having the UI know too much about the data.
VGridControl and PropertyGridControl
From a distance VGridControl looks like a Property grid control. The main difference is you can display many records at a time while a property grid control displays a single record.
  • Both theVGridControl and PropertyGridControl use reflection to display the properties of an object.
  • For some reason PropertyGridControl works fine for public properties with exotic types (such as collections) while VerticalGridControl simply doesn't display collection properties -unless there is something I missed...
TreeList The first column contains the tree, the other columns display data in a grid. Handy when each node of the tree contains usefull info and you don't want users to click each node to see the info. Instead you display the info directly in the grid and users can sort and filter as they see fit.
Most of the effort with the DevExpress controls is working out what they do. Two main sources:
  • The DemoCenter that comes with the DevExpress install
  • The blonde and brunette from DevExpress TV