Why has noone mentioned performance?

  • Thread starter Thread starter Pete
  • Start date Start date
P

Pete

Hi,

Amazing that noone has mentioned performance, especially since this is
almost certainly the key reason that methods are non-virtual by default!
Calling a virtual method is slower than calling a non-virtual method.
Objects with virtual methods also require more memory. Forcing programmers
to use slower-than-necessary methods (even when there's clearly no purpose
to it being virtual) is just poor design in a programming language.

Further discussion inline:
There are two different perspectives on library design, and which one
is better depends upon your perspective. It's a tradeoff between
flexibility and robustness.

Not really, see below:
If you value extensibility and flexibility, you will likely prefer
the Java approach, which says that everything can be extended unless
you explicitly say that it shouldn't be. If you value robustness
more, you will likely prefer the C# approach, which says that things
can be extended only if the class designer allowed it to be extended.

Surely making everything virtual is the opposite of flexibility? Flexibility
is *allowing* programmers to use non-virtual methods if they want. I can
easily get the Java approach by always using virtual or override, but I
don't have to.. *that's* flexible.

With the c# approach you have the best of both worlds -- extensibility if
you want it (and hence, flexibility).
In addition to the default behavior, there's also a philosophical
issue related to class design. Should you leave things virtual unless
you're sure there's a good reason for them not to be virtual, or
should you make them virtual only if you know of a good reason for
them to be virtual.

Like you implied earlier in your post.. you should use virtual methods where
you intend people to override them. Making a method virtual is as good
as -telling- the user that they can (and should) override the method. When
all methods are virtual people have no way of knowing which methods are
intended to be overridden, which can cause unforeseen problems.

I guess you could argue that making everything virtual gives extensibility
even where it wasn't intended.. but this just seems like you're working
around poor design to me.

Pete
 
Pete said:
Amazing that noone has mentioned performance, especially since this is
almost certainly the key reason that methods are non-virtual by default!
Calling a virtual method is slower than calling a non-virtual method.

#define 'slower'. If you override a method, the compiler will make
sure the runtime will map the relative address of the overriding method in
the VTable of the class in which the original virtual method is located at
runtime. I don't see a slowdown there. Aren't you confusing static/non-
static methods?
Objects with virtual methods also require more memory. Forcing
programmers to use slower-than-necessary methods (even when there's
clearly no purpose to it being virtual) is just poor design in a
programming language.

Hmmm, only if the compiled code doesn't use VTables, otherwise there
is no difference. I'm pretty sure the compiled code uses a VTable variant.

FB
 
Frans Bouma said:
#define 'slower'. If you override a method, the compiler will make
sure the runtime will map the relative address of the overriding method in
the VTable of the class in which the original virtual method is located at
runtime. I don't see a slowdown there. Aren't you confusing static/non-
static methods?

No, not necessarily. If a method is virtual, the address of the method
needs to be looked up in the vtable on every call, as it could be
different for different objects. If it's non-virtual, it will always be
the same, so that address can be injected directly into the code
stream. Non-virtual methods can also be inlined whereas virtual methods
can't.

Here's some sample code to show the difference:

// See http://www.pobox.com/~skeet/csharp/benchmark.html for
// how to run this code
using System;

public class VirtualSpeed
{
static int iterations=1000000000;

public static void Init(string[] args)
{
if (args.Length>0)
iterations = Int32.Parse(args[0]);
}

[Benchmark]
public static void TestVirtual()
{
VirtualSpeed foo = new VirtualSpeed();
for (int i=iterations; i > 0; i--)
foo.VirtualMethod();
}

[Benchmark]
public static void TestNonVirtual()
{
VirtualSpeed foo = new VirtualSpeed();
for (int i=iterations; i > 0; i--)
foo.NonVirtualMethod();
}

public virtual void VirtualMethod()
{
}

public void NonVirtualMethod()
{
}
}

Results:
C:\test>benchmark -runtwice
Benchmarking type VirtualSpeed
Run #1
TestVirtual 00:00:12.0973952
TestNonVirtual 00:00:03.4549680
Run #2
TestVirtual 00:00:12.0673520
TestNonVirtual 00:00:03.4549680

Note that this is one area where the HotSpot Java JIT has an advantage
over the MS CLR - because it can undo its optimisations, it can treat a
method as non-virtual until a class which overrides it is loaded. (I
wrote a test program to show that a while ago - it should be on
groups.google.com somewhere if you're interested.)
 
It's little wonder the Java JIT does that. If everything's virtual by
default, then you'd hope it would, otherwise the performance would be
shocking (given those numbers you have posted).

Niall
 
Back
Top