HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Validation Extension method performance

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
performancevalidationmethodextension

Problem

I'm writing a simple set/framework of extension methods for argument/parameter validation. What I'm mostly concerned about, ATM is the performance, against the simpliest boilerplate

if(obj == null)
   throw new ArgumentNullException()


The framework I came up with is like that:
The Validatable class packing the base object that will be validated through the ThrowIf() extension method.

public class Validatable
{
    public T Value { get; }
    public Validatable(ref T argument)
    {
        Value = argument;
    }
}

public static Validatable ThrowIf(this T argument)
{
    return new Validatable(ref argument);
}


And test methods themselves:

public static Validatable IsNull(this Validatable argument) where T : class
{
    if (argument.Value == null)
        throw new ArgumentNullException();
    return argument;
}

public static Validatable CollectionEmpty(this Validatable argument) where T: ICollection
{
    if (argument.Value.Count == 0)
        throw new ArgumentException();
    return argument;
}


This allows me to validate items with simple:

List testList = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
testList.ThrowIf().IsNull().CollectionEmpty();


Everything was fine untill I decided to test, how it fares against the simple boilerplate.

int iNumber = 1000000000;
Stopwatch sw1 = new Stopwatch();
Stopwatch sw2 = new Stopwatch();
sw1.Start();
for (int i = 0; i < iNumber; ++i)
{
    if (testList == null)
        throw new ArgumentNullException();
    if (testList.Count == 0)
        throw new ArgumentException();
}
sw1.Stop();
sw2.Start();
for (int i = 0; i < iNumber; ++i)
{
    testList.ThrowIf().IsNull().CollectionEmpty();
}
sw2.Stop();

Console.WriteLine($"sw1: {sw1.ElapsedTicks} ticks");
Console.WriteLine($"sw2: {sw2.ElapsedTicks} ticks");


and the output was:

sw1: 10720019 ticks

sw2: 161726524 ticks

That's an order of magnitute difference. It was over 1,000,000,000 iterations, but still the difference is there.

Solution

public static Validatable ThrowIf(this T argument)
{
    return new Validatable(ref argument);
}


This of course is creating a lot of objects. You could speed this a little bit up by making Validatable a struct but still, it'll be slower then the normal check. Convenience comes often with some kind of a performance hit.


I was going to use it my game engine

You'd better not. Make it fast, not convenient.

There is one more thing about validating arguments. The only thing you need to validate is user input or something that you cannot predict like configurations. Internally most methods usually work without argument checking because it's nearly impossible to pass invalid values. Use Debug.Assert for this purpose during development to be absolutely sure if you want. It'll be removed in the release version so that it doesn't slow the application down.

Code Snippets

public static Validatable<T> ThrowIf<T>(this T argument)
{
    return new Validatable<T>(ref argument);
}

Context

StackExchange Code Review Q#153197, answer score: 2

Revisions (0)

No revisions yet.