Umbraco 4.1 Benchmarks Part 2 (Back Office Database Queries)

by Shannon Deminick 28. April 2010 17:03

This is part 2 in a series of Umbraco 4.1 benchmarks created by various members of the core team in the lead up to launch. See Part 1 here on request/response peformance in the Umbraco back office.

This benchmark report looks at the data layer improvements in 4.1 by comparing query counts in 4.1 to 4.0.3. Not only has the data layer improved but there’s been significant improvements in the consumption of the data layer API made by many of the 4.1 pages and controls.

The stats below are represented as a percentage of the total calls of 4.0.3 where the number of queries in 4.0.3 are 100% and the number of queries in 4.1 are a percentage in relation to this. These results are based on the procedures listed at the bottom of this post and on averages run over 3 separate trials.

Step 4.0.3 4.1.0
Login 100% 68%
Expand all Content nodes 100% 23%
Edit Home node 100% 49%
Publishing Home node 100% 55%
Edit About Umbraco node 100% 49%
Go to Settings App 100% 100%
Expand Document types tree 100% 100%
Edit Home document type 100% 61%
Save Home document type 100% 67%
Go to Media app 100% 50%
Create new folder labeled ‘Test’ 100% 88%
Create new image under new ‘Test’ folder labeled ‘test1’ 100% 64%
Upload new image file to ‘test1’ and save the node 100% 49%
Go to Content app (and in the case of 4.0.3, expand the tree and select the About Umbraco node since in 4.1 this will already be selected and loaded) 100% 41%
Edit Home node 100% 43%
Add ‘test1’ image to the ‘Text’ WYSIWYG property with the image picker and Publish node 100% 49%
Average of averages above   60%
Complete run through of the above steps 100% 66%

 

So based on averages, Umbraco 4.1 is looking to have around 40% less queries made than 4.0.3!!! Thats HUGE!

The following steps were taken on each trial of the above steps:

  • New instances of both 4.0.3 and 4.1
  • Install CWS package on both instances
  • Log out of both instances
  • Bump web.config for both instances (clear out all data cache)
  • Use SQL Profiler to determine query counts for each step listed above

Also, SQL debugging has been added to 4.1 for MS SQL instances. If you compile the source in Debug mode you can get the SQL command output by adding a trace listener to your web.config. Underneath the configuration node you can add this xml block:

<system.diagnostics>
	<trace autoflush="true">
	  <listeners>
		<add name="SqlListener" 
			type="System.Diagnostics.TextWriterTraceListener" 
			initializeData="trace.log" />
	  </listeners>
	</trace>
</system.diagnostics>

This will create a trace.log file in the root of your web app SQL debugging.

Styling XML with CSS

by James Diacono 23. April 2010 05:26

I’m sure you’ve heard of XSLT (DON'T GO AWAY I'M NOT SUPPORTING XSLT!). XSLT is used to transform XML into different XML – for example, rendering XML as HTML.  An example:

The XSLT method

<album>
	<title>Funkentelechy Vs. The Placebo Syndrome</title>
	<artist>Parliament</artist> 
	<year>1976</year> 
	<funkativity>10</funkativity> 
</album>

can be transformed (using XSLT) to this:

<div class="album">
	<h1>Funkentelechy Vs. The Placebo Syndrome</h1>
	<p class="artist">Parliament</p>
	<p class="year">1976</p>
	<p class="funkativity">This album has a funkativity rating of 10/10</p>
</div>

Now the question is, "is h1 a better tagname for the artist of the album than artist?". I'm pretty sure the answer is no. However, the HTML engine has no idea how to display an artist tag - it treats every unknown tag like a span tag.

The pure CSS method

So display information has to come from somewhere else. Some people may find the idea of markup depending entirely on CSS for display abhorrent. I do not. I maintain that reading the source of the album XML block makes just as much sense as reading the rendered HTML version. And screenreaders...if I was a screenreader I'd want concise and descriptive XML, rather than having to wade through a bunch of HTML crap. And let's be real: everyone's web client supports CSS.

Styling XML with CSS is actually very simple and very robust. The first thing to understand is that HTML is just a custom namespace of XML. The second thing to understand is you can have multiple namespaces present in any XML document. That means you can use both HTML and, say, a custom namespace...which you can define and set styling rules.

I won't blather much more. I'll just fill you in on how CSS targets namespaces.

The CSS @namespace declaration

In short, I can write up a stylesheet which targets a specific namespace and only a specific namespace. My XML file would look like this:

<?xml version="1.0" encoding="UTF-8" ?>
<albums xmlns="http://jdiacono.org/music">
	<album>
		<title>Funkentelechy Vs. The Placebo Syndrome</title>
		<artist>Parliament</artist> 
		<year>1976</year> 
		<funkativity>10</funkativity> 
	</album>
<albums>

Here I declare that the XML inside and including the albums block is of the namespace http://jdiacono.org/music. Don't be misled by the namespace looking like a URL...I haven't even registered jdiacono.org and this is still valid. This is because namespaces are actually just unique, case-sensitive strings, and URLs tend to be unique and full of information. Let it be known that this block is all there is. It is a completely self descriptive block of pure data, which references nothing external.

Now to style this...here is my CSS:

@namespace url("http://jdiacono.org/music");

albums {
	display:block;
	}
	
album {
	display:list-item;
	list-style-type:decimal;
	margin-bottom:0.5em;
	padding:0.5em;
	border:1px solid;
	}
	
album title {
	display:block;
	font-size:2em;
	font-weight:bold;
	border-bottom:1px dashed;
	}
	
album artist {
	display:block;
	font-size:0.9em;
	}
	
album year {
	display:block;
	font-weight:bold;
	letter-spacing:0.4em;
	color:Green;
	}
	
album funkativity {
	display:block;
	font-style:italic;
	}
	
album funkativity:before {
	content: "This album has a funkativity rating of ";
	}
	
album funkativity:after {
	content: "/10";
	}

Now I have another example that is much more nourishing, which uses HTML and a custom XML namespace in the same page. You will need a browser other than IE to view this.

farmcode.org/sourcecode/cssNamespaces/cssNamespaces.xml

UPDATE: Looks like IE9 is supporting this!

Categories: CSS

Umbraco 4.1 Benchmarks Part 1 (Do Over)

by Shannon Deminick 19. April 2010 17:06

Doh! Turns out that my first Umbraco 4.1 benchmarks was done on a build of 4.1 that had a couple of bugs in it :( BUT, this turns out to be even better for 4.1 that I previously thought! (plus there’s bugs fixed now :) If you didn’t read the last post, i recommend that you do as it has some insight as to how these stats came to be.

So, without further adieu, here’s the (true) new results:

Test Stats 4.0.3 4.0.3
client cached
4.1 4.1
client cached
Content app Completed Requests 68 7 45 5
Response (KB) 687.05 72.48 382.42 11.61
Edit content
home page
Completed Requests 50 2 34 1
Response (KB) 385.10 47.28 335.02 11.94
Expand all
content nodes
Completed Requests 17 17 16 16
Response (KB) 18.47 18.47 13.96 7.54
TOTALS Completed Requests 135 26 95 22
Response (KB) 1063.62 138.23 731.40 31.09

So to recap, here’s the total average savings in 4.1

  • Without client cache (First run)
    • Number of completed requests: 30% Less
    • Response bandwidth: 31% Less
  • With client cache
    • Number of completed requests: 6% Less
    • Response bandwidth: 78% Less
Categories: .Net | Umbraco

CSS3: Using the fun stuff in real life

by James Diacono 19. April 2010 12:08

Sweep IE6 under the carpet

Do whatever you can to remove IE6 support from your website’s build spec. Proper CSS selectors like the direct child (ul > li), the :hover state for elements other than anchors, and attribute selectors (a[href*=”http://”]do not work in IE6. Then, add ie6updatein a conditional comment and voila! IE6 users see a totally legit looking alert bar across the top of their screen telling them that the page below looks horrible because they have an old browser and need to upgrade. Now you are ready to begin.

CSS3 is only sort of supported

CSS3 is currently a working draft. Microsoft hence decided to implement barely any of its features in IE8, and as a result your CSS3 magic is restricted to ‘modern’ (real) rendering engines, like WebKit (Google Chrome, Safari) and Gecko (Firefox). However, the developers of these engines understand that CSS3 is a draft and as such the interface can be changed without warning. As a safeguard they apply a prefix to the drafted properties they want to support. These are known as:

Vendor-specific extensions

If you’ve ever seen anything like -moz-border-radius: 6px; you know what I mean. Vendor-specific extensions are a standardised and accepted (however occasionally non-validating) way of implementing future rules without fear of breaking anything. If you want to use CSS3 properties you will most likely have to include the same property with a prefix right after (excepting the few properties like opacity and border-radius). Your rules will look something like this:

.box {
	-webkit-box-shadow:2px 2px 5px gray;
	-moz-box-shadow:2px 2px 5px gray;
	box-shadow:2px 2px 5px gray;
	}

I know that hurts, but at least your repitition of code is localised.  And it is future-friendly – as browsers start supporting CSS3 your advanced styles will begin to appear!  A shadow on a header here, a rounded corner there, an opacity somewhere. Patience. 

You’ll notice there’s no -ie-border-radius property above. This is very sad. This leads us to our next restriction in using CSS3:

Don't force a design

Think about it - why must the design for a site look the same in IE as Chrome? What if they looked different? Someone who sees the site in IE is not going to know what they're missing. If a design feature can't be implemented in IE that's no reason not to implement it in WebKit, so long as it degrades gracefully.

For this to work you need to be close to the designers (or be the designer) and have laid back superiors - it can't really be done when you're dealing with long chains of design approval. Convince everyone that the site is going to look better in Chrome (happy face!), not worse in IE (ANGRY FACE).

Validating CSS3

By default, the W3C's CSS Validator does not recognise CSS3. You must specify that you are validating CSS3 by clicking "More Options" on the validator page and selecting the CSS level 3 profile.

That’s it! Go forth and play:

CSS3 Goodies you have got to check out:

Note on this site

This post is pretty much a press release for the recent redesign of FARMCode.org – CSS3 allowed me to code the site exactly how I wanted in Google Chrome, translate it across to Firefox in like 5 minutes and then conduct quick damage control for IE (no rounded corners there).

Categories: CSS

Examine RC2 posted

by Aaron Powell 17. April 2010 05:08

I’ve just released Examine RC2 into the while, you can download it from our CodePlex site.

RC2 fixes a bug in RC1 which wasn’t indexing user fields, only attribute fields.

There’s a few breaking changes with RC2:

  • IQuery.MultipleFields has been removed. Use IQuery.GroupedAnd, IQuery.GroupedOr, IQuery.GroupedNot or IQuery.GroupedFlexible to define how multiple fields are added
  • ISearchCriteria.RawQuery added which allows you to pass a raw query string to the underlying provider
  • ISearcher.Search returns a new interface ISearchResults (which inherits IEnumerable<SearchResult>)
  • New interface ISearchResults which exposes a Skip to support paging and TotalItemCount

 

Will be working on more documentation to explain some of the newly added and obscure features shortly :P.

Categories: .Net | Examine | Umbraco

TSQL CASE statement in WHERE clause for NOT IN or IN filter

by Shannon Deminick 16. April 2010 09:58

There’s a ton of articles out there on how to implement a case statement in a WHERE clause but couldn’t find one on how to implement a CASE statement in a WHERE clause that gives you the ability to use a NOT IN or IN filter. I guess the only way to explain this is to use an example, and I am fully aware that the use of this may not be the best practice and is most likely required because of poor database design/implementation but hey, when you inherit code, there’s really no other choice :)

Suppose I have a stored proc that has an optional value:

@OnlyNonExported bit = 0

I want to return all items from MYTRANSACTIONS table if @OnlyNonExported  = 0, but if this value is 1 I want to return all items from MYTRANSACTIONS that have not been tracked in my TRACKEDTRANSACTIONS table. The original theory is to use a NOT IN clause to acheive the latter requirement:

SELECT * FROM mytransactions m 
WHERE mytransactions.id NOT IN (SELECT id FROM trackedtransactions)

So if I wanted to use a case statement for this query, one would think you could do something like this:

SELECT * FROM mytransactions m 
WHERE mytransactions.id NOT IN 
	CASE WHEN @OnlyNonExported = 0 
		THEN  (SELECT -1) 
		ELSE  (SELECT id FROM trackedtransactions) 
	END

But SQL doesn’t like this syntax and it turns out that you cannot use IN or NOT IN conditions with CASE statement in a WHERE clause, you can only use = or != conditions. So how do you achieve the above? Well the answer is even more dodgy that the above:

SELECT * FROM mytransactions m 
WHERE mytransactions.id != 
	CASE WHEN @OnlyNonExported = 0 
		THEN  (SELECT -1) 
		ELSE  COALESCE((SELECT id FROM trackedtransactions t WHERE t.id = m.id), -1)
	END

So basically, when we want to return all transactions, return all rows where the id equals –1 (assuming that your IDs start at 1) and when we want to filter the results based on whether or not these IDs exist in another table, we only return rows who’s IDs don’t match the same ID in the tracked table. BUT if this ID doesn’t exist in the tracked table, then an empty result set is returned and the id won’t be matched against it, so we need a COALESCE function will will return a –1 value if there is an empty result set.

Hopefully you’ll never have to use this but if you do, hope this saves you some headaches :)

Tags:
Categories: .Net

Umbraco 4.1 Benchmarks Part 1

by Shannon Deminick 15. April 2010 18:42

This is the first installment of what will hopefully be many Umbraco benchmark reports created by various members of the core team in the lead up to the launch of Umbraco 4.1. This benchmark report is about the request/response performance of the Umbraco back-office. This compares 4 different configurations: 4.0.3 with browser cache disabled (first run), 4.0.3 with browser cached files, 4.1 with browser cache disabled and 4.1 with browser cached files. These comparisons have been done by using newly installed Umbraco instances with ONLY the CWS package installed. The benchmark results were prepared by using Charles Proxy.

Test Stats 4.0.3 4.0.3
client cached
4.1 4.1
client cached
Content app Completed Requests 68 7 46 6
Response (KB) 687.05 72.48 431.41 32.54
Edit content
home page
Completed Requests 50 2 34 1
Response (KB) 385.10 47.28 343.36 12.07
Expand all
content nodes
Completed Requests 17 17 16 16
Response (KB) 18.47 18.47 13.96 10.85
TOTALS Completed Requests 135 26 96 23
Response (KB) 1063.62 138.23 788.73 55.46

Note: the above is based on <compilation debug=”false”> being set in the web.config. If it is set to true, the compression, combination and minification for both the ClientDependency framework and ScriptManager is not enabled. Also, this is not based on having IIS 7’s dynamic/static compression turned on, these benchmarks are based on Umbraco performing ‘as is ‘ out of the box which will be the same for IIS 6.

Though there’s only 3 tests listed above, these results will be consistent throughout all applications in the Umbraco back office in version 4.1.

The 4.1 difference:

  • In 4.0.3, all ScriptResource calls generated by ScriptManager were not being compressed or minified. This was due to a browser compatibility flag that was set in the base page (this was probably very old code from pre v3!).
  • Script managers in the back-office have the ScriptMode=”release” explicitly set (for minification of ScriptResource.axd)
  • The ClientDependency framework is shipped with 4.1 and all of the back office registers it’s JavaScript and CSS files with this framework. This allows for:
    • Combination, compression, minification of dependencies
    • Rogue script/style detection (for those scripts/styles that weren’t registered with the framework will still get compressed/minified)
    • Compression/minification of specified Mime types, in this case all JSON requests in the back office (namely the tree)
    • Compression/minification of all JavaScript web service proxy classes (‘asmx/js’ requests that are made by registering web services with the ScriptManager
  • Much of the back office client scripting in 4.1 has been completely refactored. Most of the JavaScript has been rewritten and a ton of file cleanup has been done.

Compared to 4.0.3, this is a HUGE difference with some serious performance benefits!

Categories: .Net | Umbraco | ClientDependency

ClientDependency now supporting MVC

by Shannon Deminick 6. April 2010 18:38

I’m please to announce that the ClientDependency framework now supports MVC! It’s very easy to implement using HtmlHelper extension methods. Here’s some quick examples:

Make a view dependent on a CSS file based on a path defined as “Styles”

<% Html.RequiresCss("Content.css", "Styles"); %>

Make a view dependent on jQuery using a full path declaration:

<% Html.RequiresJs("/Js/jquery-1.3.2.min.js"); %>

Rendering the Style blocks and defining a global style path:

<%= Html.RenderCssHere(new BasicPath("Styles", "/Css")) %>

Rendering the Script block (no global script path defined):

<%= Html.RenderJsHere() %>

There’s still a provider model for MVC but it uses a slightly different implementation from Web Forms. The same compositeFiles provider model is used but instead of the fileRegistration provider model that is used in Web Forms, a new mvc renderers provider model is used. A renderer provider is similar to the Web Forms fileRegistration providers but instead of registering the markup in the page using the page life cycle, a renderer provider is used to render out the html block necessary to embed in the page.

All of the functionality that existed in Web Forms exists in MVC. You can make as many views that you want dependent on as many of the same or different client files that you want and the system will still sort by position and priority and remove all duplicate registrations. Rogue scripts & styles still get processed by the composite file provider in MVC. Currently however, if you place user or composite controls on your views that have Client Dependencies tagged with either the control or attribute method used in Web Forms, these will not be registered with the view and output with the renderer. 

MVC pages have been added to the demo project as examples so have a look! You can download the source HERE

For full details and documentation go HERE

Examine hits RC1

by Shannon Deminick 5. April 2010 12:04

I’m happy to announce that Examine and UmbracoExamine have today hit RC1!FileDownload[1]

The Codeplex site also has more extensive documentation about how to get UmbracoExamine up and running within your Umbraco website.

Go, download your copy today.

Categories: .Net | Examine | Umbraco