【问题标题】:How to dynamically avoid 'use module' to reduce memory footprint如何动态避免“使用模块”以减少内存占用
【发布时间】:2015-09-19 00:10:31
【问题描述】:

给定以下模块:

package My::Object;

use strict;
use warnings;

use My::Module::A;
use My::Module::B;
use My::Module::C;
use My::Module::D;

...
1;

我希望能够在接下来的 2 个场景中调用 My::Object:

  1. 正常使用

    使用我的::对象;

    My::Module->new();

  2. 减少内存使用。调用相同的对象,但使用条件或标志告诉对象跳过使用模块以减少内存使用。不知何故:

    使用 My::Object -noUse;

    My::Module->new();

如果尝试Perl if condition 没有成功。

我遇到的问题是使用很多用途的大对象,然后仅加载此对象会消耗大量 RAM。我知道我可以重构它们,但是如果我可以在确定在给定场景中没有使用它们的情况下以某种方式避免这些用途,那就太好了。

一种解决方案是当需要模块时,在所有地方都用 requires 替换 all uses,但是当其中一些在很多方法中使用时,我认为不方便。

有什么想法吗?

谢谢

【问题讨论】:

  • 你能展示你从 2 开始的尝试吗?
  • @HunterMcMillen 这有点像 Sobrique 在他的回答中所建议的。但我无法让它工作。

标签: perl memory-management


【解决方案1】:

本机编译指示 autouse 将在调用普通 子例程 时加载所需的模块:

use autouse 'My::Module::A' => qw(a_sub);
# ... later ...
a_sub "this will dynamically load My::Module::A";

对于正确的 OO 方法,Class::Autouse 将在调用 方法 时加载模块(类):

use Class::Autouse;
Class::Autouse->autouse( 'My::Module::A' );
# ... later ...
print My::Module::A->a_method('this will dynamically load My::Module::A');

【讨论】:

    【解决方案2】:

    我认为您正在寻找的可能是 require - 稍后会评估 require 以便您可以在条件中成功使用它:

    if ( $somecondition ) {
        require Some::Module;
    }
    

    当然,如果您没有加载它,您将无法执行Some::Module->new() - 没有办法。

    use 在编译时触发(因此如果模块不可用,将在perl -c 下触发警告)require 发生在运行时。您可能应该测试 require 是否因此成功。

    例如:

    if ( $somecondition ) {
        eval { require Some::Module };
        warn "Module Not loaded: ".$@ if $@;
    }
    

    否则您可能正在寻找:

    Is it possible to pass parameters to a Perl module loading?

    #!/usr/bin/perl
    
    package MyObject;
    
    sub import {
        my ( $package, $msg ) = @_;
        if ( defined $msg and $msg eq "NO_USE" ) {
            #don't load module
        }
        else {
            require XML::Twig;
        }
    }
    
    1;
    

    然后调用:

    use if $somecondition, MyObject => ( 'NO_USE'  );
    

    或者更简单:

    use MyObject qw( NO_USE );
    

    编辑:

    在对“使用”进行了一番摆弄之后——有几个问题,use if 似乎不喜欢词法变量。因此,您需要执行以下操作:

    #!/usr/bin/perl
    
    package MyObject;
    use strict;
    use warnings;
    
    our $import_stuff = 1;
    
    sub import {
        my ( $package, $msg ) = @_;
        if ( $msg and $msg eq "NO_USE" ) {
            $import_stuff = 0;
        }
        use if $import_stuff, 'Text::CSV';
    }
    
    1;
    

    然后调用:

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    use MyObject qw( NO_USE );
    use Data::Dumper;
    
    print Dumper \%INC;
    my $test = Text::CSV -> new();
    

    (如果您设置了NO_USE,则会出现错误,否则不会)。

    认为这是 use 仍然是编译时指令的工件,因此需要(包范围)条件。

    【讨论】:

    • 嗯,这可能更多的是关于对正在加载的模块应用条件。
    • "use if 似乎不喜欢词法变量" 这不是真的。棘手的部分是在编译时use if 之前声明和定义一个词法变量。像my $wanted; BEGIN { $wanted = 1 } use if $wanted, 'My::Module' 这样的东西可以正常工作
    • 但是任何传递给 import 的东西在编译时都不会可用,所以 use if 根本不会在这里工作
    • @ysth 啊,好点,我错过了问题中关于想要通过导入来做到这一点的部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    相关资源
    最近更新 更多