Re: Can perl modules be compiled?
by Joost (Canon) on Feb 26, 2007 at 11:26 UTC
|
| [reply] |
|
|
Hello! I wonder what's the best practice to deal with this limitation described in the AutoLoader documentation:
Package lexicals declared with my in the main block of a package using AutoLoader will not be visible to auto-loaded subroutines, due to the fact that the given scope ends at the __END__ marker. A module using such variables as package globals will not work properly under the AutoLoader.
The vars pragma (see "vars" in perlmod) may be used in such situations as an alternative to explicitly qualifying all globals with the package namespace. Variables pre-declared with this pragma will be visible to any autoloaded routines (but will not be invisible outside the package, unfortunately).
The vars pragma sounds risky, but I thought that using "my" in the main block as globals for subroutines was standard practice. Am I wrong (perhaps there should be no such "globals" for subroutines, and everything needed to produce the subroutine's result should come in as a parameter; or use "our")?
| [reply] |
Re: Can perl modules be compiled?
by lima1 (Curate) on Feb 26, 2007 at 11:40 UTC
|
Do you know why it takes 10 seconds just to compile the script?
I guess you do something in the constructors that you should do elsewhere.
Try profiling before rewriting. Devel::DProf | [reply] |
|
|
I've done profiling, as you suggested, and I found out what I already knew. 90% of the time is taken by loading my monstruous module. I will give Autoloader a chance (only a small fraction of the module is used at one time).
| [reply] |
Re: Can perl modules be compiled?
by mad_ady (Acolyte) on Feb 26, 2007 at 12:54 UTC
|
Well, many thanks, Joost! I have made the necessary modifications to my modules to use AutoLoader and presto! Now, my script loads in about 2 seconds, instead of 10!
Amazing!!!
However, when I compile my module, I get a bunch of warnings (I believe):
AutoSplitting blib/lib/RTC/Telnet.pm (blib/lib/auto/RTC/Telnet)
blib/lib/RTC/Telnet.pm: some names are not unique when truncated to 8 characters:
directory blib/lib/auto/RTC/Telnet:
getHostnameCisco.al, getHostnameTelco.al, getHostnameEricsson.al truncate to getHostn
getInterfaces.al, getInterfacesCisco.al, getInterfacesTelco.al, getInterfacesEricsson.al truncate to getInter
loginToCisco.al, loginToCiscoCPE.al, loginToCiscoCPEthruHQ.al truncate to loginToC
logoutOfCisco.al, logoutOfTelco.al, logoutOfEricsson.al, logoutOfCiscoCPE.al, logoutOfCiscoCPEthruHQ.al truncate to logoutOf
runCommands.al, runCommandsCisco.al, runCommandsTelco.al, runCommandsEricsson.al, runCommandsCiscoCPE.al truncate to runComma
My script seems to be running just fine, anyway... Is there a problem with these messages?
| [reply] |
|
|
| [reply] |
|
|
I think you should use or complement your current approach with a different strategy. Your sub names strongly suggest that your code should be split into multiple modules, probably OO ones. So you would have Mymod.pm as a base class with MyMod::Cisco, MyMod::Cisco::CPEthruHQ, MyMod::Cisco::CPE, MyMod::Telco, MyMod::Ericson as subclasses. Then you would simply have a base set of routines: getHostname(), getInterfaces(), login(), logout(), runCommands(), which would be overriden as necessary in the subclasses. This would reduce the initial load time since you would only load the baseclass and then let it load on the fly the appropriate subclass. And it would still be possible to use Autoloader, but with no possibilitiy of file name clashes, and most likely be much easier to work with.
You have to think that whenever you have subs named like you do that you probably are doing the subroutine equivelent of numbered variables like $x1,$x2,$x3, which is almost always a product of bad design. The same thing applied to subroutines, except that the solution is to use OO and not a hash or an array. (Although you could use a hash based dispatch table, but why bother, using subclasses is easier and is specifically designed for this type of scenario.)
---
$world=~s/war/peace/g
| [reply] |
|
|
Yes, you are right about splitting the module into smaller individual parts; it's just that when I started writing it, I didn't think it would grow to this size ... and now it's a bit of a challenge to untangle it. :) Actually this would have been my strategy if AutoLoader wouldn't have worked.
As for the OO aproach... well, I haven't studied yet how to write OO in perl, so I wouldn't venture here. I agree that I could have written the whole thing to be more efficient, but I don't really have the time to optimize it - it has to run first :)
| [reply] |
Re: Can perl modules be compiled?
by mad_ady (Acolyte) on Feb 26, 2007 at 14:28 UTC
|
Thank you all for your help! :) | [reply] |
Re: Can perl modules be compiled?
by PreferredUserName (Pilgrim) on Feb 26, 2007 at 16:47 UTC
|
I'm curious just *how big* is your module? I've never experienced anything close to a 10s startup time on a reasonable machine.
Also, if 2s is still too slow for you, you could take the modperl route of keeping a long-running server going to service requests, so there's only a one-time startup penalty. | [reply] |
|
|
My main module is about 50k in size and uses Net::Telnet::Cisco, Error.pm, Log4Perl, DBI and a lot of regular expressions.
When I tried to compile my script that uses this module, I tried to generate a standalone perl script, and this script was 2M in size! :)
I guess that would account for the slow startup time.
I'm not sure about modperl, because my script doesn't run from inside a web browser, but my script is called frequently (about once every 5-10 seconds), so I'd appreciate it if I could compile it once and run it many times without recompilation. Can it be done from outside the browser?
| [reply] |
|
|
mod_perl does what you want by loading your code into an anonymous coderef and calling it when needed. You could do the same by simply turning the script into an infinite loop with a sleep or possibly some kind of polling, if external input is required
| [reply] |