Visual Studio Debugger Voodoo - c#

Ok, maybe this isn't so amazing considering I don't really understand how the debugger works in the first place, let alone Edit and Continue, which is totally amazing.
But I was wondering if anyone knew what the debugger is doing with variable declarations in this scenario. I can be debugging through my code, move the line of execution ahead - past a variables initial declaration and assignment, and the code still runs ok. If it's a value type it will have it's default value, for a ref type, null.
So if I create a function that uses a variable before it's declared it won't compile, but if I use the debugger to run it that way it will still run without error. Why is this? And is this related to the fact that you can't put a breakpoint on a declaration?

Yes, those declarations are more structural. They're part of the locals on the stack that are allocated as the method is called. You can't break on them because they don't really happen where you write them - they're not instructions.
The reason the compiler won't let you use them before they are declared is mostly for your sanity - you always know to look up for a declaration. Complex scoping of variables within a method would further illustrate this point.

According to the article Gain performance by not initializing variables:
In .NET, the Common Language Runtime (CLR) expressly initializes all variables as soon as they are created. Value types are initialized to 0 and reference types are initialized to null.
Presumably the debugger already knows about these variables either because the code is already compiled, or (seems less likely now that I am typing it, but) the debugger is smart enough to detect that a variable was declared.

I think that because you are using the debugger, you are confusing the two different activities, compile and execute, and the two different statement types, declarative and functional.
When you compile, a declarative statement tells the compiler to reserve some memory for your variable. It says "oh, you want to declare an integer named "wombatCount"; OK, I'll take address 0x1234 and reserve four bytes just for you and stick a label on them called wombatCount." That happens during the compile, long before you run your code. *
When you execute the code in the debugger, you are running your code, so it already knows about every byte of memory it reserved for you. The variable wombatCount is already associated with four bytes at address 0x1234, so it can immediately access and change that data at any time, not just after your declaration statement. Your program can't, of course, but the debugger can.
The C# language syntax demands that you declare the memory before using it in your code, but that's just part of the language definition, and not a hard-and-fast requirement of all compilers. There are languages that do not require you to pre-declare your variables at all, and there are even some ancient languages where you can declare variables at any point in the code, not just "above" where you'll use them. But language developers now understand that the language syntax is most important for human understanding, and is no longer for ease of machine encoding or helping the compiler writers, so modern language syntaxes are generally created to help the programmers as much as possible. This means making things less confusing, so "declarations must come first" is a common rule to help you avoid mistakes.
(*To be more technically correct, I believe that in .Net the labels are only associated at compile time with a list of pointers that will reserve memory at run time, but the data bytes are not actually allocated until you use them. The difference is internal, and not very important to your understanding. The important takeaway is that a declarative statement declares the label in advance, during compile time.)

Related

Why doesn't C# compiler optimize unnecessary bit-wise operations? [duplicate]

Please ignore code readability in this question.
In terms of performance, should the following code be written like this:
int maxResults = criteria.MaxResults;
if (maxResults > 0)
{
while (accounts.Count > maxResults)
accounts.RemoveAt(maxResults);
}
or like this:
if (criteria.MaxResults > 0)
{
while (accounts.Count > criteria.MaxResults)
accounts.RemoveAt(criteria.MaxResults);
}
?
Edit: criteria is a class, and MaxResults is a simple integer property (i.e., public int MaxResults { get { return _maxResults; } }.
Does the C# compiler treat MaxResults as a black box and evaluate it every time? Or is it smart enough to figure out that I've got 3 calls to the same property with no modification of that property between the calls? What if MaxResults was a field?
One of the laws of optimization is precalculation, so I instinctively wrote this code like the first listing, but I'm curious if this kind of thing is being done for me automatically (again, ignore code readability).
(Note: I'm not interested in hearing the 'micro-optimization' argument, which may be valid in the specific case I've posted. I'd just like some theory behind what's going on or not going on.)
First off, the only way to actually answer performance questions is to actually try it both ways and test the results in realistic conditions.
That said, the other answers which say that "the compiler" does not do this optimization because the property might have side effects are both right and wrong. The problem with the question (aside from the fundamental problem that it simply cannot be answered without actually trying it and measuring the result) is that "the compiler" is actually two compilers: the C# compiler, which compiles to MSIL, and the JIT compiler, which compiles IL to machine code.
The C# compiler never ever does this sort of optimization; as noted, doing so would require that the compiler peer into the code being called and verify that the result it computes does not change over the lifetime of the callee's code. The C# compiler does not do so.
The JIT compiler might. No reason why it couldn't. It has all the code sitting right there. It is completely free to inline the property getter, and if the jitter determines that the inlined property getter returns a value that can be cached in a register and re-used, then it is free to do so. (If you don't want it to do so because the value could be modified on another thread then you already have a race condition bug; fix the bug before you worry about performance.)
Whether the jitter actually does inline the property fetch and then enregister the value, I have no idea. I know practically nothing about the jitter. But it is allowed to do so if it sees fit. If you are curious about whether it does so or not, you can either (1) ask someone who is on the team that wrote the jitter, or (2) examine the jitted code in the debugger.
And finally, let me take this opportunity to note that computing results once, storing the result and re-using it is not always an optimization. This is a surprisingly complicated question. There are all kinds of things to optimize for:
execution time
executable code size -- this has a major effect on executable time because big code takes longer to load, increases the working set size, puts pressure on processor caches, RAM and the page file. Small slow code is often in the long run faster than big fast code in important metrics like startup time and cache locality.
register allocation -- this also has a major effect on execution time, particularly in architectures like x86 which have a small number of available registers. Enregistering a value for fast re-use can mean that there are fewer registers available for other operations that need optimization; perhaps optimizing those operations instead would be a net win.
and so on. It get real complicated real fast.
In short, you cannot possibly know whether writing the code to cache the result rather than recomputing it is actually (1) faster, or (2) better performing. Better performance does not always mean making execution of a particular routine faster. Better performance is about figuring out what resources are important to the user -- execution time, memory, working set, startup time, and so on -- and optimizing for those things. You cannot do that without (1) talking to your customers to find out what they care about, and (2) actually measuring to see if your changes are having a measurable effect in the desired direction.
If MaxResults is a property then no, it will not optimize it, because the getter may have complex logic, say:
private int _maxResults;
public int MaxReuslts {
get { return _maxResults++; }
set { _maxResults = value; }
}
See how the behavior would change if it in-lines your code?
If there's no logic...either method you wrote is fine, it's a very minute difference and all about how readable it is TO YOU (or your team)...you're the one looking at it.
Your two code samples are only guaranteed to have the same result in single-threaded environments, which .Net isn't, and if MaxResults is a field (not a property). The compiler can't assume, unless you use the synchronization features, that criteria.MaxResults won't change during the course of your loop. If it's a property, it can't assume that using the property doesn't have side effects.
Eric Lippert points out quite correctly that it depends a lot on what you mean by "the compiler". The C# -> IL compiler? Or the IL -> machine code (JIT) compiler? And he's right to point out that the JIT may well be able to optimize the property getter, since it has all of the information (whereas the C# -> IL compiler doesn't, necessarily). It won't change the situation with multiple threads, but it's a good point nonetheless.
It will be called and evaluated every time. The compiler has no way of determining if a method (or getter) is deterministic and pure (no side effects).
Note that actual evaluation of the property may be inlined by the JIT compiler, making it effectively as fast as a simple field.
It's good practise to make property evaluation an inexpensive operation. If you do some heavy calculation in the getter, consider caching the result manually, or changing it to a method.
why not test it?
just set up 2 console apps make it look 10 million times and compare the results ... remember to run them as properly released apps that have been installed properly or else you cannot gurantee that you are not just running the msil.
Really you are probably going to get about 5 answers saying 'you shouldn't worry about optimisation'. they clearly do not write routines that need to be as fast as possible before being readable (eg games).
If this piece of code is part of a loop that is executed billions of times then this optimisation could be worthwhile. For instance max results could be an overridden method and so you may need to discuss virtual method calls.
Really the ONLY way to answer any of these questions is to figure out is this is a piece of code that will benefit from optimisation. Then you need to know the kinds of things that are increasing the time to execute. Really us mere mortals cannot do this a priori and so have to simply try 2-3 different versions of the code and then test it.
If criteria is a class type, I doubt it would be optimized, because another thread could always change that value in the meantime. For structs I'm not sure, but my gut feeling is that it won't be optimized, but I think it wouldn't make much difference in performance in that case anyhow.

C# get object that was on top of stack before exception

I am creating an interpreted programming language in C# (kind of for the lulz, no real purpose other than to have fun and learn about compilers), and ran into a problem. In my lexer, I remember where the token was in the original file to give more useful debug errors. I keep this "TokenPosition" object around, copying it along as the program goes through compile steps, until it winds up in the same object that runs interpreted code (for example, my "Identifier" class for named variables has a TokenPosition member).
My question: If an exception gets thrown, I want to look at the stack, find the topmost object with a TokenPosition member, and print its location. Or, more generally, "How do I get objects that are/were on the stack after an exception? Is this even possible?" (I can do the checking if it has a TokenPosition object / getting it easily, I'm not asking how to do that)
Last resorts that I do not want to have to do: Every single call to a behavior (which happens A LOT) assign a static tokenPosition variable somewhere with this.tokenPosition. I also could surround EVERYTHING with try/catches, but again, I don't really want to do this.
Parameters to methods are ephemeral. They may be overwritten by local variables when they are no longer live, or optimized out by the JIT compiler as unused, or even garbage collected while the method is running. You will have to track this information yourself, for example, by having a separate stack data structure for "currently active object" that is automatically unwound by a using clause.

Why aren't Automatic Properties inlined by default?

Being that properties are just methods under the hood, it's understandable that the performance of any logic they might perform may or may not improve performance - so it's understandable why the JIT needs to check if methods are worth inlining.
Automatic properties however (as far as I understand) cannot have any logic, and simply return or set the value of the underlying field. As far as I know, automatic properties are treated by the Compiler and the JIT just like any other methods.
(Everything below will rely on the assumption that the above paragraph is correct.)
Value Type properties show different behavior than the variable itself, but Reference Type properties supposedly should have the exact same behavior as direct access to the underlying variable.
// Automatic Properties Example
public Object MyObj { get; private set; }
Is there any case where automatic properties to Reference Types could show a performance hit by being inlined?
If not, what prevents either the Compiler or the JIT from automatically inlining them?
Note: I understand that the performance gain would probably be insignificant, especially when the JIT is likely to inline them anyway if used enough times - but small as the gain may be, it seems logical that such a seemingly simple optimization would be introduced regardless.
EDIT: The JIT compiler doesn't work in the way you think it does, which I guess is why you're probably not completely understanding what I was trying to convey above. I've quoted your comment below:
That is a different matter, but as far as I understand methods are only checked for being inline-worthy if they are called enough times. Not the mention that the checking itself is a performance hit. (Let the size of the performance hit be irrelevant for now.)
First, most, if not all, methods are checked to see if they can be inlined. Second, keep in mind that methods are only ever JITed once and it is during that one time that the JITer will determine if any methods called inside of it will be inlined. This can happen before any code is executed at all by your program. What makes a called method a good candidate for inlining?
The x86 JIT compiler (x64 and ia64 don't necessarily use the same optimization techniques) checks a few things to determine if a method is a good candidate for inlining, definitely not just the number of times it is called. The article lists things like if inlining will make the code smaller, if the call site will be executed a lot of times (ie in a loop), and others. Each method is optimized on its own, so the method may be inlined in one calling method but not in another, as in the example of a loop. These optimization heuristics are only available to JIT, the C# compiler just doesn't know: it's producing IL, not native code. There's a huge difference between them; native vs IL code size can be quite different.
To summarize, the C# compiler doesn't inline properties for performance reasons.
The jit compiler inlines most simple properties, including automatic properties. You can read more about how the JIT decides to inline method calls at this interesting blog post.
Well, the C# compiler doesn't inline any methods at all. I assume this is the case because of the way the CLR is designed. Each assembly is designed to be portable from machine to machine. A lot of times, you can change the internal behavior of a .NET assembly without having to recompile all the code, it can just be a drop in replacement (at least when types haven't changed). If the code were inlined, it breaks that (great, imo) design and you lose that luster.
Let's talk about inlining in C++ first. (Full disclosure, I haven't used C++ full time in a while, so I may be vague, my explanations rusty, or completely incorrect! I'm counting on my fellow SOers to correct and scold me)
The C++ inline keyword is like telling the compiler, "Hey man, I'd like you to inline this function, because I think it will improve performance". Unfortunately, it is only telling the compiler you'd prefer it inlined; it is not telling it that it must.
Perhaps at an earlier date, when compilers were less optimized than they are now, the compiler would more often than not compile that function inlined. However, as time went on and compilers grew smarter, the compiler writers discovered that in most cases, they were better at determining when a function should be inlined that the developer was. For those few cases where it wasn't, developers could use the seriouslybro_inlineme keyword (officially called __forceinline in VC++).
Now, why would the compiler writers do this? Well, inlining a function doesn't always mean increased performance. While it certainly can, it can also devastate your programs performance, if used incorrectly. For example, we all know one side effect of inlining code is increased code size, or "fat code syndrome" (disclaimer: not a real term). Why is "fat code syndrome" a problem? If you take a look at the article I linked above, it explains, among other things, memory is slow, and the bigger your code, the less likely it will fit in the fastest CPU cache (L1). Eventually it can only fit in memory, and then, inlining has done nothing. However, compilers know when these situations can happen, and do their best to prevent it.
Putting that together with your question, let's look at it this way: the C# compiler is like a developer writing code for the JIT compiler: the JIT is just smarter (but not a genius). It often knows when inlining will benefit or harm execution speed. "Senior developer" C# compiler doesn't have any idea how inlining a method call could benefit the runtime execution of your code, so it doesn't. I guess that actually means the C# compiler is smart, because it leaves the job of optimization to those who are better than it, in this case, the JIT compiler.
Automatic properties however (as far as I understand) cannot have any
logic, and simply return or set the value of the underlying field. As
far as I know, automatic properties are treated by the Compiler and
the JIT just like any other methods.
That automatic properties cannot have any logic is an implementation detail, there is not any special knowledge of that fact that is required for compilation. In fact, as you say auto properties are compiled down to method calls.
Suppose auto propes were inlined and the class and property are defined in a different assembly. This would mean that if the property implementation changes, you would have to recompile the application to see that change. That defeats using properties in the first place which should allow you to change the internal implementation without having to recompile the consuming application.
Automatic properties are just that - property get/set methods generated automatically. As result there is nothing special in IL for them. C# compiler by itself does very small number of optimizations.
As for reasons why not to inline - imagine your type is in a separate assembly hence you are free to change source of that assembly to have insanely complicated get/set for the property. As result compiler can't reason on complexity of the get/set code when it sees your automatic property first time while creating new assembly depending on your type.
As you've already noted in your question - "especially when the JIT is likely to inline them anyway" - this property methods will likely be inlined at JIT time.

How does the debugger get type information about an object initialized to null?

If an object is initialized to null, it is not possible to get the type information because the reference doesn't point to anything.
However, when I debug and I hover over a variable, it shows the type information. Only the static methods are shown, but still, it seems to know the type. Even in release builds.
Does the debugger use other information than just reflection of some sort to find out the datatype? How come it knows more than I? And if it knows this, why isn't it capable of showing the datatype in a NullReferenceException?
It seems like you're confusing the type of the reference with the type of the value that it points to. The type of the reference is embedded into the DLL metadata and as readily accessible by the debugger. There is also aditional information stored in the associated PDB that the debugger leverages to provide a better experience. Hence even for null references a debugger can determine information like type and name.
As for NullReferenceException. Could it also tell you the type on which it was querying a field / method ... possibly. I'm not familiar with the internals of this part of the CLR but there doesn't seem to be an inherent reason why it couldn't do so.
But I'm not sure the added cost to the CLR would be worth the benefit. I share the frustration about the lack of information for a null ref exception. But more than the type involved I want names! I don't care that it was an IComparable, i wanted to know it was leftCustomer.
Names are somethnig the CLR doesn't always have access to as a good portion of them live in the PDB and not metadata. Hence it can't provide them with great reliability (or speed)
Jared's answer is of course correct. Just to add a little to it:
when I debug and I hover over a variable, it shows the type information
Right. You have a bowl. The bowl is labelled "FRUIT". The bowl is empty. What is the type of the fruit in the bowl? You cannot say, because there isn't any fruit in the bowl. But that does not mean that you know nothing about the bowl. You know that the bowl can contain any fruit.
When you hover over a variable then the debugger can tell you about the variable itself or about its contents.
Does the debugger use other information than just reflection of some sort to find out the datatype?
Absolutely. The debugger needs to know not just what is the type of the thing referred to by this reference but also what restrictions are placed on what can be stored in this variable. All the information about what restrictions are placed on particular storage locations are known to the runtime, and the runtime can tell that information to the debugger.
How come it knows more than I?
I reject the premise of the question. The debugger is running on your behalf; it cannot do anything that you cannot do yourself. If you don't know what the type restriction on a particular variable is, it's not because you lack the ability to find out. You just haven't looked yet.
if it knows this, why isn't it capable of showing the datatype in a NullReferenceException?
Think about what is actually happening when you dereference null. Suppose for example you do this:
Fruit f = null;
string s = f.ToString();
ToString might be overloaded in Fruit. What code must the jitter generate? Let's suppose that local variable f is stored in a stack location. The jitter says:
copy the contents of the memory address at the stack pointer offset associated with f to register 1
The virtual function table is going to be, lets say eight bytes from the top of that pointer, and ToString is going to be, let's say, four bytes from the top of that table. (I am just making these numbers up; I don't know what the real offsets are off the top of my head.) So, start by adding eight to the current contents of register 1.
Now dereference the current contents of register 1 to get the address of the vtable into register 2
Now add four bytes to register 2
Now we have a pointer to the ToString method...
But hold on a minute, let's follow that logic again. The first step puts zero into register 1, because f contains null. The second step adds eight to that. The third step dereferences pointer 0x00000008, and the virtual memory system issues an exception stating that an illegal memory page has just been touched. The CLR handles the exception, determines that the exception happened on the first 64 K of memory, and guesses that someone has just dereferenced a null pointer. It therefore creates a null reference exception and throws it.
The virtual memory system surely does not know that the reason it dereferenced pointer 0x00000008 was because someone was trying to call f.ToString(). That information is lost in the past; the memory manager's job is to tell you when you touched something you don't have any right to touch; why you tried to touch memory you don't own is not its job to figure out.
The CLR could maintain a separate side data structure such that every time you accessed memory, it made a note of why you were attempting to do so. That way, the exception could have more information in it, describing what you were doing when the exception happened. Imagine the cost of maintaining such a data structure for every access to memory! Managed code could easily be ten times slower than it is today, and that cost is borne just as heavily by correct code as by broken code. And for what? To tell you what you can easily figure out yourself: which variable that contains null that you dereferenced.
The feature isn't worth the cost, so the CLR does not do it. There's no technical reason why it could not; it's just not practical.

Creating Local variables in .Net

I just want to know that creating local variables to accept the return value of function is going to hit memory usage or performance in .Net applications , especially in ASP.Net.
say
MyObject myObject = Foo();
MyOtherObject myOtherObject = Boo();
SomeFuntion(myObject, myOtherObject);
OR
Should I use
MyFunction(Foo(), Boo());
Certainly the former usage has a better readability.. But what about the memory usage and performance?
Thanks in advance
123Developer
Don't optimise prematurely; in a release build it is quite likely that the compiler will optimise these away anyway! Either way, you are just talking a tiny amount of stack space for (presumably) a few references. Either approach is fine; go with whichever is more readable.
CIL (the intermediate language into which C# is compiled) is a stack-based language so the return values of the intermediate functions need to end up on the stack before being passed as arguments to the final one anyway.
There's no way of predicting what the C# compiler will do[1] in terms of locals; it may decide to use locals when you do, or it may use the stack behaviour and skip them altogether. Similarly it may synthesize locals even when you don't use them, or it might not.
Either way, the performance difference isn't worth worrying about.
[1] Yes, of course, you can compile and look at the IL it produces to determine what it will do, but that is only valid for the current version of the compiler you're using and is an implementation detail you shouldn't rely on.
I believe the memory performance would be essentially the same. And unless performance testing were to show a significant difference, choose the option with enhanced readability.
Don't be afraid to use local variables. The difference in memory usage and performance is very small, or in some cases none at all.
In your specific case the local variables may use 8 bytes (16 bytes on a 64-bit application) of stack space. However, the compiler can create local variables by itself if it's needed for temporary storage, so it's possible that both versions have the same set of local variables anyway.
Also, the compiler can use processor registers instead of stack space for some local variables, so it's not even certain that creating a local variable actually uses any stack space at all.
Allocating stack space is very cheap anyhow. When the method is called, a stack frame is created for the local data in the method. If more memory has to be allocated, that will only change how much the stack pointer is moved, it will not produce any extra code at all.
So, just write the code so that it's maintainable and robust, and trust the compiler to optimize the variable usage.

Categories

Resources