Perl:分配[]或{}贵吗?如何快速重置数字/关联数组?

时间:2011-06-15 12:46:13

标签: perl performance memory-management reference

我有a card game - 用Perl编写并且只有很少的对象,比如这个:

package PlayingTable;

our (%Games, $Num);

sub new {
        my $pkg   = shift;

        my $game = {
                ID        => ++$Num,
                PHASE     => WAITING,
                KIBITZERS => [],
                PLAYERS   => [],
                INFO      => '',
                RED5      => '',
                TALON     => [],
                TABLE     => {},
                ROUND     => 0,
                PASS_ROUND => 0,
                START     => undef,
                TURN      => undef,
                NPASSED   => 0,
                HOLDER    => undef,
                WHISTER1  => undef,
                WHISTER2  => undef,
                ACTIVE    => undef,
                PASSIVE   => undef,
                SHOW      => undef,
                BEFORE    => undef,
                SUIT1     => undef,
                TRUMP     => undef,
                WINNER    => undef,
        };

        $Games{$Num} = $game;
        bless($game, $pkg);
}

在对象中我有很多哈希和列表引用,我经常需要重置它们。例如,当游戏结束时(一种情况:当所有玩家都通过时),我只会调用 $ player-> {CARDS} = {}; 来减少游戏中的牌数玩家手到0。

我的问题是如果分配[]和{}是一个足够好的做法,或者它太昂贵,因为perl解释器将malloc(或它做的任何事情来分配内存)那些新的哈希和内部的数组对象(它真的吗?还是解释器足够聪明?)。

我正在使用(并且不想升级)库存CentOS perl包:

This is perl, v5.8.8 built for x86_64-linux-thread-multi

使用CentOS 5.6 / 64位,在4GB机器上,并且有最大值。在晚上同时有500名玩家。我的perl进程(非分叉守护进程,轮询TCP套接字)现在使用:

top - 13:50:07 up 13 days,  3:25,  1 user,  load average: 2.64, 3.36, 3.46
Tasks: 179 total,   2 running, 177 sleeping,   0 stopped,   0 zombie
Cpu0  :  3.6%us,  0.3%sy,  0.0%ni, 96.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu1  :  6.0%us,  1.3%sy,  0.0%ni, 92.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu2  : 13.7%us,  0.3%sy,  0.0%ni, 85.3%id,  0.7%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu3  : 42.7%us,  1.7%sy,  0.0%ni, 54.6%id,  0.0%wa,  0.3%hi,  0.7%si,  0.0%st
Mem:   4018280k total,  2831016k used,  1187264k free,   313128k buffers
Swap:  7999472k total,    13612k used,  7985860k free,  1775196k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
13685 afarber   15   0  112m  46m 2704 R 41.8  1.2 176:45.14 pref.pl

谢谢! 亚历

3 个答案:

答案 0 :(得分:7)

rules of optimization

  1. 别。
  2. 不要......但是。
  3. 优化前的配置文件。
  4. 在另一条评论中,您说您没有性能问题,因此您仍然处于规则1。

    至于如何清除阵列和散列,有一个潜在的缺陷要避免。好的做法是始终返回对象私有数据的副本。考虑

    #! /usr/bin/env perl
    
    use strict;
    use warnings;
    
    package My::Class;
    
    sub new {
      my($class,@a) = @_;
      bless { a => \@a } => $class;
    }
    
    sub a {
      my($self) = @_;
      $self->{a};
    }
    
    package main;
    
    my $obj = My::Class->new(1, 2, 3);
    
    my $a = $obj->a;
    print "@$a\n";
    
    push @$a, qw/ foo bar /;
    
    my $b = $obj->a;
    print "@$b\n";
    

    它的输出是

    1 2 3
    1 2 3 foo bar

    返回对私有数据的引用为处理不受控制且可能令人惊讶的修改提供了一个句柄。

    如果您的代码是共享引用,请务必清除相同的数组和哈希,而不是创建对新引用的引用。否则,其他所有人都将继续使用旧数据而不知道有任何改变。在Perl术语中,写

    @{ $game->{PLAYERS} } = ();
    

    而不是

    $game->{PLAYERS} = [];
    

答案 1 :(得分:0)

您的样本是一种很好的做法。

Perl在基于RHEL的系统上存在性能问题,包括CentOS。 RedHat构建的软件包应该比Perl慢得多。您应该尝试使用ActiveState的构建或Perl的新构建(如果您愿意,可以在/ opt / perl514中构建Perl 5.14,这并不难),看看您是否获得了更好的性能。

答案 2 :(得分:0)

我对此进行了搜索,因为我认为这是一个有趣的问题,但我没有找到任何确切的数字。

但是,这里有一些我发现的文章: