Re: C# very optimisation



Everyone seems to be missing the important point about ++i vs i++
optimization...

Namely it comes in play mostly on user defined types with an overload
operator ++.

You're just not going to see the difference using an int.

To understand this, imagine we have a class (MyClass), which has a
member function (AddOne), and we want to implement op++ and ++op. (For the
moment, I'm going to do this in C++)

class MyClass
{
public:
void AddOne() {.....}

// The Pre-fix (++x) operator is rather straight forward.
MyClass& operator++()
{
AddOne();
return *this;
}

// the post-fix (x++) is a bit trickier
MyClass operator++(int)
{
MyClass temp(*this);
AddOne();
return temp;
}
}

Note that for the post fix, we've got to make two copies of MyClass (one
in temp, and one for the return), which aren't needed in the pre-fix op++.
Also, note that I could have written the post-fix as:

MyClass operator++(int)
{
MyClass temp(*this);
this->operator++(); // or ++(*this);
return temp;
}

Now, let's write a similar class in C#:

class MyClass
{
public void AddOne() {.....}

public static MyClass operator++(MyClass a)
{
a.AddOne();
return a;
}
}

You'll note that this is the pre-fix operator++. So, where is the
post-fix? The C# compiler creates it for you automatically. And is it
written? Basically:

public static MyClass operator++(MyClass a) // post-fix
{
MyClass b = a.Clone();
++a;
return b;
}

So, like in the C++, the post-fix has to create a copy of the unaltered
object, so that it can be returned.

When an int is used, the operator method is inlined, so, when it's just
"x++;" on a line by itself, the compile can see that the duped value isn't
used, and it can remove the whole creation of it. When ++ is used on some
other type object, the oper++ is done out-of-line, and so, the compiler
cannot remove it.

So, now, let's try your test again, but this using a class:
using System;
public class LikeAnInt
{
int n =0;
public LikeAnInt(int i)
{
n = i;
}
public void AddOne()
{
++n;
}
static public LikeAnInt operator++(LikeAnInt a)
{
a.AddOne();
return a;
}
public int Val
{
get { return n; }
}
}

public class MyClass
{
public static void Main()
{
DateTime d;
TimeSpan t;
int iMax = 1000000000;
int j;
// Test 1 : i++
j = 0;
d = DateTime.Now;
for (LikeAnInt i = new LikeAnInt(0); i.Val < iMax; i++)
j += i.Val;
t = DateTime.Now - d;
Console.WriteLine("i++ : {0}", t.TotalMilliseconds.ToString());

// Test 2 : ++i
j = 0;
d = DateTime.Now;
for (LikeAnInt i = new LikeAnInt(0); i.Val < iMax; ++i)
j += i.Val;
t = DateTime.Now - d;
Console.WriteLine("++i : {0}", t.TotalMilliseconds.ToString());
// Test 3 : i.AddOne()
j = 0;
d = DateTime.Now;
for (LikeAnInt i = new LikeAnInt(0); i.Val < iMax; i.AddOne())
j += i.Val;
t = DateTime.Now - d;
Console.WriteLine("i.AddOne : {0}", t.TotalMilliseconds.ToString());
Console.Read();
}
}

The Results:
SnippetCompiler:
i++ : 44206.6704
++i : 42848.6265
Approx 3% faster

VC#-Debug:
i++ : 34887.6795
++i : 34731.5825
Approx 0.3% faster

VC#-Release:
i++ : 1623.4088
++i : 1607.7991
i.AddOne : 1607.7991
Approx 0.9% faster

A minmal difference, but it's beyond the "noise" level.
--
--
Truth,
James Curran
[erstwhile VC++ MVP]

Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com

"Ennixo" <ennixo@xxxxxxx> wrote in message
news:428b4cc1$0$32525$626a14ce@xxxxxxxxxxxxxxx
> Helge Jensen a écrit :
>
> > I can't imagine that there is *any* difference whatsoever for the
> > performance using ++i or i++ (esp. on integral types), and will continue
> > to think that untill I see a test-program proving otherwise.
> >
>
> so try this sample code (paste in Main method) and you will think that
> ++i is really faster than other ways to increment by 1. (note: run in
> RELEASE mode)


.



Relevant Pages

  • Re: C# very optimisation
    ... > You're just not going to see the difference using an int. ... > class MyClass ... > Approx 0.3% faster ... Post-increment loop ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: The effect of "^"
    ... public ref class MyClass ... public ValueType SomeNumber; ... public int SomeNumber; ... public IntPtr WindowHandle; ...
    (microsoft.public.dotnet.languages.vc)
  • RE: ValueType reference in objects
    ... You will also need to check the "Allow unsafe code" option in the Build tab ... unsafe class MyClass ... public int* i; ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: How to share data?
    ... > int getdata; ... Why is readdata() public? ... Your constructor copies the values ...
    (comp.programming)
  • Re: ValueType reference in objects
    ... to receive the event structure I use IntPtr: ... int result = StaticClass.UnmanagedFunction ... unsafe class MyClass ... public int* i; ...
    (microsoft.public.dotnet.languages.csharp)