If reflection is inefficient, when is it most appropriate?
Asked Answered
C

7

17

I find a lot of cases where I think to myself that I could use relfection to solve a problem, but I usually don't because I hear a lot along the lines of "don't use reflection, it's too inefficient".

Now I'm in a position where I have a problem where I can't find any other solution than to use reflection with new T(), as outlined in this question & answer.

So I'm wondering if somebody can tell me reflection's specific intended usage, and if there's a set of guidelines to indicate when it's appropriate and when it isn't?

Camillacamille answered 31/7, 2010 at 9:40 Comment(0)
T
26

It is often "fast enough", and if you need faster (for tight loops etc) you can do meta-programming with Expression or ILGenerator (perhaps via DynamicMethod), to make extremely fast code (including some tricks you can't do in C#).

Reflection is more commonly used for framework/library scenarios, where the library by definition knows nothing about the caller, and must work based on configuration, attributes or patterns.

Tribade answered 31/7, 2010 at 9:49 Comment(3)
On .NET 4.0, there's also the option of dynamic, which has optimizations such as call site caching. So there's an intermediate step between reflection and metaprogramming. In fact, I use dynamic whenever I can instead of directly using reflection, just for readability.Trisect
+1 for ILGenerator and DynamicMethod; they can be a lot of fun and are perfect for the rare cases when Reflection is too slow (generally because you want to use it repeatedly in an inner loop.) They can be addictive, though and code using Emit is harder to maintain (some of my colleagues look at code I've written using Emit and treat it like some sort of voodoo magic.)Rossie
@Dan - you want to see some of the goo in protobuf-net "v2" then; meta-programming in extremis ;pTribade
H
26

If there's one thing that I hate hearing it's "don't use reflection, it's too inefficient".

Too inefficient for what? If you're writing a console application that's run once a month and isn't time critical, does it really matter if it takes 30 seconds instead of 28, because of you using reflection?

Guidelines for when it's inappropriate to use are ones that only you can really put together as they're heavily dependent on what you're doing and how efficient/performant alternatives are.

Hydrophyte answered 31/7, 2010 at 9:42 Comment(5)
I like the point you're making rob, I keep hearing it but I'm sure the people I'm hearing it from heard it from someone else, who in turn heard it from someone else..... that's the point of the question. I'd like to know for myself when it's right or wrongCamillacamille
@DaveDev, it's never right or wrong in and of itself, it's how you use it. It's kinda like that saying "guns don't kill people, people do".Hydrophyte
It's right when you need it, or when other solutions would be too complicated.Accomplished
Nowadays it also means "don't use IoC" and "don't use unit testing frameworks".Harrus
@Camillacamille yes, people get paranoid about reflections possible performance problem. Those people often do not have much clue about the inner working of a language or compiler.Hm
T
26

It is often "fast enough", and if you need faster (for tight loops etc) you can do meta-programming with Expression or ILGenerator (perhaps via DynamicMethod), to make extremely fast code (including some tricks you can't do in C#).

Reflection is more commonly used for framework/library scenarios, where the library by definition knows nothing about the caller, and must work based on configuration, attributes or patterns.

Tribade answered 31/7, 2010 at 9:49 Comment(3)
On .NET 4.0, there's also the option of dynamic, which has optimizations such as call site caching. So there's an intermediate step between reflection and metaprogramming. In fact, I use dynamic whenever I can instead of directly using reflection, just for readability.Trisect
+1 for ILGenerator and DynamicMethod; they can be a lot of fun and are perfect for the rare cases when Reflection is too slow (generally because you want to use it repeatedly in an inner loop.) They can be addictive, though and code using Emit is harder to maintain (some of my colleagues look at code I've written using Emit and treat it like some sort of voodoo magic.)Rossie
@Dan - you want to see some of the goo in protobuf-net "v2" then; meta-programming in extremis ;pTribade
A
23

A useful abstraction for code efficiency is to partition it in three categories of time, each about 3 orders of magnitude apart.

First is human-time. There's a lot you can do when you only need to keep a person happy with the performance of your code. Humans cannot perceive the difference between code that needs 10 milliseconds or 20 milliseconds, both look instant. And a human is forgiving when a program needs 6 seconds instead of 5, roughly 3 billion machine instructions more. Common examples of programs that run at human-time are compilers and point-and-click designers. Using reflection is never a problem.

Then there is I/O-time. When your program needs to hit the disk or the network. I/O is slow, restricted by mechanical motion in the case of the disk, bandwidth and latency in the case of a network. You can always tell when I/O is the bottleneck, your program is running but it isn't driving up the CPU load much. The operating system is constantly blocking the thread, making it wait until the I/O request is complete.

Reflection operates at I/O-time. To retrieve type data, the CLR must read the assembly metadata. And when that wasn't done before, your program will cause a page-fault, requiring the operating system to read the data from disk. What follows is that, roughly, reflection can make I/O bound code only twice as slow. Usually better because after the first perf hit, the metadata is cached and can be retrieved a lot quicker. Reflection is thus often an acceptable trade-off. The canonical examples are serialization and dbase ORMs.

Then there's machine-time. The raw performance of a CPU core is stupendous. A property getter can execute in somewhere between 0 and 1/2 a nanosecond. This does not compare favorably with, say, PropertyInfo.GetValue(). Both will keep the CPU busy, you'll see the CPU load for the core at 100%. But GetValue() costs hundreds if not thousands of machine code instructions. Not counting the time needed to page in the metadata. While not much an incremental time, it builds up fast when you loop.

If you cannot classify your reflection code in the human-time or I/O-time categories then reflection is unlikely to be an appropriate substitute for regular code.

Agram answered 31/7, 2010 at 14:23 Comment(3)
"And when that wasn't done before, your program will cause a page-fault" Does this mean that running a GetType().GetMethod("prefix_" + userInputString).Invoke() and Activator.CreateInstance(Type.GetType(userInputString)) and MethodBase.GetCurrentMethod() will only be slow the first time it is called in each method, but in all subsequent calls it will NOT be inefficient ? This is what I usually use it for, and I can sure live with it if the inefficiency is limited to the first couple of times it is called after the application has started.Cloudlet
Beautifully put! When you're trying to let the CPU blaze, don't bog it down with anything that needs it to check on itself (the true meaning of reflection).Dg
@nl-x: The second and subsequent use is probably 100 times faster than the first use... but still a thousand times slower than direct access. (Well, all code in a JIT infrastructure is immensely slower the first time it is used, because that's when the JIT compiler runs). In contrast, calling a delegate that was created via reflection, as my answer suggests, is only about 3x slower than direct. So if you're going to make the call more than once, consider caching, and if more than 5 times, consider caching a requirement.Osmanli
O
9

The key to keeping reflection from slowing down your program is to not use it inside a loop. If you want to read a property from an object during startup (happens once), use reflection. You want to read a property from a list of 10,000 objects of unknown type, use reflection to get the property getter delegate once (search term: PropertyInfo.GetGetMethod), then call the delegate 10,000 types. There are plenty of examples of this on StackOverflow.

Osmanli answered 31/7, 2010 at 14:37 Comment(1)
Very useful tip to get the delegate fist and invoke it when looping.Unruh
M
8

Reflection is not inefficient. It is less efficient than direct calls. So personnaly I use reflection when there's no equivalent compile time safe method. IMHO the problem with reflection is not so much the efficiency but the fragility of the code as it uses magic strings which are very refactor unfriendly.

Mispleading answered 31/7, 2010 at 9:42 Comment(0)
W
5

I use it for plugin architecture - looking through assemblies in the plugin folder for methods marked with a custom attribute indicating info about the plugin - and in a logging framework. The framework detects a custom attribute on the assembly itself which holds information about the author of the assembly, the project, version information, and other tags that are logged along with everything in the stack trace.

Going to give away a 'trade secret', but it's a good one. The framework allows you to tag each method or class with a 'Story ref', e.g.

[StoryRef(Ref="ImportCSV1")]

...and the idea is it would integrate into our agile project management framework: if there were any exceptions thrown within that class/method, the logging method would use reflection to check for a StoryRef attribute in the stack trace, and if so that would be logged as an exception against that story. In the PM software you could see exceptions by Story (a story is like an extreme/agile use case).

I think that's a valid use, at least! Basically, when it just seems the most neat, and appropriate way to do it, I use reflection. Nothing else really comes into it - I can't think of an occasion you'd be using reflection to make that many calls that efficiency would come into it.

Wadi answered 31/7, 2010 at 9:43 Comment(0)
U
2

So I'm wondering if somebody can tell me reflection's specific intended usage, and if there's a set of guidelines to indicate when it's appropriate and when it isn't?

A bad example of reflection is this one from Wikipedia:

//Without reflection
Foo foo = new Foo();
foo.Hello();

//With reflection
Type t = Type.GetType("FooNamespace.Foo");
object foo = Activator.CreateInstance(t);
t.InvokeMember("Hello", BindingFlags.InvokeMethod, null, foo, null);

Here, there is no advantage to using reflection: The non-reflection-using code is not only more efficient, but easier to understand.

Good uses of reflection are things like serialization and object-relational mapping, which are easy to implement if you have a list of a class's properties, but otherwise require a custom-written function for each class.

Uncinariasis answered 31/7, 2010 at 15:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.