Tom Goff's .Net Musings

Tidbits of information regarding .Net, C#, and SQL Server.

Archive for the ‘Optimization’ Category

TOTW: Avoid Unnecessary EventArgs Allocations

leave a comment »

In a previous blog entry about the generic EventHandler delegate, I included an example similar to the following example:

public class MyObject {
    // ... Other code ...

    /// <summary>
    /// This event is fired when something happens.
    /// </summary>
    [field: NonSerialized]
    public event EventHandler<MyCustomEventArgs> SomeEvent;

    /// <summary>
    /// This method is used to fire the <see cref="E:SomeEvent"/>
    /// event.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The event arguments.</param>
    private void OnSomeEvent(Object sender,
        MyCustomEventArgs e) {
        if (null != SomeEvent)
            SomeEvent(sender, e);
    }
}

public class MyCustomEventArgs : EventArgs {
    /// <summary>
    /// Initializes a new instance of the
    /// <see cref="MyCustomEventArgs"/> class.
    /// </summary>
    /// <param name="whatHappened">What happened.</param>
    public MyCustomEventArgs(String whatHappened) {
        this.whatHappened = whatHappened;
    }

    /// <summary>
    /// Holds a string that tells what happened.
    /// </summary>
    private String whatHappened;

    /// <summary>
    /// Gets a string that tells what happened.
    /// </summary>
    /// <value>What happened.</value>
    public String WhatHappened {
        get {
            return this.whatHappened;
        }
    }
}

In general, most developers would include additional overloads of the OnSomeEvent method to make their lives easier. For example, the following overload of OnSomeEvent allows you simply provide the “what happened” text and the method handles everything else.

/// <summary>
/// This method is used to fire the <see cref="E:SomeEvent"/>
/// event.
/// </summary>
/// <param name="whatHappened">What happened.</param>
private void OnSomeEvent(String whatHappened) {
    OnSomeEvent(this, new MyCustomEventArgs(whatHappened));
}

The problem with the code above is that a new instance of MyCustomEventArgs is allocated even if SomeEvent is null. Eventhough, nobody is subscribing to the SomeEvent event, we are performing a memory allocation.

We can update our overload so that the memory allocation is only performed if someone is actually subscribing to the event.

/// <summary>
/// This method is used to fire the <see cref="E:SomeEvent"/>
/// event.
/// </summary>
/// <param name="whatHappened">What happened.</param>
private void OnSomeEvent(String whatHappened) {
    if (null != SomeEvent)
        SomeEvent(this, new MyCustomEventArgs(whatHappened));
}

Now, the allocation of MyCustomEventArgs is only performed if it’s needed. If this event is fired often and typically does not have any handlers hooked up, then we can remove any unneeded burdon on memory and the garbage collector. 

With the example above, the OnSomeEvent methods are private. If you are expecting your class to be extended, then you may want to make OnSomeEvent(Object, MyCustomEventArgs) protected/public and virtual. This allows derived classes to customize the behavior of the SomeEvent event. If we change OnSomeEvent(String) so that it calls the event directly (instead of calling OnSomeEvent(Object, MyCustomEventArgs)), then dervied classes would have to override this overload as well. If OnSomeEvent needs to be virtual, then it’s probably best not to make the change described here.

Written by Tom

November 1, 2007 at 7:49 am

TOTW: EventArgs.Empty

leave a comment »

Events in .Net should always have two parameters: sender and the event arguments. The first parameter is the object that generated the event. The second parameter is either an instance of EventArgs[^] or a class derived from EventArgs.

By using a class derived from EventArgs, developers can include additional information about the event. The following code, shows a typical event definition:

public class MyObject {
    // ... Other code ...

    /// <summary>
    /// This event is fired when something happens.
    /// </summary>
    [field: NonSerialized]
    public event EventHandler<MyCustomEventArgs> SomeEvent;

    /// <summary>
    /// This method is used to fire the <see cref="E:SomeEvent"/>
    /// event.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The event arguments.</param>
    protected virtual void OnSomeEvent(Object sender,
        MyCustomEventArgs e) {
        if (null != SomeEvent)
            SomeEvent(sender, e);
    }
}

In the event above, I specify that the event will use MyCustomEventArgs (not shown). I can then include additional properties in MyCustomEventArgs as needed. There are times when no additional information can be or needs to be included with the event. In these cases, the event typically takes an instance of EventArgs. An example of this is shown here:

public class MyObject {
    // ... Other code ...

    /// <summary>
    /// This event is fired when something happens.
    /// </summary>
    [field: NonSerialized]
    public event EventHandler<EventArgs> SomeEvent;

    /// <summary>
    /// This method is used to fire the <see cref="E:SomeEvent"/>
    /// event.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The event arguments.</param>
    protected virtual void OnSomeEvent(Object sender,
        EventArgs e) {
        if (null != SomeEvent)
            SomeEvent(sender, e);
    }
}

The following code shows an example of how to fire this event. In addition, it shows an overload of OnSomeEvent that provides the appropriate parameters.

public class MyObject {
    // ... Other code ...

    /// <summary>
    /// This method is used to do something important.
    /// </summary>
    public void SomeMethod() {
        // ... Other code ...

        OnSomeEvent(this, new EventArgs());

        // ... Other code ...
    }

    /// <summary>
    /// This method is used to fire the <see cref="E:SomeEvent"/>
    /// event.
    /// </summary>
    protected virtual void OnSomeEvent() {
        if (null != SomeEvent)
            SomeEvent(this, new EventArgs());
    }
}

The code above works great, but has one problem. Every time SomeEvent is fired, we allocate a new instance of EventArgs. Since EventArgs is immutable and has no properties or fields, we could allocate a single global instance of EventArgs and use that single instance every time we fire our event. Luckily, .Net already defines such an instance in EventArgs.Empty[^].

Using this new global instance of EventArgs, our code would look like this:

public class MyObject {
    // ... Other code ...

    /// <summary>
    /// This method is used to do something important.
    /// </summary>
    public void SomeMethod() {
        // ... Other code ...

        OnSomeEvent(this, EventArgs.Empty);

        // ... Other code ...
    }

    /// <summary>
    /// This method is used to fire the <see cref="E:SomeEvent"/>
    /// event.
    /// </summary>
    protected virtual void OnSomeEvent() {
        if (null != SomeEvent)
            SomeEvent(this, EventArgs.Empty);
    }
}

I put together a small sample project[^] to demonstrate the additional allocation. I also included a test of the Empty field from the String class. This is the code from the sample project:

static void Main(string[] args) {
List strings = new List(10000);
List eventArgs = new List(10000);
Int64 before, after;

Console.Write(“Starting \”\” test…”);
strings.Clear();
before = GC.GetTotalMemory(true);
for (Int32 i = 0; i < 10000; i++) strings.Add(""); after = GC.GetTotalMemory(true); Console.WriteLine("done ({0} bytes)", after - before); Console.Write("Starting String.Empty test..."); strings.Clear(); before = GC.GetTotalMemory(true); for (Int32 i = 0; i < 10000; i++) strings.Add(String.Empty); after = GC.GetTotalMemory(true); Console.WriteLine("done ({0} bytes)", after - before); Console.Write("Starting new EventArgs() test..."); eventArgs.Clear(); before = GC.GetTotalMemory(true); for (Int32 i = 0; i < 10000; i++) eventArgs.Add(new EventArgs()); after = GC.GetTotalMemory(true); Console.WriteLine("done ({0} bytes)", after - before); Console.Write("Starting EventArgs.Empty test..."); eventArgs.Clear(); before = GC.GetTotalMemory(true); for (Int32 i = 0; i < 10000; i++) eventArgs.Add(EventArgs.Empty); after = GC.GetTotalMemory(true); Console.WriteLine("done ({0} bytes)", after - before); Console.ReadKey(); }[/sourcecode]Note: I realize GC.GetTotalMemory isn’t the most accurate way to detect memory allocations.

And this is the output from one test run:

emptyfieldtest

As you can see, the only time the total memory is increased is when we create new instances of EventArgs (as expected). Strings have special handling in .Net, such as string interning[^], but there is no special handling for EventArgs. This means you have to specifically use the EventArgs.Empty field.

You won’t see a huge improvement, if any, by using EventArgs.Empty. This is just a good coding practice.

Written by Tom

October 23, 2007 at 8:02 am

Collection Performance Test

leave a comment »

Like most developers, we make extensive use of the .Net collection classes. But there are times where those classes seem like overkill. For example, if I needed to collect a unique set of strings then I could define a Dictionary<T, U>[^] class like “Dictionary<String, Object>”. This would allow me to see if the string already exists and if it doesn’t then I could add it.

This led me to the Power Collections for .Net[^] provided by Wintellect[^]. This library has a Set<T>[^] class, which would allow me to collect the unique strings without the extraneous mapped value. But like most things, I worry that performance will suffer.

So I decided to run some performance tests on both the .Net collection classes and the Power Collections. I’m not going to include my actual results here, but I have put together a sample project[^] so you can run the tests yourself.

When you run the tests you will see that the .Net collections classes perform better than the Power Collection classes. The project is setup to tests each collection with 1 million entries, but similar results occur when running with 100, 000 entries.

Another item to note, is that Dictionary<T, U> can perform better than a Hashtable[^] . The times for the common operations are almost identical, but the Hashtable does not have the TryGetValue[^] method. This means you must first verify that the value exists with the Contains method, then get the value. So basically, if you use a Hashtable you have to lookup an item twice. I’m assuming of course that you are not relying on exceptions to notify you that a key does not exist. Finally, with the Dictionary class you do not need to cast the Keys or Values to their actual type. So you save in performance there also.

Because I find that I need the Set<T> class from Power Collections often, I decided to write a wrapper around the .Net Dictionary<T, U> class. This makes the code easier to read, but I do not sacrifice performance. I’ve included this class in the sample project, which you are free to use as you see fit.

I do realize that the performance gains are not huge, but they can be significant depending on how they are used. In addition, the Power Collections offer a lot more types of Collections, so it is still very useful.

Written by Tom

June 18, 2007 at 4:10 pm

Posted in .Net, C#, Optimization

Coding and Accessing Properties

leave a comment »

I was recently re-reading parts of “CLR via C#” by Jeffery Richter. In the book, Mr. Richter wished that Properties were not supported in .Net framework for various reasons. The one reason that caught my eye was that a “property can take a long time to execute”.

I use properties through-out my code, for various reasons (XmlSerializer and PropertyGrid are the first two that jump to mind). I’m probably guilty of creating properties that may be a bit to expensive to be properties. Although, I’ve never run into any performance issues relating to them. Regardless, I’m always looking for ways to squeeze a bit more speed/memory from my applications.

So I created a simple class with a single property that does more work than it should:

    public class Class1 { 
        public Int32 Sum { 
            get { 
                Int32 retVal = 0; 
                for (Int32 i = 1; i <= 100; i++) 
                    retVal += i; 
                return retVal; 
            } 
        } 
    }

I then accessed this property as follows:

    Class1 c1 = new Class1(); 
    for (Int32 i = 0; i < c1.Sum; i++) { 
        Console.WriteLine(i.ToString()); 
    }

This resulted in the following compiled IL code:

    .maxstack 2 
    .locals init ( 
        [0] class TestApp.Class1 c1, 
        [1] int32 i) 
    L_0000: newobj instance void TestApp.Class1::.ctor() 
    L_0005: stloc.0 
    L_0006: ldc.i4.0 
    L_0007: stloc.1 
    L_0008: br.s L_001a 
    L_000a: ldloca.s i 
    L_000c: call instance string [mscorlib]System.Int32::ToString() 
    L_0011: call void [mscorlib]System.Console::WriteLine(string) 
    L_0016: ldloc.1 
    L_0017: ldc.i4.1 
    L_0018: add 
    L_0019: stloc.1 
    L_001a: ldloc.1 
    L_001b: ldloc.0 
*-> L_001c: callvirt instance int32 TestApp.Class1::get_Sum() 
    L_0021: blt.s L_000a 
    L_0023: ret 

As you can see by the marked line, the property is access for each iteration of the loop. I then updated the property access to save the value in a local variable as follows:

    Class1 c1 = new Class1(); 
    Int32 sum = c1.Sum; 
    for (Int32 i = 0; i < sum; i++) { 
        Console.WriteLine(i.ToString()); 
    }

This resulted in the following compiled IL code:

    .maxstack 2 
    .locals init ( 
        [0] class TestApp.Class1 c1, 
*->     [1] int32 sum, 
        [2] int32 i) 
    L_0000: newobj instance void TestApp.Class1::.ctor() 
    L_0005: stloc.0 
    L_0006: ldloc.0 
*-> L_0007: callvirt instance int32 TestApp.Class1::get_Sum() 
*-> L_000c: stloc.1 
    L_000d: ldc.i4.0 
    L_000e: stloc.2 
    L_000f: br.s L_0021 
    L_0011: ldloca.s i 
    L_0013: call instance string [mscorlib]System.Int32::ToString() 
    L_0018: call void [mscorlib]System.Console::WriteLine(string) 
    L_001d: ldloc.2 
    L_001e: ldc.i4.1 
    L_001f: add 
    L_0020: stloc.2 
    L_0021: ldloc.2 
*-> L_0022: ldloc.1 
    L_0023: blt.s L_0011 
    L_0025: ret 
}

As expected, the new code only access the property once outside the loop. The new local variable “sum” is then used inside the loop.

Obviously, this is a simple example and would not result in a noticable speed improvement, but it illustrates the point. I don’t think a general rule can be defined (e.g. always save the property value in a local variable), because every case varies. There may be cases where  the code expecting the value to change. Such as:

    while (false == c1.IsCompleted) { 
        ... 
    }

This is just something to keep in mind when coding and using properties. Personally, I like properties, but I just think of them as pretty methods 😉

Written by Tom

April 6, 2007 at 1:55 pm

Posted in .Net, C#, Optimization