|
For reference, a branch misprediction is less than 20 cycles on any reasonable µarch (ie excluding NetBurst), you can't do thousands of anything in that time.
|
|
|
|
|
Another issue is trying to debug it. If you get an error or exception then it's harder to debug when it's effectively a single statement.
harold aptroot wrote: Side question, why is this style popular?
I worked with someone that used linq wherever possible. His argument was that it was "faster". I think people think that because something is new it's fast *shrug*
|
|
|
|
|
That's really weird, I would have thought that anyone who likes speed tests to see how fast it really is, or at least looks up someone elses test.. and then they'd never use this style again.
|
|
|
|
|
Or you know, some one can be aware of the costs and still make decision to use this style? Almost as if speed is not top priority all the time. In parts that you really care about performance - write it in C++, slap managed wrapper around and call it a day. For everything else - enjoy modern1 features which make your life easier.
1 - if you can call something that is 10 years modern, in programming world.
|
|
|
|
|
Yes, but you can't use this style for speed, because it doesn't offer that.
|
|
|
|
|
Depends what you mean by "speed". Speed of execution, of course not. But speed of coding, sure. You could argue that it doesn't make a big difference in coding it, but I'd argue that using a for loop instead of this approach doesn't make a big difference (per iteration) either. It's all in how you use it.
|
|
|
|
|
I put each method call on a separate line for this very reason.
e.g.
someStuff
.Where(c => c != What)
.Select(d => d + The)
.Foreach(e => Hell(e));
What do you get when you cross a joke with a rhetorical question?
The metaphorical solid rear-end expulsions have impacted the metaphorical motorized bladed rotating air movement mechanism.
Do questions with multiple question marks annoy you???
|
|
|
|
|
Does that actually work for simplifying debugging now?
I haven't done any major LINQ work since VS2010; but then it would treat everything upto the semicolon as a single statement regardless of the newlining.
Debugging into it required replacing all the .'s with ;'` newlines and temp variables.
Did you ever see history portrayed as an old man with a wise brow and pulseless heart, waging all things in the balance of reason?
Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful?
--Zachris Topelius
Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies.
-- Sarah Hoyt
|
|
|
|
|
No, it doesn't help for debugging. I think it helps for readability, though. I keep the first one on the same line and then line up all the dots like so:
someStuff.Where(c => c != What)
.Select(d => d + The)
.Foreach(e => Hell(e));
|
|
|
|
|
For debugging, though, if you convert the lambda expression into a lambda statement, you can put a breakpoint in it. That can help in debugging. Usually what I end up doing is split the fluent chain into separate pieces if I need to debug it.
That being said, this is usually a style I employ as I'm finishing up code and have already tested it while doing my normal refactoring. (and when I know high performance is not necessary)
|
|
|
|
|
I just set breakpoints on the lambda expressions in the statements. The debugger is a little finicky on setting them there -- you have to click somewhere in the RHS of the lambda and then hit F9 to set the breakpoint. No harder to debug than any other bit of code.
I use Linq a lot, but for non-performant areas. I don't expect it to be faster to run, only faster to write, debug and maintain.
We can program with only 1's, but if all you've got are zeros, you've got nothing.
|
|
|
|
|
You can easily step into it using F11. You would see the deferred execution in action
|
|
|
|
|
He could have meant it was faster to write than do the foreach and the if statements. Not that it runs faster. And I find it is much faster to write.
|
|
|
|
|
No, he meant to execute. I set up some experimental code that looped many times using the various methods like native code and linq and timed them. I also pointed out that the linq code was using anonymous methods and that they had overhead too.
|
|
|
|
|
Writing all of your code in one big Main function is faster than any of this "object-oriented" nonsense.
And using C or assembly will be much faster than this JIT-compiled C# nonsense.
Of course, it will take a lot longer to write, and be much harder to debug. But premature optimization is much more important than sleep!
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
It's about trade-offs though. There is nothing wrong with going for a worse performing technology\method if you gain elsewhere and the gain is an acceptable trade. But using linq over a foreach gives no real gain in the kind of situations we're talking about, so for no gain you are suffering in performance.
|
|
|
|
|
F-ES Sitecore wrote: using linq over a foreach gives no real gain
Except for more readable* and concise code.
* For those of us who have been assimilated.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
That's a matter of opinion, in one of the articles posted on this thread MS explain why there is no ForEach for List and the reason being that it is less readable and offers no real advantage over the native foreach.
You also forget "harder to debug"
|
|
|
|
|
As others have pointed out, ForEach is the odd man out here. A foreach loop of the results of the sequence returned from LINQ is the better option.
But the bulk of LINQ is about telling the compiler what to do, not how to do it. And that makes the code much more readable (for some).
Imagine you start with a big block of code in a single method. It takes a list, filters it, sorts it, groups it, filters it some more, projects it, and then processes it. You've got a fairly complex method which is specific to one task. If you need to repeat any of those operations, you have to duplicate the code.
The first thing you would do is refactor the code, to move some of the common operations out into separate, simpler, reusable methods. You could then write simple unit tests for those methods, without having to set up the more complicated data for your original method, and without having to work out which part of the original method failed if the tests failed.
Then, you would reuse those simpler methods elsewhere when you needed to do the same thing. Need to filter a list? Call SomeClass.FilterAList . Need to group a list? Call SomeClass.MakeSomeGroups .
Pretty soon, you end up with a collection of utility methods that you're reusing everywhere. But the syntax is quite nasty:
var source = GetAList();
var filtered = SomeClass.FilterAList(source, SomeFilter);
var sorted = SomeClass.MakeItSorted(filtered, SomeSortingCondition);
var grouped = SomeClass.MakeSomeGroups(sorted, SomeGroupingCondition);
var filteredAgain = SomeClass.FilterAList(grouped, AnotherFilter);
var result = SomeClass.ProjectAList(filteredAgain, SomeProjection);
var result = SomeClass.ProjectAList(
SomeClass.FilterAList(
SomeClass.MakeSomeGroups(
SomeClass.MakeItSorted(
SomeClass.FilterAList(
GetAList(),
SomeFilter),
SomeSortingCondition),
SomeGroupingCondition),
AnotherFilter),
SomeProjection);
To tidy it up, you would like to be able to call each utility method as if it was defined on the IEnumerable<T> interface. You can't add the methods to the interface, since that would break everything that implemented it. So instead, you introduce extension methods, and the syntax becomes:
var result = GetAList()
.FilterAList(SomeFilter)
.MakeItSorted(SomeSortingCondition)
.MakeSomeGroups(SomeGroupingCondition)
.FilterAList(AnotherFilter)
.ProjectAList(SomeProjection);
Now it's much easier to see what's going on, which condition applies to which operation, etc.
Change the method names, and you've effectively reinvented LINQ.
F-ES Sitecore wrote: You also forget "harder to debug"
Only if you're trying to debug the framework code. If you stick to debugging your own code, it's easier to debug, because there's less of it.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I'm talking about using linq to foreach a collection vs using foreach. As I said in my post, it is fine to use linq if you are getting advantages such as in the example you just posted, but I thought I made it pretty clear that was not the kind of code I was talking about and also that I never said to never use linq.
Richard Deeming wrote: If you stick to debugging your own code, it's easier to debug, because there's less of it
var result = GetAList()
.FilterAList(SomeFilter)
.MakeItSorted(SomeSortingCondition)
.MakeSomeGroups(SomeGroupingCondition)
.FilterAList(AnotherFilter)
.ProjectAList(SomeProjection);
That line throws a null exception...can you look at the line that threw the exception and know what the issue is?
|
|
|
|
|
F-ES Sitecore wrote: That line throws a null exception...can you look at the line that threw the exception and know what the issue is?
Assuming I'm using LINQ, the most likely culprit would be GetAList returning null .
Failing that, I'd have a stack-trace to tell me where the exception occurred.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
But you agree it wouldn't be immediately obvious like it would if you weren't using linq?
|
|
|
|
|
If I wasn't using LINQ, then I'd be able to identify which line in the massive complicated method the exception was thrown from.
Whether it would be obvious why the exception was thrown is a different matter.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
So it's easier to debug without linq?
|
|
|
|
|
No, because you've still got a massive overly-complicated method to dig through to find the cause of the problem.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|