仅通过加载模块的某些部分来节省资源?



我正在阅读O'Reilly的Perl Objects, References&Modules,更具体地说是关于模块的部分。它指出,使用use Some::Module时,您可以指定导入列表。从它的解释来看,使用此列表的唯一好处似乎是为了保持命名空间干净。换句话说,如果您的main包中有一个子例程some_sub,并且加载的模块具有同名的子,则您的子例程将被覆盖。但是,如果指定导入列表并从此列表中省略some_sub,则不会发生此冲突。然后,您仍然可以从模块运行some_sub,方法是像这样声明它:Some::Module::some_sub.

除了我上面描述的好处之外,还有其他好处吗?我之所以问这个问题,是因为在某些情况下,即使您只对它的某些方法感兴趣,您也会加载具有大量功能的模块。起初,我认为通过指定导入列表,您只加载这些方法,而不会使用您无论如何都不会使用的方法来膨胀内存。但是,从上面的解释来看,情况似乎并非如此。您是否可以通过仅加载模块的某些部分来有选择地节省资源?或者 Perl 是否足够聪明,可以在编译时做到这一点,而不需要程序员的干预?

从使用中看到use Module LIST;的意思正是

BEGIN { require Module; Module->import( LIST ); }

另一方面,从要求

否则,如果尚未包含库文件,require会要求包含该文件。该文件通过do-FILE机制包含在内,[...]

do 'file''file'作为 Perl 脚本执行。因此,通过use我们加载整个模块。

"导入"sub 意味着它的名称被包的import函数添加到(或覆盖)调用方的符号表中(通过 typeglob 的CODE槽,通常为别名)。子的代码不会被复制。现在,import可以按照作者想要的任何方式编写,但通常use语句中的导入列表仅控制将哪些符号带入命名空间。在模块中提供import的首选方法是使用导出器的import方法。

选择性导入减轻了符号表(也许还有一些相关机制)的负担,但我不知道这样做的实际好处。好处与编程有关,通过减少碰撞的机会。

另一个明显的好处是,它很好地记录了代码中使用的内容。

请注意,"导入列表"只是一个约定。模块的import功能可以自由地做任何它喜欢的这个列表,你可以看到它(ab)被许多所谓的编译指示模块使用。因此,部分加载不受任何约束use。例如,模块可以在您导入或不导入它们的任何地方加载繁重的函数存根,并在实际的第一次调用时动态加载繁重的实现。

因此,带有部分导入列表的use可能会或可能不会实际节省任何资源 - 这完全取决于used模块的实际实现。

虽然requireuse确实加载了整个.pm文件,但该文件可能只是一个轻量级的存根和加载器,用于位于其他地方的实际代码。还有另一种约定将这些模块称为::Heavy

模块也可以以任何他们喜欢的方式自由实现部分加载。以下是模块如何节省资源的一些可能性:

自动加载
  1. (带有免费的自动加载器,自动拆分和自动加载器模块)。
  2. 使用加载必要子模块的存根。
  3. 首次按名称访问大量数据(即字典或编码映射)时动态加载这些数据。
  4. 如果您依赖于其他繁重的模块,请在运行时在依赖于它们的函数中动态require它们,而不是在开始时use编译时。

此列表中的所有内容都可以在后台自动工作,通过导入列表公开use或者以其他完全任意的方式工作/调用。再一次,这完全取决于模块的实现。

最新更新