Ransom has asked for the wisdom of the Perl Monks concerning the following question:
This is more of a silly style question but the issue is cropping up more and more in the code I'm working on. Which of the following code block is more "correct"? Better yet, which provides better performance.
foreach (@nodes) { my $tdev = parse_node($_); push (@device, $tdev) if defined($tdev); }
foreach (@nodes) { push (@device, parse_node($_) if defined(parse_node($_); }
My guess is that using the 2nd method would be faster, but only if parse_node is only called once for real. I'm afraid that the sub would get called twice and thus be twice as slow. On the other hand, creating a temp variable for each entry must have some overhead to worry about. In reality it doesn't matter for this project, but I'd like to know before I make this mistake in a bad place.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Temp variable performace vs Inline behavior
by BrowserUk (Patriarch) on Jun 27, 2012 at 15:05 UTC | |
Apart from the fact that, as posted, your two snippets do different things (and the second is missing a ')'), I'd do that this way:
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
by Athanasius (Archbishop) on Jun 27, 2012 at 15:37 UTC | |
BrowserUk’s solution:
is compact and efficient, but has one side-effect: the assignment to $_ clobbers the contents of @nodes. In cases where this is undesirable, the following seems to do the same without the side-effect:
Or is there a simpler way? Athanasius <°(((>< contra mundum | [reply] [d/l] [select] |
by tobyink (Canon) on Jun 27, 2012 at 16:44 UTC | |
You could use the same technique but clobber a temporary array instead...
Or you could use map:
If parse_node was written to return the empty list in cases of failure (rather than returning the scalar undef), then it would just be:
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
| [reply] [d/l] [select] |
by Ransom (Beadle) on Jun 27, 2012 at 15:15 UTC | |
I've tested my script with both and get the same results. parse_node return a nodelet on success or undef on failure. Where is the difference? | [reply] |
by BrowserUk (Patriarch) on Jun 27, 2012 at 15:25 UTC | |
Calling parse_node() twice in order to avoid a temporary variable, is very unlikely to effect a performance gain. Unless parse_node() does almost nothing, in which case you would certainly gain more by in-lining it code in the loop. The grep solution will almost certainly prove faster. Either way, it probably isn't worth the effort unless this is likely to be called thousands or millions of times. My philosophy is "Optimise if it is worth it!". And that means concentrating ones effort where gains are likely to be measurable -- in the overall runtime. With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
by muba (Priest) on Jun 27, 2012 at 15:17 UTC | |
Where is the difference? In the number of times parse_node is called, for starters. | [reply] [d/l] |
|
Re: Temp variable performace vs Inline behavior
by muba (Priest) on Jun 27, 2012 at 15:10 UTC | |
I'd go for the first version, with the temporary variable, for the exact reason you mention: the second version has an extra call to the subroutine. The extra memory overhead shouldn't be much of a problem. I don't think you're dealing with gigabites of data here at once. Another reason the first version is preferable because the call to the subroutine in the if clause may have side effects that will affect the value that will be pushed onto the array. The following script demonstrates what I mean. Update: there was a stupid little error in the script. Fixed.
| [reply] [d/l] |
by Ransom (Beadle) on Jun 27, 2012 at 15:18 UTC | |
Thanks for the example and snippet. It's good to know that parse_node does indeed get called twice. | [reply] |
|
Re: Temp variable performace vs Inline behavior
by GrandFather (Saint) on Jun 28, 2012 at 01:15 UTC | |
creating a temp variable for each entry must have some overhead to worry about Umm, no, actually creating a temporary variable almost never has enough overhead to worry about. Creating a temporary copy of a large array or hash may impose enough overhead to worry about, but you'd find that out when you find that there is a speed (or other) issue and profile the code. Don't premature optimise code. Write code so it is clear, correct and maintainable first, then optimise if there is a problem.
True laziness is hard work
| [reply] |
|
Re: Temp variable performace vs Inline behavior
by frozenwithjoy (Priest) on Jun 27, 2012 at 15:12 UTC | |
| [reply] [d/l] [select] |
|
Re: Temp variable performace vs Inline behavior
by bulk88 (Priest) on Jun 28, 2012 at 01:30 UTC | |
small and smallx win My Devel::Size is not the stock CPAN Devel::Size, so my numbers are much lower than the CPAN version but relative to each other they should be fine. Getting rid of the nextstate op for the block of the foreach loop interestingly did not decrease the size the ::Size reported, IDK why. I know that the nextstate ops do execute if I step through runops in C. | [reply] [d/l] [select] |
|
Re: Temp variable performace vs Inline behavior
by locked_user sundialsvc4 (Abbot) on Jun 27, 2012 at 22:31 UTC | |
Apart from the performance/capacity “edge cases” that I openly acknowledge BrowserUK (in particular) deals with every day, my bright-line rule always tilts in favor of: clarity, and maintainability. In the world that I live in every day, it is “six o’one, half a dozen of the other” in terms of performance ... because raw speed in my world is rarely actually the issue. (And to the extent that it may be, I look for a deeper algorithm change.) Certainly, to me, the first example is clear, and the second example would instantly fail my code-review: in the second case, the code does not plainly say that parse_node() will be called once vs. twice. I emphatically do not want to have to “understand Perl” in order to understand what a line of source-code says. I want it to very plainly and unambiguously say precisely what it means. (And if the compiler’s optimizer can improve upon it, goody for the optimizer and thank you for the freebie.) Spoken from the point-of-view of a businessman who did lose $10,000.00(USD) in actual cash, that he most-emphatically could not afford to lose but also could not rightfully keep, due to code written by someone else that was not clear. The cause of project-death was “cleverness.” I could not find the bug because I could not identify it. I had to borrow money fast. | |
by BrowserUk (Patriarch) on Jun 27, 2012 at 23:14 UTC | |
I emphatically do not want to have to “understand Perl” Hoisted by your own petard! And it probably explains: I could not find the bug because I could not identify it. Would you trust or employ a lowyer who spoke English, but wasn't familiar with legal terminology? For example: One who didn't know the difference between "chattels" and "property"? Why should anyone employ a programmer for a Perl project, that knew COBOL, but didn't: ' “understand Perl” '? With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |