2009-08-06 52 views
0

由于其良好的结构和RDBO比CDBI和DBIC更快的术语,我计划从Class :: DBI迁移到Rose :: DB :: Object。我的Rose :: DB :: Object编译时间太慢了吗?

但是我的机器(Linux的2.6.9-89,Perl的5.8.9)RDBO编译时间上比CDBI慢得多:

 
$ time perl -MClass::DBI -e0 
real 0m0.233s 
user 0m0.208s 
sys  0m0.024s 

$ time perl -MRose::DB::Object -e0 
real 0m1.178s 
user 0m1.097s 
sys  0m0.078s 

这是一个很多不同...

任何人都有类似的行为?

干杯。


@manni和@约翰:感谢有关RDBO引用的模块的解释,那肯定回答为什么编译时间比CDBI慢。

该应用程序未运行在持久性环境中。事实上,它是由几个同时执行cron作业,运行时间为2分钟,5分钟和x分钟间隔 - 是的,编译时间是至关重要的...

Jonathan Rockway的应用程序::持久看似有趣,但其(当前)限制只允许一次运行的应用程序不适合我的目的。此外,它有问题,当我们杀了客户端,服务器进程仍在运行...

+0

加载时间只是一个问题,如果你没有运行在一个持久化的环境中(比如mod_perl或者FastCGI),你真的应该(因为FastCGI托管这些天很便宜,所以没有任何理由)。而且,对于大多数应用程序而言,运行时间占总时间的百分比远远超过启动时间。 – mpeters 2009-08-06 14:16:47

+0

@mpeters:谁说他要构建一些网络应用程序? – innaM 2009-08-06 17:11:02

回答

1

这看起来几乎是戏剧性的在这里:

time perl -MClass::DBI -e0 
real  0m0.084s 
user  0m0.080s 
sys  0m0.004s 

time perl -MRose::DB::Object -e0 
real  0m0.391s 
user  0m0.356s 
sys  0m0.036s 

我的差异恐怕一部分可以简单地解释通过依赖的每个模块中的数量:

perl -MClass::DBI -le 'print scalar keys %INC' 
46 

perl -MRose::DB::Object -le 'print scalar keys %INC' 
95 

当然,你应该问自己多少编译时间真的很重要为您的特定问题。哪些源代码更容易为您维护。

5

Rose::DB::Object简单包含(或从其它模块的引用)比Class::DBI得多的代码。在光明的一面,它也有many more featuresmuch faster at runtime比Class :: DBI。如果编译时间是你的问题,那么你最好的办法就是尽可能少加载代码(或者加快磁盘速度)。

另一种选择是设置auto_load_related_classes为false在您的元数据对象。要尽早做到这一点,全球可能需要您制作一个Metadata子类,然后将其设置为您的常见Rose::DB::Object基类中的meta_class

打开auto_load_related_classes关闭意味着你不得不手动加载你真的想在你的脚本中使用相关的类。这有点痛苦,但它可以让你控制有多少类被加载。 (如果您有大量相互关联的类,加载一个人可以最终拉动所有其他的人英寸)

你可以,也许,有一个环境变量来控制行为。例如元数据类:

package My::DB::Object::Metadata; 

use base 'Rose::DB::Object::Metadata'; 

# New class method to handle default 
sub default_auto_load_related_classes 
{ 
    return $ENV{'RDBO_AUTO_LOAD_RELATED_CLASSES'} ? 1 : 0 
} 

# Override existing object method, honoring new class-defined default 
sub auto_load_related_classes 
{ 
    my($self) = shift; 

    return $self->SUPER::auto_load_related_classes(@_) if(@_); 

    if(defined(my $value = $self->SUPER::auto_load_related_classes)) 
    { 
    return $value; 
    } 

    # Initialize to default 
    return $self->SUPER::auto_load_related_classes(ref($self)->default_auto_load_related_classes); 
} 

,这里是它是如何与您的共同对象的基类:

package My::DB::Object; 

use base 'Rose::DB::Object'; 

use My::DB::Object::Metadata; 

sub meta_class { 'My::DB::Object::Metadata' } 

然后,当你在一个持续的环境中运行设置RDBO_AUTO_LOAD_RELATED_CLASSES为真,并把它假(并且不要忘记为命令行脚本显式加载相关的类)。

同样,如果由于默认的auto_load_related_classes元数据属性的真实值,您目前正在加载比您在特定脚本中严格需要的类更多的类,这只会有所帮助。

+0

对不起,很长的响应延迟... 我必须先完成实施,并且现在已经完成并且所有测试通过,我将返回到性能优化。 但是,按照上面的建议不会提高编译时间? %INC中加载的模块数量保持不变。 该文档说,当这个类初始化时,会自动加载“auto_load_related_classes”,我认为这发生在我通过My​​ :: DB :: Object调用“sub init_db {My :: DB-> new()}”时发生。 – est 2009-08-31 07:27:46

+0

不,这意味着如果加载类A并且它与类B有关系,那么如果auto_load_related_classes()为true,则会自动加载类B.如果您已经手动加载了A和B类,那么显然这个设置不起作用。 – 2009-08-31 13:21:00

+0

啊,现在开始有意义了。我想要更快的磁盘将成为我的案例... – est 2009-09-01 01:51:18

3

如果编译时间是个问题,有一些方法可以降低影响。一个是PPerl,它将普通的Perl脚本编译成一次编译的守护进程。你需要做(安装后,当然)唯一的变化是把家当行:

#!/usr/bin/pperl 

另一种方法是代码编写,其中的大部分工作是由做了客户机/服务器模式应用程序加载昂贵模块的服务器以及仅通过套接字或管道与服务器交互的瘦脚本。

你也应该看看App::Persistentarticle,这两个都是由Jonathan Rockway(又名jrockway)写的。