URN Logo
UNIX Resources » Linux » China Linux Forum » Perl 编 程 » 5 » [精华] perl 语言编程实例-多进程篇
announcement 声明: 本页内容为中国Linux论坛的内容镜像,文章的版权以及其他所有的相关权利属于中国Linux论坛和相应文章的作者,如果转载,请注明文章来源及相关版权信息。
Resources
China Linux Forum(finished)
Linux Forum(finished)
FreeBSD China(finished)
linuxforum.net
  业界新闻与评论
  自由软件杂谈
  IT 人生
  Linux软件快递
  翻译作坊
  Linux图书与评论
  GNU Emacs/XEmacs
  Linux 中文环境和中文化
  Linux桌面与办公软件
  Linux 多媒体与娱乐版
  自由之窗Mozilla
  笔记本电脑上的Linux
  Gentoo
  Debian 一族
  网络管理技术
  Linux 安装与入门
  WEB服务器和FTP服务器
  域名服务器和邮件服务器
  Linux防火墙和代理服务器应用
  文件及打印服务器
  技术培训与认证
  Linux内核技术
  Linux 嵌入技术
  Linux设备驱动程序
  Linux 集群技术
  LINUX平台数据库
  系统和网络安全
  CPU 与 编译器
  系统计算研究所专栏
  Linux下的GUI软件开发
  C/C++编程版
  PHP 技 术
  Java&jsp技术
  Shell编程技术
  Perl 编 程
  Python 编 程
  XML/Web Service 技术
  永远的Unix
  FreeBSD世界
   
[精华] perl 语言编程实例-多进程篇
[精华] perl 语言编程实例-多进程篇 - horsley [2004-07-06 11:29 | 4,744 byte(s)]
 
Re: perl 语言编程实例-多进程篇 - enow [2004-09-21 16:34 | 71 byte(s)]
 
Re: perl 语言编程实例-多进程篇 - horsley [2004-09-23 11:28 | 110 byte(s)]
 
Re: perl 语言编程实例-多进程篇 - horsley [2004-09-23 11:32 | 1,695 byte(s)]
 
Re: perl 语言编程实例-多进程篇 - enow [2004-09-24 02:13 | 26 byte(s)]
 
Re: perl 语言编程实例-多进程篇 - uzhou [2004-09-06 16:23 | 48 byte(s)]
 
 
Subject: [精华] perl 语言编程实例-多进程篇
Author: horsley    Posted: 2004-07-06 11:29    Length: 4,744 byte(s)
[Original] [Print] [Top]

perl 语言编程实例-多进程篇

perl 语言是一种非常强大的脚本语言,其应用遍及系统维护,CGI,数据库编程。
以下是我遇到的一个具体问题,应用perl获得圆满解决。

问题提出:
某数据库应用。需要检索一批数据(A表,数据量12万左右)。对该批数据
将进行逐一核对,期间将关联三个千万级的表(C,D,E表,分别有近亿条数据),
并将检索状态插入一张新表(F)。

传统解决方案:
编写存储过程。打开一个cursor,对A表遍历,逐一检索C,D,E表。
判断状态写入新表。编程过程十分简单,顺利完成。但执行时效率低下,耗时在
8小时左右,不能满足要求。

分析:
C,D,E表建有极其完备的索引。对单条数据检索极其快速。同时执行时主机CPU,
内存等资源十分空闲。查询单条记录耗时:8×3600/12万=0.24秒,也是在合理的范围。
同时主机数据库在业务高峰期时可以支持500-600用户同时登陆(telnet方式)。以上
说明性能瓶颈不在主机,数据库上。

结论:以上所有都合情合理,采用单进程方式无法进一步提高性能。为提高速度,只能
采用多进程。


快速构造原型:

原型一:
#!/usr/bin/perl

my $maxchild=20;
foreach $item (1..500) {
while ( `ps -ef|grep $0|wc -l` > $maxchild) { select undef,undef,undef,0.1; };
if ($PID=fork()){
print "Starting Sub_Process:$PID ";
} else {
print "I will handle data:$item ";
sleep 1;
exit 1;
};
}

执行以上,正常,子进程控制在20。

以上述脚本为基础,添加数据库部分:

#!/usr/bin/perl

use DBI;


my $dbh=DBI->connect(...);
my $sth=$dbh->prepare(qq/select * from A/);
$sth->execute();
$sth->bind_column(undef,.....);

while ($sth->fetch()) {
while ( `ps -ef|grep $0|wc -l` > $maxchild) { select undef,undef,undef,0.1; };
if ($PID=fork()) {
print "Starting Sub_Process:$PID ";
} else {
query(B,C,D); #执行数据库操作
insert(E);
exit 1;
}
}
$sth->finish();
$dbh->disconnect();

确保无语法错误,执行。处理一两条数据后脚本报错,中断。具体错误略。

分析:程序框架没错,但是在fork子进程时,$dbh同时被子进程继承,导致该数据库连接反复使用

由于数据库底层的某种原因,对该种操作是不允许的。结论:以上简单的多进程方式不可行。数据

连接部分必须同 fork 分离。

######################################

考虑很久,设计如下原型:将打开A表的cursor单独提出,结果传给另外一个进程。
12万数据较大,作为参数传递似乎不妥,考虑利用管道通信。



原型二:
############################

分成 getdata,setdata两个程序。首先建立管道 : mknod data.pipe p

cat getdata:

#!/usr/bin/perl

use DBI;
open(DATAPIPE,">./data.pipe") or die "$! ";

my $dbh=DBI->connect(...);
my $sth=$dbh->prepare(qq/select * from A/);
$sth->execute();
$sth->bind_column(undef,.....);

while ($sth->fetch()) {
print DATAPIPE data.....;
}
close(DATAPIPE);

######################

cat setdata:

#!/usr/bin/perl
use DBI;
open(DATAPIPE,"<./data.pipe") or die "$! ";

my $pipecount=0;
my $maxlines=2000;
my @lines=();

while($record=<DATAPIPE>) {
$pipecount++;
push @lines,$record;

unless ($pipecount % $maxlines) {
if ($PID=fork()){
print "Starting Sub_Process:$PID ";
@lines=();
}else{
my $dbh=DBI->connect(...);
foreach (@lines) {
handle_data($_);
}
$dbh->disconnect();
exit 1;
}
}
}

my $dbh=DBI->connect(...);
foreach (@lines) {
handle_data($_);
}

$dbh->disconnect();

以上脚本运行正常,执行时启动:12万/$maxlines= 60个子进程。
处理万所有数据耗时在 10分钟左右,效率提高几十倍。

[Original] [Print] [Top]
Subject: [精华] Re: perl 语言编程实例-多进程篇
Author: horsley    Posted: 2004-07-06 11:33    Length: 65 byte(s)
[Original] [Print] [Top]
脚本执行方法如下:

./getdata&./setdata
[Original] [Print] [Top]
Subject: Re: perl 语言编程实例-多进程篇
Author: uzhou    Posted: 2004-09-06 16:23    Length: 48 byte(s)
[Original] [Print] [Top]
Good! Are there more materials about this topic?
[Original] [Print] [Top]
Subject: Re: perl 语言编程实例-多进程篇
Author: enow    Posted: 2004-09-21 16:34    Length: 71 byte(s)
[Original] [Print] [Top]
好!

但在Windows环境下,好像不能运行,有解决办法吗?
----
---------------------
问的太多?谁叫我不懂!
[Original] [Print] [Top]
Subject: Re: perl 语言编程实例-多进程篇
Author: horsley    Posted: 2004-09-23 11:28    Length: 110 byte(s)
[Original] [Print] [Top]
我没有试过windows 下的perl

我想,只要解决 fork 和 管道的问题,
windows下应该也可以
[Original] [Print] [Top]
Subject: Re: perl 语言编程实例-多进程篇
Author: horsley    Posted: 2004-09-23 11:32    Length: 1,695 byte(s)
[Original] [Print] [Top]
这里我使用pipe函数将原有程序改了一下,
两个合成一个,也不用另外建管道了。
程序没测过,应该没问题:


#!/usr/bin/perl

use DBI;

pipe(PIPE_READ,PIPE_WRITE) or die "Can't make pipe! ";

unless ($pid = fork) {
defined $pid or die "can't fork:$! ";
close(PIPE_READ);

my $dbh=DBI->connect(...);
my $sth=$dbh->prepare(qq/select * from A/);
$sth->execute(); $sth->bind_column(undef,.....);
while ($sth->fetch()) { print PIPE_WRITE data.....;}
$dbh->disconnect();
exit;
}

$SIG{CHLD} = sub { waitpid($pid,0) };

close(PIPE_WRITE);

my $pipecount=0;
my $maxlines=2000;
my @lines=();

while($record=<PIPE_READ> ) {
$pipecount++;
push @lines,$record;
unless ($pipecount % $maxlines) {
if ($PID=fork()){
print "Starting Sub_Process:$PID ";
@lines=();
}else{
my $dbh=DBI->connect(...);
foreach (@lines) { handle_data($_);}
$dbh->disconnect();
}
exit 1;
}
}
}

my $dbh=DBI->connect(...);
foreach (@lines) {handle_data($_);}
$dbh->disconnect();

[Original] [Print] [Top]
Subject: Re: perl 语言编程实例-多进程篇
Author: enow    Posted: 2004-09-24 02:13    Length: 26 byte(s)
[Original] [Print] [Top]
谢谢,我测试一下再回复你。
----
---------------------
问的太多?谁叫我不懂!
[Original] [Print] [Top]
« Previous thread
替换时可以使用函数进行处理么?
Perl 编 程
5
Next thread »
请问: 如何查询perl 已经安装的模块?
     

Copyright © 2007 UNIX Resources Network, All Rights Reserved.      About URN | Privacy & Legal | Help | Contact us
备案序号: 京ICP备05006143    webmaster: webmaster@unixresources.net
This page created on 2008-07-17 04:09:04, cost 0.055386066436768 ms.