📄 perlfaq3.html
字号:
若你的系统架构有支援的话,标准 perl 套件便应该有此功能(介由 DynaLoader这个模组)。详情请参看 <A HREF="../../tppmsgs/msgs0.htm#71" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlxstut.html#">perlxstut</A>。<P><P><HR><H2><A NAME="_O_undump_">什麽是 undump?</A></H2>看下个问题。<P><P><HR><H2><A NAME="_p_Perl_o_">如何让我的 Perl程式跑得更快些?</A></H2>最好是能设计一个较好的演算法 (algorithm),这通常会让程式有大不相同的表现。骆驼书第八章里有些你或许想知道的增进效率小技巧。<P>其它方法包括自动载入较少使用的 Perl 程式码。请参看标准 perl 套件中的 AutoSplit及 AutoLoader模组的用法。或当你能断定程式执行效率的瓶颈在何处时,用 C来写那个部份,就像用组合语言来撰写 C程式的瓶颈部份一样。与此法相近的是使用以 C撰写瓶 颈部份的模组 (例如 CPAN中的 PDL 模组)。<P>在某些情况下,使用後端的编译器把程式编译成位元码 (byte code)(可节省编译时间) 或是将 perl程式转编译为 C程式的作法值得一试;这些作法绝对会节省编译的时间并且有时能省一些[但不多]执行时间 。请参考“编译你的 Perl程式”这个问题的答案。<P>如果你目前是将你的 perl直译器动态连结到 libc.so的话,重新作一份静态连结到 libc.a的 perl直译器可以提高 10-25%的执行效能。虽然这会使你的 perl直译器变得更胖,但你的 Perl程式 (及程式设计者) 或许会因此而感谢你。详情请参考 perl标准套件原始码版本中的 <EM>INSTALL</EM> 档案。<P>一些未经证实的报告中宣称有些使用 sfio的 Perl直译器表现得比没有用 sfio的还好 (针对於 IO频繁的应用程式)。想试试看?参考 perl套件原始程式版中的 <EM>INSTALL</EM>档案,尤其是 ``Selecting File IO mechanisms''这一段。<P>使用 undump程式把编译後的档案格式存到硬碟里以加快执行的速度已经是老掉牙的手法了。它已不再是个可行的方法,因为这方法只有几种平台能用,况且它终究不是个治本之 道。<P><P><HR><H2><A NAME="_p_Perl_Y_I_O">如何让我的 Perl程式吃少一点的记忆体?</A></H2>当问题变成时间与空间的交易时, Perl 几乎总是用记忆体来帮忙解决问题。 Perl中的纯量 (Scalar) 耗掉的记忆体比 C中的字串形态还多,阵列又更多, 更别谈杂凑阵列了 (Hashes)。关於这一点,我们当然还有很多工作得作,近来发布的版本,已开始针对这些问题做改进了。例如, 5.004 版中, 重复的杂凑阵列索引值 (duplicate hash keys) 由使用它的杂凑阵列共用,这样就不用再重新定份位置给它了。<P>在某些情况下,使用 <CODE>substr()</CODE>或 <CODE>vec()</CODE>来模拟阵列有很大的好处。例如,一个有上千 个布林代数值的阵列将占用至少 20,000位元组的空间,但是它可以被转变为一个 125位元组的位元向量 (bit vector)以节省相当可观的记忆体。标准套件中的 Tie::SubstrHash模组也能够帮助特定形态的资料结构节省些记忆体。若你正在和一些特殊的资料结构奋战 (例如,矩阵),用 C写的模组所耗掉的记忆体可能低於同功能并用 Perl写的模组。<P>另一件值得一试的是,查一下你的 Perl是以系统内的 malloc 还是 Perl内含的 malloc编译起来的。不论是哪个,试着换成另一个,再看看这是否造成任何差别。关於malloc的资讯可在 perl标准套件原始码版中的 <EM>INSTALL</EM> 档案找到。键入 <CODE>perl-V:usemymalloc</CODE>就可以知道你是否在使用 perl的 malloc。<P><P><HR><H2><A NAME="_O_w_">把指标传回到区域资料是不安全的做法吗?</A></H2>不,Perl的资源回收 (garbage collection)系统会解决此问题。<P><PRE> sub makeone { my @a = ( 1 .. 10 ); return \@a; }</PRE><P><PRE> for $i ( 1 .. 10 ) { push @many, makeone(); }</PRE><P><PRE> print $many[4][5], "\n";</PRE><P><PRE> print "@many\n";</PRE><P><P><HR><H2><A NAME="_p_C_C_H_Y">我如何释放一个阵列或杂凑阵列以缩小我的程式尺寸?</A></H2>你无法这麽作。系统配置给程式的记忆体是覆水难收。这也是为何执行很长一段时间的程式有时会重新执行 (re-exec)它们自己的原因。<P>然而,在使用你的变数时,明智地用 <CODE>my()</CODE>来定义执行范围,可让 Perl在脱离该范围後 将它们所占的空间释放给其它部份的程式。 (注:my()的变数也比全域变数执行起来快 10%。)当然,一个全域变数永远没有超出范围的时候,所以你无法将它占用的空间自动重新分配,不过,把它 <CODE>undef()</CODE> 或/和 <CODE>delete()</CODE>会有相同的效果。总之,在 Perl里,你并不能/应该去担心太多有关记忆体定址与解除这件事,而我们连添加这项功能(资料形态的预先定址),目前都已在进行中。<P><P><HR><H2><A NAME="_p_CGI_script_">如何让我的 CGI脚本 (script)执行起来更有效率?</A></H2>除了使一般 Perl程式加快或缩小的平常手段外,一个 CGI 程式还有其他的顾虑。也许它每秒会被执行好几次。每次它执行时,重新编译所花的时间、加上定址所需的 1 MB以上的系统记忆体,就是一个大杀手。光是编译成 C <STRONG>是没啥帮助的</STRONG>,因为瓶颈在於整个程序开始时所负担的包袱 (start-up overhead) 。<P>最起码有两种较流行的方法可以避免这些包袱。一种解法是将 mod_perl 或是 mod_fastcgi其中一个模组加在你所执行的 Apache HTTP server (可从 <A HREF="../../tppmsgs/msgs0.htm#85" tppabs="http://www.apache.org/">http://www.apache.org/</A>取得)。有了 mod_perl 和 Apache::*模组 (从 CPAN取得),httpd执行时会带起一个内 嵌的 Perl直译器,而它会预先编译你的程式,并在不产生其它子程序的情况下用同一个定址空间来执行。Apache 扩充模组亦给 Perl一个连通 server API 的管道,所以用 Perl写的模组可以做到任何 C写的模组所具备的功能。而有了 FCGI模组 (自 CPAN取得),你以 sfio (参看 perl标准套件原始码版本中的 <EM>INSTALL</EM>档案) 和 mod_fastcgi (从 <A HREF="../../tppmsgs/msgs0.htm#86" tppabs="http://www.fastcgi.com/">http://www.fastcgi.com/</A>取得)模组编译成的 Perl 直译器将使你的每个 perl程式变成一个固定的 CGI 背景程序 (daemon process)。<P>这些方法对你的系统与你撰写 CGI程式的方法都有超乎想像之外的影响,所以请小心地 探索它们。<P><P><HR><H2><A NAME="_p_Perl_l_X_">如何隐藏 Perl程式的原始码?</A></H2>删除它。 :-)说真的,有一些具有不同“安全”等级的方法(大部分都不能令人满意)。<P>然而,首先,你 <EM>不能</EM>拿走读取权,不然你的程式怎麽被解译或是编译呢? (不过那也并不表示一个 CGI程式的原始码可以被使用者读取。)所以你得让档案权限停留在 0755这个友善的阶段。<P>有些人认为这是个安全上的漏洞。不过若你的程式作的是不安全的事情,光仰赖别人看不见这些漏洞、不知从何下手,那麽它依然是不安全的。其实对有些人来说他们并不需要看见程式原始码便可能判定并揭露这些不安全的部份。透过隐瞒达到的安全,就是不修正臭虫反而隐藏它们,实际上是没有安全性可言的。<P>你可以试着透过原始码过滤模组 (CPAN中的 Filter::*)来替原始码加密。但高手也许有办法将其解密还原。你也可以用下面提到的 byte code编译器与直译器,但高手也有可能反解译它。你可以试试後面提到的原生码编译器(native-code compiler),但高手也有可能反组译它。这些手段都需要不同难度的技巧才能让别人拿到你的原始码,但没有一种能够很确定地隐藏它。(这对每种语言来说都为真,不是只有 Perl)<P>如果你所担心的是别人自你的程式码中获利,那麽一纸权限执照是能提供你法律上安全的唯一途径。注册你的软体并且写份权限说明,再加上一些具威胁性的句子像“这是 XYZ公司未出版的专有软体。你能撷取它并不代表你具有使用的权限...”之类云云。当然,我们不是律师,所以若你想要你的执照中每一句话在法庭上都站得住脚,就去见个律师吧。<P><P><HR><H2><A NAME="_p_Perl_X_s_byt">如何把我的 Perl程式码编译成 byte code或 C?</A></H2>Malcolm Beattie已经写了一个多功能的後端编译器,可以从 CPAN取得,它就能做到这两项功能。1997 年二月是 alpha测试版的最後几个阶段,这代表着若你是个程式设计 员而非寻找万灵解药的人,那麽参与其测试就会充满趣味。<P><EM>请</EM>了解光是编译成 C其本身或在本质上并不能保证它就会跑得快更多。那是因为除了在运气好的状况中有一堆可以衍生成出来的原生形态外,平时的 Perl执行系统环境依然存在因此依然会花差不多长的执行时间与占用差不多大小的记忆空间。大多数程式能省下来的不过是编译时间,这使执行速度顶多快 10-30%。有些罕见的程式能真正从中受利(例如增快好几倍),但这还得配合原始码的微调。<P>Malcolm 将会主导 Perl 5.005版的发展并试着将其编译器与多执行绪部份的工作融合进主要的发行版本里。<P>你或许会惊讶地发现,现行版本的编译器做出来的执行档大小跟你的 Perl直译器一样大,有时更大些。那是因为依照现在的写法,所有的程式皆转成一个被 <CODE>eval()</CODE>的大叙述。只要建造一个动态连结的 libperl.so程式库,并将之连结起来,你就可以戏剧性地减少这 种浪费。参看 perl原始码套件中的 <EM>INSTALL</EM> pod档案以获得更详尽的讯息。如果你用这方法连结你主要的 perl执行档,就能使它变得很渺小。举例来说,在作者之一的系 统里, /usr/bin/perl只有 11k“小”而已!<P><P><HR><H2><A NAME="_p_perl_b_MS_DOS_N">如何才能让 '#!perl'在 [MS-DOS,NT,...]下作用?</A></H2>OS/2下只要用:<P><PRE> extproc perl -S -your_switches</PRE><P>当作 <CODE>*.cmd</CODE>档案的第一行 (<CODE>-S</CODE> 是因 cmd.exe中其 `extproc'处理的臭虫才要的)。DOS使用者应先制作一个相对的 batch 档案然後将它以 <CODE>ALTERNATIVE_SHEBANG</CODE>的方式写成程式。(更多讯息在原始码版本的 <EM>INSTALL</EM>档案里)<P>若安装 Activeware版的 Win95/NT 专用 Perl,它会更动 Registry的内容,把 .pl 的扩充档名与 perl直译器结合。如果你安装另一版本或是用 WinGCC建构你自己的 Win95/NT用 Perl,那你就得自己更动 Registry的内容了。<P>麦金塔的 perl程式将会有适当的创造者与形态 (Creator and Type),所以双击它们就会执行这些 perl 应用程式。<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -