调用子程序的最快方法

Kri*_*rma 2 perl module subroutine

据我所知,在Perl中,我们可以使用以下技术从Module调用子例程:

  • 导出子程序foo,导入具有该子程序的模块.最后在你的perl脚本中调用它.
  • Object在perl脚本中创建一个该模块,最后foo使用它调用Object.
  • 直接foo使用它的路径调用,就像这样myDir::Module::foo();.

如果我总是困惑哪个是调用子程序的更好方法foo.如果我有一个动态脚本,我从浏览器而不是命令行运行,那么应采用哪种方法,以便脚本花费更少的时间.

谢谢.

amo*_*mon 6

在Perl中调用代码的最快和最好的方法之间存在差异.


编辑:请参阅simbabques答案.他特别介绍了#1和#3之间的差异,以及为什么要使用它们.


#1,#3:函数调用

您的#1和#3是相同的:子例程在全局可见的命名空间中具有唯一的名称.许多名称可能通过别名映射到一个子例程,或导入模块.

如果在编译时已知要调用的函数的名称,则将在编译时解析该子函数.这假设您不会自发地重新定义您的功能.如果确切的函数仅在运行时已知,则这只是哈希查找.

如何调用函数有三种方法:

foo(@args);
&foo(@args);
@_ = @args; goto &foo;
Run Code Online (Sandbox Code Playgroud)

第一个(大括号有时是可选的)是默认的,并且针对子原型验证你的参数(不使用原型).此外,构造了整个调用堆栈帧(具有许多有用的调试信息).这需要时间.

第二个跳过原型验证,并假设您知道自己在做什么.这稍快一点.我认为这是草率的风格.

第三个是尾部通话.这将从当前sub返回,返回值为foo.这很快,因为原型被忽略,并且可以重用当前的调用堆栈帧.这经常没用,而且语法很难看.内联代码大约快一个数量级(即在Perl中,我们更喜欢循环而不是递归☹).

#2:方法调用

OO的灵活性具有很高的性价:由于您调用消息的对象类型在运行时才会知道,实际方法只能在运行时解析.

这意味着$foo->bar()查找已编辑bar的包中的函数.如果在那里找不到它,它将在父类中搜索.这很慢.如果要使用OO,请注意浅层次结构(→减少查找次数).还要注意Perls默认的Method Resolution Order是不寻常的.$foobless

即使您知道类型,也通常无法减少对函数调用的方法调用.

如果$foo是class Foo,并且Foo::bar是sub,那么Foo::bar($foo)将跳过方法resultution,甚至可能工作.然而,这打破了封装,并且一旦Foo被子类化就会中断.此外,如果Foo未定义bar,则此方法无效,但该方法是在父类中定义的.

我通常赞成面向对象,直到从基准测试中可以清楚地看出这不会提供您所需的性能.

  • 惭愧我们无法合并我们的答案,我认为两者都很好地涵盖了它.;-) (3认同)