Posted By: DigitalDud | Jul 7th, 2007 @ 1:30 AM
page 1 of 1
Comments: 23 | Views: 7188
So there's a number of well-known performance issues with .NET.  Reflection is slow.  Throwing exceptions takes half a second.  Cold starts take forever, the memory footprint is high.  Half these performance bugs people just take for granted, "Oh yeah don't use reflection a lot, its pretty slow". But WHY is reflection slow?  Why doesn't someone at MS open a bug against .NET, "Priority 1, fix NOW, millions of customers experiencing millions of dollars lost in operating costs cause of a slow reflection code, blah blah"

Environments like .NET are supposedly awesome because if you make performance improvements to the runtime, the JIT compiler, etc., every single program that targets .NET receives a performance benefit.  And today that is A LOT of programs.  But the thing is, they DON'T update the runtime.  They haven't touched it in years, and 2.0 didn't do much for performance anyway.  And it's not like you can't make runtime changes without breaking compatibility.  You don't have to touch the libraries, just make the compiler faster.

And now MS is investing big in Silverlight and its "thinner" runtime, so .NET will probably never see any improvements beyond new really fat libraries like WPF.
DigitalDud wrote:
So there's a number of well-known performance issues with .NET.  Reflection is slow.  Throwing exceptions takes half a second.  Cold starts take forever, the memory footprint is high.  Half these performance bugs people just take for granted, "Oh yeah don't use reflection a lot, its pretty slow". But WHY is reflection slow?  Why doesn't someone at MS open a bug against .NET, "Priority 1, fix NOW, millions of customers experiencing millions of dollars lost in operating costs cause of a slow reflection code, blah blah"

Well with the things you mentioned it's likely not to be performance issues. Its simply design issues. And as you wrote these have been VERY well documented and are widely known. If you have Exceptions in your normal execution path its simply plain wrong.
Moreover as these were design choices they are
a) likely to not be correctable without changing the design
b) speeding them up would not help anybody, because nobody uses these constructs in performance-critical code anyways.

DigitalDud wrote:

Environments like .NET are supposedly awesome because if you make performance improvements to the runtime, the JIT compiler, etc., every single program that targets .NET receives a performance benefit.  And today that is A LOT of programs.  But the thing is, they DON'T update the runtime.  They haven't touched it in years, and 2.0 didn't do much for performance anyway.  And it's not like you can't make runtime changes without breaking compatibility.  You don't have to touch the libraries, just make the compiler faster.

I'm here with you for this one (mostly). Obviously not the compiler, but the JIT-results, but I guess thats what you meant anyways.
E.g. why do NGEN compiled programs usually still perform worse that the same application compiled with an optimizing c++ compiler?
With the additionaly system information that NGEN has (Exact processor type, available RAM, ...). It should always be able to outperform or at least be on line with precompilers.
And the JIT still isn't able to take advantage from its special execution semantics to dynamically optimize applications (e.g. like HotSpot).
stevo_
stevo_
Human after all
Reflection is slow? I've just written an app that uses reflection quite a lot, and its far from slow.. reflection might not be as performant as normal code but its far from slow..
stevo_ wrote:
Reflection is slow? I've just written an app that uses reflection quite a lot, and its far from slow.. reflection might not be as performant as normal code but its far from slow..


The time taken to execute a method using reflection compared to directly executing the method is much longer... reflection is slow compared to directly accessing methods, properties, classes etc.

So why's reflection slow: It has to lookup the metadata of the application before it can invoke the method. That's perfectly normal and after that it executes normally.

I've used .NET since the first beta of version 1.0 and I never experienced unmanagably slow applications with it. The key here is that you need to be very aware of how the garbage collector and the other mechanics work.

Java has the same issues, especially with the swing GUI library. Of cource C++ is faster, but it has the other downsides as well, like a lack of checks on the boundaries of buffers and memory management that doesn't protect against memory leaks.
Sven Groot
Sven Groot
My name has 9 letters. Coincidence? I think not...
stevo_ wrote:
Reflection is slow? I've just written an app that uses reflection quite a lot, and its far from slow.. reflection might not be as performant as normal code but its far from slow..

Depends on what you're doing. A few reflection calls won't make a different, but do it millions of times in a tight loop and you'll feel it.

Reflection is not just slower, it's orders of magnitude slower than a regular method call. This is perfectly normal because of the extra work it has to do. If you're really worried about it, use a dynamic method.
stevo_
stevo_
Human after all
For the record, I said I reflection wasn't slow.. slow suggests its a real sacrifice to use.

I don't think many systems using reflection are going to be calling reflection based methods millions of times recursively..

Edit: the dynamic method is an interesting class..
Frank Hileman
Frank Hileman
VG.net
I agree with the original poster. None of these things need to be this way. Just look at other languages/virtual machines where overhead was considered more carefully during design. You can see examples where startup is fast, reflection is fast, basic memory overhead is minimal. From what I can tell it is a general reflection of a "code and move on" style of development, continual planned obsolecence.
Sven Groot
Sven Groot
My name has 9 letters. Coincidence? I think not...
DigitalDud wrote:
How is "looking up metadata in order to invoke a method" any different from doing a virtual call by looking up a vtable?

Because the vtable's layout is determined by the compiler. If you make a virtual call, the compiler will translate the method name into an index in the vtable. So at runtime, it's just a direct index.

With reflection, the type information must be loaded. The list of methods must be searched for one with a matching name for the one requested (string comparisons, which is slow). It has to check the type of the arguments (again something which the compiler normally does). Only then can it call the method.
RichardRudek
RichardRudek
So what do you expect for nothin'... :P
Sven Groot wrote:

Depends on what you're doing. A few reflection calls won't make a different, but do it millions of times in a tight loop and you'll feel it.

Reflection is not just slower, it's orders of magnitude slower than a regular method call. This is perfectly normal because of the extra work it has to do. If you're really worried about it, use a dynamic method.


Wow, talk about obfusticated.

Anyway, I thought you might be interested in the results from VB.NET, slightly revised, and including VB's late-binding abilities.

NOT optimised, and may have errors.

DEBUG:
Each test will perform 1000000 iterations.

Compiled        00:00:00.3801251
Dynamic Method  00:00:00.3956237
Reflection 1    00:00:10.0621492
Reflection 2    00:00:12.1479894
Late Binding    00:00:22.9242498

RELEASE:
Each test will perform 1000000 iterations.

Compiled        00:00:00.3749116
Dynamic Method  00:00:00.3929541
Reflection 1    00:00:08.9885750
Reflection 2    00:00:10.8800976
Late Binding    00:00:21.4694188

The source (Console):
Imports System
Imports System.Diagnostics
Imports System.Reflection
Imports System.Reflection.Emit

Class Foo
Private _bar As String

Public Property Bar() As String
Get
Return _bar
End Get
Set(ByVal value As String)
_bar = value
End Set
End Property
End Class

Module Module1
Public Const kITER = 1000000

Delegate Sub TestDelegate(ByVal arg As Foo, ByVal str As String)

Function CreateMethod() As TestDelegate
Dim args() As Type = {GetType(Foo), GetType(String)}
Dim method As New DynamicMethod("Test", Nothing, args, GetType(Module1))
Dim gen As ILGenerator = method.GetILGenerator()
gen.Emit(OpCodes.Ldarg_0)
gen.Emit(OpCodes.Ldarg_1)
Dim m As MethodInfo = GetType(Foo).GetProperty("Bar").GetSetMethod()
gen.EmitCall(OpCodes.Call, m, Nothing)
gen.Emit(OpCodes.Ret)
Return method.CreateDelegate(GetType(TestDelegate))
End Function


Sub Main()
Dim i As Integer
Dim f As New Foo
Dim w As New Stopwatch

Console.WriteLine("Each test will perform {0} iterations." & vbCrLf, kITER)

Console.Write("Compiled" & vbTab)
w.Start()
For i = 1 To kITER
f.Bar = i.ToString()
Next
w.Stop()
Console.WriteLine(w.Elapsed)

Console.Write("Dynamic Method" & vbTab)
Dim test As TestDelegate = CreateMethod()
w.Reset()
w.Start()
For i = 1 To kITER
test(f, i.ToString())
Next
w.Stop()
Console.WriteLine(w.Elapsed)

Console.Write("Reflection 1" & vbTab)
w.Reset()
w.Start()
Dim t As Type = f.GetType()
Dim pi As PropertyInfo = t.GetProperty("Bar")
For i = 1 To kITER
pi.SetValue(f, i.ToString(), Nothing)
Next
w.Stop()
Console.WriteLine(w.Elapsed)

Console.Write("Reflection 2" & vbTab)
w.Reset()
w.Start()
For i = 1 To kITER
Dim t2 As Type = f.GetType()
Dim pi2 As PropertyInfo = t2.GetProperty("Bar")
pi2.SetValue(f, i.ToString(), Nothing)
Next
w.Stop()
Console.WriteLine(w.Elapsed)

Console.Write("Late Binding" & vbTab)
Dim o As Object = f
w.Reset()
w.Start()
For i = 1 To kITER
o.Bar = i.ToString()
Next
w.Stop()
Console.WriteLine(w.Elapsed)

Console.Write(vbCrLf & "Done. Press a key")
Console.ReadKey()
End Sub

End Module

amotif
amotif
No Silver Bullet
Sven Groot wrote:
If you're really worried about it, use a dynamic method.


Interesting. Do you have any good references for learning IL op codes?
kachchhu
kachchhu
kachchhu

hello, i want know about only bill gates if you are american so that help me & give me conectivity of bill gates.....................................kachchhu fr:uk
      

Sven Groot wrote:
Reflection is not just slower, it's orders of magnitude slower than a regular method call. This is perfectly normal because of the extra work it has to do. If you're really worried about it, use a dynamic method.

I know that this is an old thread drudged up by that weird Bill Gates groupie, but I hadn't read this post in the past, and this DynamicMethod thing looks really interesting.  On the other hand, I may just use something like IronPython (or IronRuby or even VBX someday) if my code requirements are that dynamic, because DynamicMethod generation code smells.

Lloyd_Humph
Lloyd_Humph
If Blackberrys are addictive cellphones, Channel9 is the ultimate addictive website.
kachchhu wrote:


hello, i want know about only bill gates if you are american so that help me & give me conectivity of bill gates.....................................kachchhu fr:uk
      




big_g@nevergonnahappen.com
ManipUni
ManipUni
Proving QQ for 5 years!

try
{
Slow and dirty methods of doing things are slow and dirty. News at 11.
}

catch(Flame flame)
{
Use structured exception handling and reflection in your code only where absolutely necessary.
}


blowdart
blowdart
Peek-a-boo
ManipUni wrote:



catch(Flame flame)
{
Use structured exception handling and reflection in your code only where absolutely necessary.
}




And always forget the naming guidelines and call your exceptions exampleException Tongue Out
W3bbo
W3bbo
The Master of Baiters
blowdart wrote:

ManipUni wrote:


catch(Flame flame)
{
Use structured exception handling and reflection in your code only where absolutely necessary.
}




And always forget the naming guidelines and call your exceptions exampleException


That's one of the few things I don't like with many OOP languages: is that certain types of a BCL are integral to features of a language.


The normal types, I can understand: Intxx, String, Object, Array... but "Exception" is too special to be a class in a BCL.

How do other languages solve this problem?
blowdart
blowdart
Peek-a-boo
W3bbo wrote:

The normal types, I can understand: Intxx, String, Object, Array... but "Exception" is too special to be a class in a BCL.

How do other languages solve this problem?


Why special? It's part of the error handling approach, so it belongs in there. What's your thinking behind this?
ManipUni
ManipUni
Proving QQ for 5 years!
blowdart wrote:
And always forget the naming guidelines and call your exceptions exampleException


Name guidelines and common sense are overrated. I name all my variables letters of the alphabet starting at A on up. If some variables are related I add 0-9 to the end ...

e.g.

Object b33 = new String("hello world");

I also hard-code all of my strings because English is the only language. Nice trick ... To reduce the number of variables you use setup a ton of objects, and randomly change what they do though-out the execution path.

PS - This post contains no sarcasm
Minh
Minh
WOOH! WOOH!
ManipUni wrote:

PS - This post contains no sarcasm

I can tell you play nice with others.

PS - This post is 50% sarcasm Smiley
blowdart
blowdart
Peek-a-boo
ManipUni wrote:

blowdart wrote:And always forget the naming guidelines and call your exceptions exampleException


Name guidelines and common sense are overrated. I name all my variables letters of the alphabet starting at A on up. If some variables are related I add 0-9 to the end ...

e.g.

Object b33 = new String("hello world");

I also hard-code all of my strings because English is the only language. Nice trick ... To reduce the number of variables you use setup a ton of objects, and randomly change what they do though-out the execution path.

PS - This post contains no sarcasm


You sir are a fool. You need to do the following

public readonly static string A = "A";
public readonly static string B = "B";

and so on, then concatenate them using the overloaded + operator for maximum flexibility


ManipUni
ManipUni
Proving QQ for 5 years!
Minh wrote:
I can tell you play nice with others.


Teach them for trying to mess with my code Tongue Out

evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
blowdart wrote:

ManipUni wrote:
blowdart wrote:And always forget the naming guidelines and call your exceptions exampleException


Name guidelines and common sense are overrated. I name all my variables letters of the alphabet starting at A on up. If some variables are related I add 0-9 to the end ...

e.g.

Object b33 = new String("hello world");

I also hard-code all of my strings because English is the only language. Nice trick ... To reduce the number of variables you use setup a ton of objects, and randomly change what they do though-out the execution path.

PS - This post contains no sarcasm


You sir are a fool. You need to do the following

public readonly static string A = "A";
public readonly static string B = "B";

and so on, then concatenate them using the overloaded + operator for maximum flexibility




Surely it's more secure to do

public readonly static string A = new string(new char[]{0x40});
public readonly static string B = new string(new char[]{0101});

because you then even have the advantage that A == "B" and B == "A".
page 1 of 1
Comments: 23 | Views: 7188
Microsoft Communities