|
That's fair.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
|
|
Voted up your 5 star article for that. It needs to be explained. Nice drill down.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Interesting.
While the article is correct for C it's not entirely correct for C#. C# actually defines the order of execution to be Left-associative or Right-associative depending on the operator. C# operators - C# reference | Microsoft Docs[^]
|
|
|
|
|
It is a very clear compiler optimization...
"The only place where Success comes before Work is in the dictionary." Vidal Sassoon, 1928 - 2012
|
|
|
|
|
Microsoft's C# compiler as a rule, does barely anything to optimize, punting it all to the jit compiler, which does peephole optimizations. It *may* optimize those out, and it may not. NGen'd assemblies might, but that's a different story.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
I'm literally looking at the IL right now and there are no extra variables when using i++. What you see in the source isn't what is compiled to IL, and what is in IL isn't what is compiled to machine code, and what is compiled to machine code isn't what the CPU executes. You have to learn to stop worrying about how inefficient you think code looks and trust that everything downstream will work it out.
|
|
|
|
|
what's moved is where the pop is like you said. Most of the time, when small locals can be removed with stack operations they are. Has little to do with post, and pre, and everything to do with what's on the stack at that point. The internal extra storage is had by the stack rather than explicit var, so what? it's still storing it. It's just semantic at this point, because of where it's storing it. If the intermediary value isn't needed it doesn't need to be stored at all, and the fact that it is means *other* locals potentially cannot be moved to the stack.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
"x = ++i" loads i onto the stack, pushes 1 onto the stack, adds them, duplicates the return (so two copies of i+1 are on the stack), pops one into i and one into x.
"x = i++" loads i onto the stack, duplicates it (so there are two copies of i on the stack), pushes 1 onto the stack, adds them (now there is i and i+1 on the stack), pops one into i and one into x.
Both operations involve three stack values and six operations so are no more or less efficient than each other.
|
|
|
|
|
as long as there aren't any other variables being relocated to the stack at the time of your operation it holds. But if there is, then it doesn't, because the top of the stack is now a competed for resource between that variable and your post increment operator which was part of the point of my other reply.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
honey the codewitch wrote: as long as there aren't any other variables being relocated to the stack at the time of your operation it holds
There aren't, and regardless the pre and post versions of the operator have the same access so neither is more or less efficient than each other. Besides, stack access is of no real concern when it comes to performance. The memory is pre-allocated and it simply involves changing a stack pointer.
|
|
|
|
|
all .NET IL ops that operate on the stack must operate on the TOP of the stack, so yes, it's a contested resource. In the case where there are two competing resources for doing ops, you must store in a local variable in IL, and operate on that.
Unlike x86 code you can't directly manipulate the stack pointer in IL, IIRC
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
honey the codewitch wrote: all .NET IL ops that operate on the stack must operate on the TOP of the stack
Yes, that's how stacks work. In other news grass is green and water is wet.
honey the codewitch wrote: it's a contested resource.
That's a strawman argument, I didn't say it wasn't. You are also attempting to shift the goalposts away from the comparative performance of i++ vs ++i (your original argument) and onto if stack operations are performant or not. In terms of underlying code there is no difference in efficiency of i++ and ++i which is what your initial claim was.
|
|
|
|
|
except in something like x86 the stack pointer is manipulatable.
If you have a ceq or something to perform you need to do it on the stack, which means extra pushes and (and later pops) to move it, which means more instructions which is why i say the resource is in contention.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
It's interesting that despite the fact that I have told you you're moving the argument away from what you said (i++ is less efficient) onto something no-one is disputing (how stacks work) you are still doing it.
"Yeah, you're right, they are the same" is all you had to say
|
|
|
|
|
I don't agree with your characterization of my comment, and I don't think we're going to agree, so I'm disengaging.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
What you say
honey the codewitch wrote: I don't agree with your characterization of my comment, and I don't think we're going to agree, so I'm disengaging.
What I hear
honey the codewitch wrote: I don't want to admit I was wrong so I'm just going to stick my fingers in my ears.
|
|
|
|
|
The (type)value cast syntax is even more of a joke to parse, an opening paren is not enough context to know whether to parse type as a type or not and by the time you get to the "missing operator" it's already too late. Bonus points for having a non-trivial type-language (where type can consist of any number of terminals), so you can't disambiguate it with a constant amount of lookahead.
|
|
|
|
|
I ran into that two days ago and made my parser backtrack to accommodate.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
You are welcome to outlaw postfix operators in your code generator. Just be prepared for the howls of protest from the potential users.
At the very least, I would add a check for postfix operators, with a clear message saying that they are not supported, and should be replaced by the prefix form.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Frankly, the CodeDOM gets plenty of howls of protest from its users!
Fortunately, slang isn't designed to be a full language replacement. It's just a helper for making abstract generated code.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Well - how about you build your compiler so the ++ and -- operators are clever enough to use inc and dec on the assembly side? That's generally faster than actual addition.
You're (sort of) treating them like += and -= . . . and that would work, take advantage of their unique signature for that extra speed boost in a operation that is often repeated.
You read OG's tome so I don't need to tell you why you need both and how they interact. Interesting that two different language's spec's can result in different answers (on occasion)
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
I'm only building roughly 2/3 of what a compiler does. The code generation isn't part of it. Instead I'm rendering to an abstract-syntax-tree of code elements that are rendered to a target .NET language via a 3rd party.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
honey the codewitch wrote: is ++<target> really so much worse that <target>++?
No. Based on my super intense all conclusive test, they are same. Here is the test. I hope you can understand this complex set up.
static void Main(string[] args)
{
List<double> preIncrement = new List<double>();
List<double> postIncrement = new List<double>();
for (int i = 0; i < 10000; i++)
{
preIncrement.Add(PreIncrement());
postIncrement.Add(PostIncrement());
}
double letsSeeIfYouAreABadOperator = preIncrement.SkipWhile(x => x == 0).Average();
double youBetterPerformWell = postIncrement.SkipWhile(x => x == 0).Average();
}
private static double PreIncrement()
{
DateTime start1 = DateTime.Now;
int i = 0;
int x = 1;
int y = 1;
for (i = 0; i < 100000; i++)
{
x = ++y;
}
DateTime end1 = DateTime.Now;
return (end1 - start1).TotalMilliseconds;
}
private static double PostIncrement()
{
DateTime start1 = DateTime.Now;
int i = 0;
int x = 1;
int y = 1;
for (i = 0; i < 100000; i++)
{
x = y++;
}
DateTime end1 = DateTime.Now;
return (end1 - start1).TotalMilliseconds;
}
"It is easy to decipher extraterrestrial signals after deciphering Javascript and VB6 themselves.", ISanti[ ^]
|
|
|
|