InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

fun with .NET 4 expressions – Light speed edition

A few days ago I posted an article about the new .NET Expression features in .NET 4.0 (Fun with .NET 4 expressions). A few people commented and wrote the this was a pretty expensive way to synchronize data. Of course it was – performance wasn’t a design consideration. I merely followed the two rules of optimization:

  1. Don’t do it.
  2. (For experts only!) Don’t do it now.

And since the synchronization process was fast enough, I didn’t care.

However, just for the fun of it, I did some performance optimization and it is pretty amazing. The thing which made the original code rather slow was the fact that the same expressions were compiled over and over again. So an obvious improvement was to cache the compiled expressions and reuse them. So I introduced two dictionaries to hold the compiled expressions:

private static readonly Dictionary<Type, object> _SetterCache = new Dictionary<Type, object>();
private static readonly Dictionary<Type, object> _GetterCache = new Dictionary<Type, object>();

You may wonder why the type of the dictionary is Dictionary<Type, object>. The reason for this is that there is no other common base class for the type Func<TSource, TProperty>. The following this method checks the cache and compiles the expression if required:

private static Func<TTarget, TProperty> GetGetterMethod<TTarget, TProperty>(Expression<Func<TTarget, TProperty>> targetSelector)
{
    object getterObject;
    Func<TTarget, TProperty> getterMethod;
    var selectorType = targetSelector.Type;

    if (!_GetterCache.TryGetValue(selectorType, out getterObject))
    {
        getterMethod = targetSelector.Compile();
        _GetterCache[selectorType] = getterMethod;
    }
    else
    {
        getterMethod = (Func<TTarget, TProperty>) getterObject;
    }
    return getterMethod;
}

I added a similar method to handle the update expression accordingly.

Finally, I hacked together a small test program which used the Stopwatch class to measure the synchronization speed. The result is quite impressing. Synchronizing an object with two properties 10,000 times yielded these results:

Elapsed for 10000 rounds (Slow): 00:00:08.0471936
Elapsed for 10000 rounds (Fast): 00:00:00.2009293

That is quite an improvement.

I’ve attached the source code to this post, so you can measure yourself.

Downloads


Posted by Henning Krause on Sunday, December 5, 2010 9:00 PM, last modified on Sunday, December 5, 2010 8:38 PM
Permalink | Post RSSRSS comment feed

Scripts no longer function after you run an ASP.NET page which displays performance data

Symptoms

After you view an ASP.NET webpage which displays performance counter data via the PerformanceCounter class, scripts no longer function. This includes scripts launched from a command line as well as client-side scripts in any browser window that is opened after you viewed the original page. Scripts are working again after you have stopped the Word Wide Publishing service.

Cause

A deadlock occurs because of a bug in one of the WMI providers. An event tracing is done which calls the RegisterTraceGuids API which in turn calls into one of the WMI Service hosted within the Services.exe.

Resolution

A hotfix is available from Microsoft, at least in english and german.

To resolve this problem, contact Microsoft Product Support Services to obtain the hotfix for KB834010. For a complete list of Microsoft Product Support Services phone numbers and information about support costs, visit the following Microsoft Web site: http://support.microsoft.com/default.aspx?scid=fh;[LN];CNTACTMS

Status

This problem was first corrected in Microsoft Windows XP Service Pack 2

Steps to reproduce the problem

  1. Create a new ASP.NET web application
  2. Add a label control to the page
  3. Add this code to the Page_Load event:
  4.     1 using (PerformanceCounter counter = new PerformanceCounter())

        2 {

        3     counter.CategoryName = "Memory";

        4     counter.CounterName = "Available MBytes";

        5     Label1.Text = counter.NextValue().ToString();

        6 }

  5. Compile the application
  6. Open the webform with Internet Explorer

  7. Now, open any website which has client-side scripting

References

See KB Article 834010 for more information

Posted by Henning Krause on Tuesday, May 31, 2005 9:46 PM, last modified on Tuesday, July 26, 2011 9:57 PM
Permalink | Post RSSRSS comment feed

Scripts no longer function after you run an ASP.NET page which displays performance data

Symptoms

After you view an ASP.NET webpage which displays performance counter data via the PerformanceCounter class, scripts no longer function. This includes scripts launched from a command line as well as client-side scripts in any browser window that is opened after you viewed the original page. Scripts are working again after you have stopped the Word Wide Publishing service.

Cause

A deadlock occurs because of a bug in one of the WMI providers. An event tracing is done which calls the RegisterTraceGuids API which in turn calls into one of the WMI Service hosted within the Services.exe.

<xsl:template match="xhtml:img" mode="xhtmlimage">

<xsl:param name="caption" select="@title" />

< xsl:copy >

<xsl:apply-templates select="@*" mode="xhtmlattributes" />

</ xsl:copy >

<xsl:element name="span">

<xsl:attribute name="class">clsCaption</xsl:attribute>

<xsl:value-of select="$caption" />

</ xsl:element >

</ xsl:template >

Resolution

A hotfix is available from Microsoft, at least in english and german.

To resolve this problem, contact Microsoft Product Support Services to obtain the hotfix. For a complete list of Microsoft Product Support Services phone numbers and information about support costs, visit the following Microsoft Web site: http://support.microsoft.com/default.aspx?scid=fh;[LN];CNTACTMS

Status

This problem was first corrected in Microsoft Windows XP Service Pack 2

Steps to reproduce the problem

  1. Create a new ASP.NET web application
  2. Add a label control to the page
  3. Add this code to the Page_Load event:

    using (PerformanceCounter counter = new PerformanceCounter())

    {

    counter.CategoryName = "Memory";

    counter.CounterName = "Available MBytes";

    Label1.Text = counter.NextValue().ToString();

    }

  4. Compile the application

  5. Open the webform with Internet Explorer

  6. Now, open any website which has client-side scripting

References

See KB Article 834010 for more information

Posted by Henning Krause on Tuesday, May 31, 2005 9:46 PM, last modified on Tuesday, July 26, 2011 9:57 PM
Permalink | Post RSSRSS comment feed

HttpWebRequest Class has poor performance

Affected Products

  • .NET Framework 1.0
  • .NET Framework 1.1

Summary

The HttpWebRequest class performs poorly when sending requests to a server which contain a body.

Symptoms

The HttpWebRequest class performs poorly when sending requests which contain body data to a server. When monitoring the network traffic the following behaviour is seen:
  • The client sends the header of the request to the server.
  • After 350ms the rest of the request is send to the server.

Cause

The HttpWebRequest class waits for a HTTP1.1/100-Continue message before sending the body of the request. Additionally, the class supports the Nagle algorithm, which prevents the sending of many small packets to the same target. Instead, the server waits approximately 200 milliseconds, if there are other packets to be send to the same target. It then combines these requests in one packet.

Status

Microsoft has confirmed that this is a problem in the Microsoft products that are listed at the beginning of this article.
A hotfix exists (QFE810814) for version 1.0 of the Framework in the languages english and german. The patch is localized for other languages on request. Since it is a quick fix engineering (QFE), it can only be obtained directly from Microsft Support (PSS).
For the .NET Framework 1.1, no patch is necessary, since the behaviour can be controlled programmatically:
HttpWebrequest webRequest = (HttpWebRequest) Webrequest.Create("http://myserver/myfile");
webRequest.ServicePoint.Expect100Continue = false;
webRequest.ServicePoint.UseNagleAlgorithm = false;

Other Information

Note that you must have installed service pack 2 for the .NET Framework 1.0 before applying the patch.
Additionally, some configuration entries must be made in the machine.config file:
  1. Create a new <settings> section within the <system.net> section with the following content:
    <settings>
    <servicePointManager useNagleAlgorithm="false" />
    <servicePointManager expect100Continue="false" />
    </settings>
  2. In order for the .NET Framework to recognize this new section a settings sectionGroup handler needs to be added to the <configSections> portion of machine.config file:
    <sectionGroup name="system.net" >
    <section name="settings" type="System.Net.Configuration.NetConfigurationHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </sectionGroup>

Posted by Henning Krause on Thursday, December 30, 2004 6:36 PM, last modified on Thursday, July 14, 2011 10:32 PM
Permalink | Post RSSRSS comment feed