忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT HPC论坛 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
查看: 742 | 回复: 5

请教Perl内存激增问题? [复制链接]

求职 : 网络信息安全
论坛徽章:
0
发表于 2017-03-28 12:45 |显示全部楼层
使用 Parallel::ForkManager 指定最大500个进程。从一个目录读ID文件处理,ID文件约有300个,符合条件新开进程的ID约100个,另200个在主程序处理。(Perl线程不太可靠)
程序会调用
[size=-1]system("/home/root/Perl/zhubo/ZhuBo.pl $f";去掉这句换成sleep 11111;也存在下面问题(这个被调用的程序也存在内存激增问题,应该是一样的问题)
undef是没什么鸟用的~
现在的主要问题是:
运行后程序主进程内存从20M开始慢慢增加到直到好几G
另,主进程每开一个子进程,子进程的内存占有量等于当时主进程的内存占有量,比如:
主进程现在开了10个子进程,主进程内存占有500M。在开11个子进程时,第11子进程的内存初始就为500M,开第12个子进程时,主进程内存比如为600M,第12个子进程初始内存也为600M,太奇怪了!
环境为:CentOS7, Perl 5.20.3
本想用下Devel:eek,但装不上,好像得5.24
请诸位大神指导!谢谢!
  1. #!/usr/bin/perl -w
  2. use strict;
  3. # fork.pl
  4. $SIG{INT}=\&INT_EXIT;
  5. use IO::Socket::SSL;
  6. use Mojo::Asset;
  7. use Mojo::Asset::File;
  8. use Mojo::Asset::Memory;
  9. use Mojo::Base;
  10. use Mojo::Content;
  11. use Mojo::Content::MultiPart;
  12. use Mojo::Content::Single;
  13. use Mojo::Cookie;
  14. use Mojo::Cookie::Request;
  15. use Mojo::EventEmitter;
  16. use Mojo::Exception;
  17. use Mojo::IOLoop;
  18. use Mojo::IOLoop::Client;
  19. use Mojo::IOLoop::Delay;
  20. use Mojo::IOLoop::Server;
  21. use Mojo::IOLoop::Stream;
  22. use Mojo::JSON;
  23. use Mojo::Loader;
  24. use Mojo::Message;
  25. use Mojo::Parameters;
  26. use Mojo::Path;
  27. use Mojo::Reactor;
  28. use Mojo::Reactor::Poll;
  29. use Mojo::Server;
  30. use Mojo::Server::Daemon;
  31. use Mojo::Transaction;
  32. use Mojo::Transaction::HTTP;
  33. use Mojo::Transaction::WebSocket;
  34. use Mojo::URL;
  35. use Mojo::UserAgent;
  36. use Mojo::UserAgent::CookieJar;
  37. use Mojo::UserAgent::Proxy;
  38. use Mojo::UserAgent::Server;
  39. use Mojo::UserAgent::Transactor;
  40. use Mojo::Util;
  41. use Mojo::WebSocket;
  42. use File::Find;
  43. use Parallel::ForkManager;
  44. $|=1;
  45. my %ID;
  46. my $dir='/home/root/Perl/zhubo/AccountID';
  47. my $json_conf;
  48. my $fork;
  49. my %Header;
  50. my $ua;
  51. &Config;
  52. &Header;
  53. &Mojo_UA;
  54. my $pm=new Parallel::ForkManager($fork);
  55. sub Config{
  56.     open(F,"conf.json") or die;
  57.     my @conf=<F>;
  58.   close F;
  59.   chomp @conf;
  60.   my $json=join('',@conf);
  61.   $json_conf=Mojo::JSON::decode_json($json);
  62.   $fork=$json_conf->{'fork'};
  63. }
  64. sub Header{
  65.   my @header=<headers/*>;
  66.   foreach my $H(@header){
  67.     next unless($H=~m/\.header$/);
  68.     my $hn;
  69.     $hn=$1 if($H=~m/.*\/(.*?)\.header$/);
  70.     open(H,$H) or die;
  71.     while(my $h=<H>){
  72.         chomp $h;
  73.         my @H=split('=>',$h);
  74.         $Header{$hn}{'header'}{$H[0]}=$H[1];
  75.     }
  76.     close H;
  77.     }
  78. }
  79. sub Mojo_UA{
  80.   $ua=Mojo::UserAgent->new;
  81.     $ua=$ua->connect_timeout($json_conf->{'connect_timeout'});
  82.   $ua=$ua->inactivity_timeout($json_conf->{'inactivity_timeout'});
  83.   $ua=$ua->max_redirects($json_conf->{'max_redirects'});
  84. }
  85. while(1){
  86.   File::Find::find(\&wanted,$dir);
  87. }
  88. $pm->wait_all_children;
  89. sub wanted {
  90.   if(-f $File::Find::name){
  91.     if($File::Find::name=~m/\.next$/){
  92.       if(exists $ID{$_}){
  93.         my $o=$File::Find::name;
  94.         $o=~s/\.next$/.bak/;
  95.         unlink($o);
  96.         $o=~s/\.bak$//;
  97.         unlink($o);
  98.         delete $ID{$_};
  99.       }
  100.     }
  101.     if($File::Find::name=~m/\.bak$/){
  102.       my $gh=$_;
  103.       my $e=$gh;
  104.       $gh=~s/\.bak$//;
  105.       my $f=$_;
  106.       $f=~s/\.bak$//;
  107.       unless(exists $ID{$f}){
  108.         my $fuck=&AccountID($f);
  109.         if($fuck ne 'NULL'){
  110.           $ID{$f}=1;
  111.           my $pid=$pm->start and next;
  112.           system("/home/root/Perl/zhubo/ZhuBo.pl $f");
  113.           delete $ID{$f};
  114.           rename($e,$gh);
  115.           $pm->finish;
  116.         }
  117.                 undef $fuck;
  118.       }
  119.     }
  120.     else{
  121.       my $r=$File::Find::name.'.bak';
  122.       rename($File::Find::name,$r);
  123.       unless(exists $ID{$_}){
  124.         my $fuck=&AccountID($_);
  125.         if($fuck ne 'NULL'){
  126.           $ID{$_}=1;
  127.           my $pid=$pm->start and next;
  128.           system("/home/root/Perl/zhubo/ZhuBo.pl $_");
  129.           my $e=$r;
  130.           $e=~s/\.bak$//;
  131.           delete $ID{$_};
  132.           rename($r,$e);
  133.           $pm->finish;
  134.         }
  135.                 undef $fuck;
  136.       }
  137.     }
  138.   }
  139. }
  140. sub AccountID{
  141.   my $accountId=shift;
  142.   my $url='https://taobaolive.taobao.com/room/index.htm?userId='.$acco
  143. +untId;
  144.   my $res;
  145.   while(1){
  146.     my $eval=eval{
  147.       $res=$ua->get($url=>{%{$Header{'item_list'}{'header'}}})->result
  148. +;
  149.     };
  150.     last if($eval);
  151.   }
  152.   if($res->is_success){
  153.     my $body=$res->body;
  154.     if($body=~m/var liveDetail \= (.*?) \|\| \{\}\;/s){
  155.       my $liveDetail=$1;
  156.       unless($liveDetail=~m/\}$/){
  157.                 undef $res;
  158.                 undef $body;
  159.                 undef $liveDetail;
  160.                 return 'NULL';
  161.             }
  162.       my $json_hash=Mojo::JSON::decode_json($liveDetail);
  163.       if(exists $json_hash->{'liveId'}){
  164.         if($json_hash->{'liveId'} ne '0'){
  165.           my $liveId=$json_hash->{'liveId'};
  166.                     undef $json_hash;
  167.                     undef $res;
  168.                     undef $body;
  169.                     undef $liveDetail;
  170.           return $liveId;
  171.         }
  172.         else{
  173.                     undef $json_hash;
  174.                     undef $res;
  175.                     undef $body;
  176.                     undef $liveDetail;
  177.           return 'NULL';
  178.         }
  179.       }
  180.       else{
  181.                 undef $json_hash;
  182.                 undef $res;
  183.                 undef $body;
  184.                 undef $liveDetail;
  185.         return 'NULL';
  186.       }
  187.     }
  188.     else{
  189.       &AccountID($accountId);
  190.     }
  191.   }
  192.   else{
  193.     &AccountID($accountId);
  194.   }
  195. }
  196. sub INT_EXIT{
  197.   exit;
  198. }
复制代码


论坛徽章:
0
发表于 2017-04-10 22:25 |显示全部楼层
Parallel::ForkManager实际上用也的fork,理论上在Linux上进程fork有一部分memory page可以share的,所以整个的内存使用量不太会刚好是一个整数倍关系。

另外感觉代码稍微有点乱啊。。
1. 那一堆use Mojo::XX里面绝大多数都是不需要的,貌似你只用了Mojo::UserAgent
2. 为什么Parallel::ForkManager要设定最大500个进程?你确定同时fork几百个这么多的进程真的可以提高效率吗?
3. 为什么不分两部做呢?先准备好所有要处理的文件(及处理参数,如果有的话),再用一个loop + P::F?那样看上去会比你现在这样清楚一些。

论坛徽章:
34
CU大牛徽章
日期:2013-04-17 11:10:17CU大牛徽章
日期:2013-09-18 15:26:10狮子座
日期:2013-09-27 17:44:07CU十二周年纪念徽章
日期:2013-10-24 15:41:34射手座
日期:2013-10-24 21:01:23辰龙
日期:2013-12-20 17:07:19狮子座
日期:2014-05-12 11:00:00寅虎
日期:2014-06-04 16:25:27IT运维版块每日发帖之星
日期:2015-08-17 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43数据库技术版块每日发帖之星
日期:2015-12-01 06:20:00平安夜徽章
日期:2015-12-26 00:06:30
发表于 2017-04-11 08:25 |显示全部楼层
子进程继承父进程的内存空间,这个有什么奇怪的呢
如果要fork子进程,主进程最好什么都不做,只做好master的工作,其他逻辑都让worker去搞,否则必然出现内存堆积。
ps. 看起来就是个简单的爬虫程序,mojo是可以异步并行的,根本就用不到forkmanger...

求职 : 网络信息安全
论坛徽章:
0
发表于 2017-04-11 21:56 |显示全部楼层
呵呵,多谢楼上两位大佬,代码是有点乱,我后来重写,开10个进程管6000+webpage,每个进程40M,上交公司了。use Mojo::XX是防打包时依赖未能自动打包,当然,程序代码未列出的还用到像Mojo::JSON,Mojo::Util......,所以干脆都写进去了。
Mojo异步并行如何打满核与带宽,请指点,多谢!

论坛徽章:
34
CU大牛徽章
日期:2013-04-17 11:10:17CU大牛徽章
日期:2013-09-18 15:26:10狮子座
日期:2013-09-27 17:44:07CU十二周年纪念徽章
日期:2013-10-24 15:41:34射手座
日期:2013-10-24 21:01:23辰龙
日期:2013-12-20 17:07:19狮子座
日期:2014-05-12 11:00:00寅虎
日期:2014-06-04 16:25:27IT运维版块每日发帖之星
日期:2015-08-17 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43数据库技术版块每日发帖之星
日期:2015-12-01 06:20:00平安夜徽章
日期:2015-12-26 00:06:30
发表于 2017-04-12 08:48 |显示全部楼层
几核就起几个进程,可参考prefork.最简单就是shell直接起。
进程消耗大,为了避免内存泄露,worker进程可定期关闭,但要避免频繁重复启停。
每个进程内部用异步或者协程发起成百数千请求无压力。
减少进程通信,每个进程自行处理目标和结果数据。

求职 : 网络信息安全
论坛徽章:
0
发表于 2017-04-12 21:31 |显示全部楼层
呵呵,受教了,谢谢大佬解答!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP