Revision: 112 Author: matt Date: 2006-08-24 00:01:51 +0000 (Thu, 24 Aug 2006)
Log Message: ----------- effectively memoize hooks to improve performance Modified Paths: -------------- trunk/lib/AxKit2/Client.pm Modified: trunk/lib/AxKit2/Client.pm =================================================================== --- trunk/lib/AxKit2/Client.pm 2006-08-23 16:55:00 UTC (rev 111) +++ trunk/lib/AxKit2/Client.pm 2006-08-24 00:01:51 UTC (rev 112) @@ -99,14 +99,21 @@ my $conf = $self->config(); + # Logging hooks called at config parse time, so can't cache them + if ($hook ne "logging") { + if (my $cached_hooks = $conf->notes("cached_hooks_$hook")) { + return $self->_run_hooks($conf, $hook, [EMAIL PROTECTED], $cached_hooks, 0); + } + } + my @hooks; - MAINLOOP: for my $plugin ($conf->plugins) { my $plug = $PLUGINS{$plugin} || next; push @hooks, map { [$plugin, $plug, $_] } $plug->hooks($hook); } - $self->_run_hooks($hook, [EMAIL PROTECTED], [EMAIL PROTECTED]); + $conf->notes("cached_hooks_$hook", [EMAIL PROTECTED]); + $self->_run_hooks($conf, $hook, [EMAIL PROTECTED], [EMAIL PROTECTED], 0); } sub finish_continuation { @@ -116,34 +123,40 @@ $self->{continuation} = undef; my $hook = shift @$todo; my $args = shift @$todo; - $self->_run_hooks($hook, $args, $todo); + my $pos = shift @$todo; + my $conf = $self->config; + my $hooks = $conf->notes("cached_hooks_$hook"); + $self->_run_hooks($conf, $hook, $args, $hooks, $pos+1); } sub _run_hooks { my $self = shift; - my ($hook, $args, $todo) = @_; + my ($conf, $hook, $args, $hooks, $pos) = @_; - my $conf = $self->config(); + my $last_hook = $#$hooks; my @r; - while (@$todo) { - my $info = shift @$todo; - my ($plugin, $plug, $h) = @$info; - $self->log(LOGDEBUG, "$plugin running hook $hook") unless $hook eq 'logging'; - eval { @r = $plug->$h($self, $conf, @$args) }; - if ($@) { - my $err = $@; - $self->log(LOGERROR, "FATAL PLUGIN ERROR: $err"); - $self->hook_error($err); - return DONE; + if ($pos <= $last_hook) { + for my $idx ($pos .. $last_hook) { + my $info = $hooks->[$idx]; + my ($plugin, $plug, $h) = @$info; + # $self->log(LOGDEBUG, "$plugin ($idx) running hook $hook") unless $hook eq 'logging'; + eval { @r = $plug->$h($self, $conf, @$args) }; + if ($@) { + my $err = $@; + $self->log(LOGERROR, "FATAL PLUGIN ERROR: $err"); + $self->hook_error($err); + return DONE; + } + next unless @r; + if ($r[0] == CONTINUATION) { + $self->pause_read(); + $self->{continuation} = [$hook, $args, $idx]; + } + last unless $r[0] == DECLINED; } - next unless @r; - if ($r[0] == CONTINUATION) { - $self->pause_read(); - $self->{continuation} = [$hook, $args, @$todo]; - } - last unless $r[0] == DECLINED; } + $r[0] = DECLINED if not defined $r[0]; if ($r[0] != CONTINUATION) { my $responder = "hook_${hook}_end"; @@ -345,7 +358,7 @@ } elsif ($ret == OK) { $out->output($self) if $out; - $self->write(sub { $self->http_response_sent() }); + $self->write(sub { $self->http_response_sent($self->headers_out->response_code) }); } else { $self->default_error_out($ret);