Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's wrong with Loop speed?

I have this simple for loop with nothing inside. It takes almost 2 seconds to run, now, but if I replace the _img.width with 512 then it runs almost in 0.001 milliseconds. What's the problem? Should I assign a local variable instead of using _img.width? I'm wondering why it runs faster since it's just a number.

for (int aRowIndex = 0; aRowIndex < _img.width; aRowIndex += subsample)// For por cada fila de cada imagen
{
    for (int aColumnIndex = 0; aColumnIndex < _img.height; aColumnIndex += subsample)//For por cada columna
    {
    }
}
like image 433
Matimont Avatar asked Dec 07 '22 03:12

Matimont


2 Answers

why it runs faster since it's just a number

It is not just a number, it is a property. With a nontrivial implementation, unfortunately, there's an underlying unmanaged interop call involved that isn't very cheap. It blows up to an observable overhead due to the O(n^2) loop complexity.

You can simply solve it by caching the property value yourself:

int width = _img.Width;
int height = _img.Height;
for (int aRowIndex = 0; aRowIndex < width; aRowIndex += subsample)
{
    for (int aColumnIndex = 0; aColumnIndex < height; aColumnIndex += subsample)
    {
    }
}
like image 200
Hans Passant Avatar answered Dec 10 '22 11:12

Hans Passant


Looking at the .NET source for Image.Height you can see that every type you get the property value it invokes an external call to gdiplus.dll. It does not cache the value in .NET memory.

/// <summary>Gets the height, in pixels, of this <see cref="T:System.Drawing.Image" />.</summary>
/// <returns>The height, in pixels, of this <see cref="T:System.Drawing.Image" />.</returns>
public int Height
{
    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    get
    {
        int result;
        int num = SafeNativeMethods.Gdip.GdipGetImageHeight(new HandleRef(this, this.nativeImage), out result);
        if (num != 0)
        {
            throw SafeNativeMethods.Gdip.StatusException(num);
        }
        return result;
    }
}

By the way, this is actually against Microsoft's own guidelines: http://msdn.microsoft.com/en-us/library/vstudio/ms229054(v=vs.100).aspx

like image 44
Knaģis Avatar answered Dec 10 '22 12:12

Knaģis