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

Save resources by only loading parts of a module?

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

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

use 我们看到 use Module LIST; 正好意味着

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

另一方面,来自 require

Otherwise, require demands that a library file be included if it hasn't already been included. The file is included via the do-FILE mechanism, [...]

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

"Importing" sub 意味着它的名称被添加(或覆盖)在调用者的 symbol table (via the CODE slot for the typeglob, normally aliased), by the package's import function. The sub's code isn't copied. Now, import can be written any way the author wants to, but generally the import list in the use statement merely controls what symbols are brought into the namespace. The preferred way to provide import in a module is to use the Exporterimport 方法中。

选择性导入解除符号 table(可能还有一些相关机制),但我不知道这样做的实际好处。好处与编程有关,通过减少碰撞的机会。

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

请注意,"import list" 只是一个约定。模块的 import 函数可以自由地对这个列表做任何它喜欢做的事情,你可以看到它被许多所谓的 pragma 模块使用(ab)。因此,部分加载不以任何方式绑定到 use。例如,无论您是否导入,模块都可以加载繁重的函数存根,并在实际第一次调用时动态加载繁重的实现。

因此 use 使用部分导入列表可能会或可能不会真正节省任何资源 - 这完全取决于 used 模块的实际实施。

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

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

  1. AUTOLOAD(带有免费的 AutoLoader、AutoSplit 和 SelfLoader 模块)。
  2. 使用加载必要子模块的存根。
  3. 当首次通过名称访问大量数据(即字典或编码映射)时动态加载它们。
  4. 如果您依赖于其他重型模块,请在运行时动态 require 它们依赖于它们的函数,而不是在一开始就在编译时 use

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