Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I just started learning perl, I came to know that, constant are treated as subroutines in perl. I wonder then why the use of constants can be a good practice if everytime, it is making subroutine call and CPU needs to use stack/jump instruction?
That is a reasonable concern but there is in fact no function call overhead.
Let's first have a look at constant pragma docs
When a constant is used in an expression, Perl replaces it with its value at compile time, and may then optimize the expression further. In particular, any code in an if (CONSTANT) block will be optimized away if the constant is false.
So you are not paying for a function call at runtime.
Further, under Technical Notes it says
In the current implementation, scalar constants are actually inlinable subroutines. As of version 5.004 of Perl, the appropriate scalar constant is inserted directly in place of some subroutine calls, thereby saving the overhead of a subroutine call. See
Constant Functions in perlsub for details about how and when this happens.
We should take note of the "current implementation" phrase, but I think it's safe to expect this not to change in a way that would impose a runtime penalty.
Please read the rest of this section, and make sure to see the Caveats.
The mentioned Constant Functions in perlsub describes
Functions with a prototype of () are potential candidates for inlining. If the result after optimization and constant folding is either a constant or a lexically-scoped scalar which has no other references, then it will be used in place of function calls made without &. Calls made using & are never inlined. (See constant.pm for an easy way to declare most constants.)
This confirms that one is generally fine efficiency wise.
On the other hand, note that the use of constant pragma can raise questions of whether the use of barewords is of concern in your code (which it may or may not be).
The "good practice" regards the programming benefits of using constant (read-only) declarations for variables that should not be changing. Such practice generally improves the code substantially.
Related
This question already has answers here:
How can I inline Perl subroutines?
(4 answers)
Closed 7 years ago.
I know non-constant subroutines usually will not be inlined, since they can be redefined on the fly. However, I have code where inlined subroutines would actually offer a small but non-trivial optimization; but I don't want to unroll them myself since it would make the code much harder to read.
Is there some way to make Perl inline these methods, a way to indicate that the subroutine will not be modified at runtime and I want the interpreter to inline during the preprocessing phase?
Constants can be folded, but Perl subs are never inlined. Practically, they can't be. macro and Macro attempt to provide inlinable subs, but I don't know how reliable they are. You will definitely find limitations.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
So having watched 3 hours of youtube videos, and spent equally long reading about Lisp, I've yet to see these "magic macros" that allow one to write DSLs, or even do simple things like 4 + 5 without nesting this inside some braces.
There is some discussion here: Common lisp: is there a less painful way to input math expressions? but the syntax doesn't look any nicer, and still requires some enclosing fluff to define where the macro starts and ends.
So here is the challenge, define an infix macro, then use it without having to enclose it with some kind of additional syntax. I.e.
Some macro definition here
1 + 2
NOT
Some macro definition here
(my-macro 1 + 2)
NOT
Some macro definition here
ugly-syntax 1 + 2 end-ugly-syntax
If this is not possible in Lisp, then what is all the fuss about? It's kinda like saying "you have awesome powerful macros that allow for cool DSLs, provided those DSLs are wrapped in Lisp like syntax".
Of course you can implement what you're talking about in Lisp.
One big difference between Lisp and other languages is that nothing is fixed and you've control on what the reader does on every single character of the input source code. Literally.
Consider for example the project CL-Python and its mixed-syntax Lisp/Python mode.
Basically in that mode if what you type starts with an open parenthesis then it's considered Lisp, otherwise it's considered Python (including multi-line constructs).
...HOWEVER...
this kind of macro/reader-macro library is implemented rarely, because one of the main advantages of the s-expression approach is that it's well composable and you can build other macros on top of existing macros, raising the level of the language.
Once abandoned the regularity of s-expression approach, writing macros becomes annoying because to write code that manipulates code you need to consider the several different constructs of the language, precedence rules, special rules, special syntax forms.
Languages that are not based on s-expression sometimes provide real macro processing capability but working on the AST level, i.e. after some parsing processing has already been done in a fixed way. Moreover the macro code in these languages looks really weird because the code the macro is manipulating, inspecting or building doesn't look like real code.
Sometimes in other languages instead you only find text-based macros that are basically search-replace. To see an example of how ugly things can get consider the Python standard library implementation of collections.namedtuple (around line 284) and its set of absurd limitations induced just because of that implementation.
Another example of how things can get horribly complex once you force yourself to a template-only approach to avoid the complexity of manipulating an irregular and special cased language is C++ template metaprogramming.
A simple s-expression based language and quasi-quotation instead makes macro code much easier to write and read and understand, and that's why Lisp code doesn't move away from it. Not because it cannot, but because it doesn't make sense to go to a worse syntax for no reason.
In Lisp you "bend" the language a little by adding the abstractions that are really needed without however breaking everything else and, most important, without dropping the ability to do more bending in the future if needed. Writing a macro/reader-macro that makes the expression parsing the nightmare of say C++ and at the same time removes the ability to write further macros and add more constructs (or makes it impossibly hard) would be a nonsensical suicide.
Even a macro like (infix x + y * z) is just an exercise... I doubt that any lisper would use that to write real code... why on earth would someone reintroduce the absurd function/operator duality and the nightmare of precedence/associativity rules? If you don't like Lisp then just don't use Lisp.
For a lisper it's not the (infix and ) part that is ugly... it's what is in the middle.
Also why do you think that 2+3*6 is "naturally" 20? Because the teacher hit you on the palms of your hands with a stick when you were a kid until you got it right?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
At my work I wrote a little parser for C-like expressions in one of our in-house Perl tools. I initially chose Parse::RecDescent because of its extreme ease of use and straightforward grammar syntax, but I'm finding that it's excessively slow (which is corroborated by general opinion found on the web). It's safe to assume that the grammar of the expressions is no more complicated than that of C.
What are the fastest (but still with a straightforward and uncumbersome grammar format) lexxer/parser modules for the use case of thousands of simple expressions (I'd guestimate the median length is 1 token, mean is 2 or so, and max is 30)? Additionally, thanks to unsavory IT choices, it must work in Perl 5.8.8 and it and any non-core dependencies must be pure Perl.
Parse::Eyapp looks like satysfying 5.8.8, pure perl and dependency requirements. As for speed, it claims LALR parsers, which must be faster than recursive descent. A grammar for expressions is given in the doc. Hope it helps.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
As per perldoc perlsub:
The & is optional in modern Perl, as are parentheses if the subroutine has been predeclared.
I notice that a lot of times, people use the fact that you can omit parenthesis when calling Perl subroutines (e.g., randomly quoting from a recent SO answer):
open my $fin, '<', $file;
is as equally valid as
open(my $fin, '<', $file);
What are the main (ideally, technical) reasons to use the second (parenthesis-less) version?
perldoc perlsyn doesn't say anything on the topic other than again mention optionality.
For me, always using the parenthesis are mostly a stylistic choice due to my origins as a C developer; but I'd like to know if I'm missing something out on not using the optional parenthesis-less syntax as a Perl developer.
P.S. I know full well the reasons to prefer the version with parenthesis - e.g. the issues with indirect object notation, or requirement to declare non-builtins before they are used without parenthesis, or issues with precedence visavi or vs ||. I'm interested in the opposite.
P.P.S. I'm not greatly interested in answers merely stating "it's better style"/"more readable" without any studies backing the opinion up. I'm interested in either technical reasons to prefer parenthesis omission, or backed up stylistic difference preferences (Please don't confuse "backed up" with "appeal to authority" or "argumentum ad populum" fallacies. A study showing improvement in speed or comprehension of code is proof. "Everyone in Perl commmunity agrees" or "Damien Conway suggests this" without explaining how Damien backs this up is not).
I think the only time that it actually matters, other than style, is for the rarely used &subname which according to perldoc perlsub:
&NAME; # Makes current #_ visible to called subroutine.
Of course, using parens might make for easier disambiguation in some cases (both for the parser and the future reader), or else not using them might remove noise in others; the degree to which either of those is necessary is probably the primary reason I would ever choose one or the other.
From Perl::Critic::Policy::CodeLayout::ProhibitParensWithBuiltins:
Conway suggests that all built-in functions be called without
parentheses around the argument list. This reduces visual clutter and
disambiguates built-in functions from user functions.
Conway is the author of the Perl Best Practices book.
There are no technical reasons to omit parentheses. It's purely a matter of preferred coding style.
This is purely a style question. To a Perl programmer, print "Hi!\n"; is more readable than print("Hi!\n");. It is good style to make code as readable as possible, and -- all else being equal -- additional symbols make reading harder. Since built-ins don't need the parens, it makes sense to ask whether the disambiguation they provide justifies the additional cognitive load. And Perl programmers as a class have come down on the side of "no", aided in part by Damien Conway's formalization of the rule.
Conway also suggests that keeping built-ins paren-free helps distinguish them from user-defined functions, but I consider that argument less persuasive. It is more correct to say that many built-ins are designed to read naturally without parens, and so should be used that way. Seeing defined($x) or len($y) makes Perl programmers twitch, but no more than seeing croak($z).
Note that writing Perl as though it were C is emphatically bad style. Write Perl as though it were Perl.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 12 years ago.
I was wondering if you had any basic tips to improve the performance of a Perl script performance (like memoizing determinist functions)?
Install Devel::NYTProf
run your script with it: perl -d:NYTProf some_perl.pl
convert the output file into a nice report: nytprofhtml -f nytprof
open the report in a web browser: firefox nytprof/index.html
look for whatever is taking the most time
determine if that is the right algorithm for the job (e.g. are you using an O(n2) algorithm where a O(n) algorithm would also work?)
extract the slow code to a separate script that can be run by itself
write a second (or more) version of the slow code
use Benchmark to compare them (remember to use data that you expect to see in the wild, some algorithms do great for small numbers of items, but are terrible when the number of items increase)
when you have proven that you have faster code, modify the original and go back to step 2 until your code is fast enough or you can't improve it any more
if it is still too slow, ask how to do X faster here (be as detailed about X as you can be)
You should profile first. Rules are made to be broken.
Some very basic tips:
Avoid slurping. There are occasions where slurping more than a line is justified, but slurping whole files everywhere is going to exact a price.
Avoid passing large lists to subroutines.
If you have multi-level hashes or arrays, avoid repeatedly dereferencing multiple levels. Store a reference to the deepest applicable level in a lexical variable and use that.
Declare your variables in the smallest scope possible. I am not sure if this is an optimization in and of itself, but frequently will allow you to see more clearly, and that is key to improving performance.
The basic tips for improving the performance of Perl scripts consists of general approaches that apply everywhere, and some very Perl-specific things.
Things like:
measure, don't guess, and target expensive areas only. Your ROI will be much higher.
cache unchanging expensive results if you're going to use them a bit.
don't do something manually when there's a function that will do it for you. This is the difference between interpreted and compiled speed.
use CPAN, there's a module for everything, usually written by people who know Perl better than us mere mortals.
This is not something that's easy to distil into a short pithy answer.
I will give one piece of advice. The best way to improve the performance of your code is to post specific bits of it here on SO and wait for the likes of brian d foy to find it :-)
I recently found out that profiling is very useful, and that Devel::NYTProf is very good at it.. Profiling stops you from unnecessary optimizing and helps you fix the biggest bottlenecks first.
Of course, having some knowledge of what not to do helps, but guess that's not very perl specific..
A list of common perl performance gotchas would be nice though :)
Update:
here is one: glob() sorts if you don't tell it otherwise :|
don't copy large amounts of data around, use references (e.g.: Use scalar references to pass large data without copying. )
Duplicate of: How can I speed up my Perl program?
Many good suggestions here already, here are a few more:
Avoid repeatedly packing and unpacking arrays, especially when they are large
pack and unpack are very fast, but split is sometimes faster
Inline small portions of code rather than breaking everything into subroutines (you can easily go too far with this, so profile to find the hot spots).
If you want an array of aliases, know your data is mutable, or promise not to change the values, using sub{\#_}->(retuns_a_list()) is around 40% faster than [returns_a_list()] (you don't have to inline the subroutine, I usually call it sub cap {\#_} (short for capture)
And if you really, really need to improve the speed of method calls on certain objects, you can use closure based objects. Here is an excerpt from my module List::Gen discussing the curse method of creating closure objects:
curse HASHREF PACKAGE
many of the functions in this package utilize closure objects to avoid the speed penalty of dereferencing fields in their object during each access. curse is similar to bless for these objects and while a blessing makes a reference into a member of an existing package, a curse conjures a new package to do the reference's bidding
package Closure::Object;
sub new {
my ($class, $name, $value) = #_;
curse {
get => sub {$value},
set => sub {$value = $_[1]},
name => sub {$name},
} => $class
}
Closure::Object is functionally equivalent to the following normal perl object, but with faster method calls since there are no hash lookups or other dereferences (around 40-50% faster for short getter/setter type methods)
package Normal::Object;
sub new {
my ($class, $name, $value) = #_;
bless {
name => $name,
value => $value,
} => $class
}
sub get {$_[0]{value}}
sub set {$_[0]{value} = $_[1]}
sub name {$_[0]{name}}
the trade off is in creation time / memory, since any good curse requires drawing at least a few pentagrams in the blood of an innocent package. the returned object is blessed into the conjured package, which inherits from the provided PACKAGE.
when fast just isn't fast enough, since most cursed methods don't need to be passed their object, the fastest way to call the method is:
my $obj = Closure::Object->new('tim', 3);
my $set = $obj->{set}; # fetch the closure
# or $obj->can('set')
$set->(undef, $_) for 1 .. 1_000_000; # call without first arg
which is around 70% faster than pre-caching a method from a normal object for short getter/setter methods.
This question reminds me of the advice of Tim Bunce, maintainer of Devel::NYTProf.
To summarize, don't do it unless you really have to.
My favorite quote from his presentation:
“The First Rule of Program
Optimization: Don't do it.
The Second Rule of Program Optimization (for experts only!): Don't do it yet.”
-Michael A. Jackson
[emphasis added]
Here are a few specific things that haven't been mentioned yet:
use tr/// instead of s/// wherever possible
use index() to match exact substrings instead of a regex
never ever use $^, $& and $-. These are the dreaded regex match variables that slow all regexes. There are alternatives that do not impose a penalty.
Revenge of the match vars, when using the English module, exclude match variable aliasing. That is, do use English '-no_match_vars'; instead of just use English;
More info can be found in perlop, perlfunc and perlvar.