Subject: | propfind performance problems |
propfind performance degrades rapidly as the number of resources on the
server grows. Here's a patch to help fix the issue.
This patch reduced my directory listing time from 26 seconds to 5. The
remaining major bottleneck appears to be the use of XML::DOM.
Subject: | HTTP-DAV-0.31-speed-up-propfind.patch |
diff -rup HTTP-DAV-0.31.orig/DAV/ResourceList.pm HTTP-DAV-0.31.new/DAV/ResourceList.pm
--- HTTP-DAV-0.31.orig/DAV/ResourceList.pm 2001-09-01 12:48:14.000000000 -0700
+++ HTTP-DAV-0.31.new/DAV/ResourceList.pm 2006-01-19 09:52:49.000000000 -0800
@@ -28,7 +28,7 @@ sub _init {
my @pa = HTTP::DAV::Utils::rearrange( \@arg_names, @p);
$self->{_resources} = ();
-
+ $self->{_resource_xref} = {}
}
####
@@ -57,15 +57,10 @@ sub count_resources {
sub get_member {
my ($self,$uri) = @_;
- $uri = HTTP::DAV::Utils::make_uri($uri);
-
- foreach my $r ( $self->get_resources ) {
- if ( HTTP::DAV::Utils::compare_uris($uri,$r->get_uri) ) {
- return $r;
- }
- }
-
- return 0;
+ $uri = HTTP::DAV::Utils::canonical_uri(HTTP::DAV::Utils::make_uri($uri));
+ my $idx = $self->{_resource_xref}->{ $uri };
+ return 0 unless defined $idx;
+ return $self->{_resources}->[ $idx ];
}
sub add_resource {
@@ -75,6 +70,7 @@ sub add_resource {
$self->remove_resource($resource);
$resource->set_parent_resourcelist($self);
push (@{$self->{_resources}}, $resource);
+ $self->{_resource_xref}{ $resource->get_canonical_uri() } = $#{ $self->{_resources} };
# print "After: ". $self->as_string . "\n";
}
@@ -85,20 +81,11 @@ sub remove_resource {
my $uri;
my $ret;
- $uri = HTTP::DAV::Utils::make_uri($resource->get_uri);
+ $uri = $resource->get_uri;
if (defined $uri && $uri->scheme ) {
- my $found_index = -1;
- foreach my $i ( 0 .. $#{$self->{_resources}} ) {
- my $this_resource = $self->{_resources}[$i];
- my $equiv = HTTP::DAV::Utils::compare_uris($uri,$this_resource->get_uri);
- if ( $equiv || $resource eq $this_resource ) {
- $found_index = $i;
- last;
- }
- }
-
- if ( $found_index != -1 ) {
- $resource = splice(@{$self->{_resources}},$found_index,1);
+ my $idx = $self->{_resource_xref}->{ $resource->get_canonical_uri() };
+ if(defined $idx) {
+ $resource = splice(@{$self->{_resources}},$idx,1);
$resource->set_parent_resourcelist();
$ret = $resource;
} else {
@@ -110,7 +97,6 @@ sub remove_resource {
#print "Removing $ret\n" if $HTTP::DAV::DEBUG>2;
return $ret;
-
}
###########################################################################
diff -rup HTTP-DAV-0.31.orig/DAV/Resource.pm HTTP-DAV-0.31.new/DAV/Resource.pm
--- HTTP-DAV-0.31.orig/DAV/Resource.pm 2002-04-06 09:45:42.000000000 -0800
+++ HTTP-DAV-0.31.new/DAV/Resource.pm 2006-01-19 09:52:49.000000000 -0800
@@ -47,6 +47,7 @@ sub _init {
# Set the _uri
$self->{_uri} = HTTP::DAV::Utils::make_uri($self->{_uri});
die "HTTP URL required when creating a Resource object\n" if ( ! $self->{_uri}->scheme );
+ $self->{_canonical_uri} = HTTP::DAV::Utils::canonical_uri($self->{_uri});
####
# Check that the required objects exist
@@ -137,6 +138,7 @@ sub get_comms { $_[0]->{_comms}; }
sub get_property { $_[0]->{_properties}{$_[1]} ||""; }
sub get_uri { $_[0]->{_uri}; }
sub get_uristring { $_[0]->{_uri}->as_string; }
+sub get_canonical_uri { $_[0]->{_canonical_uri}; }
sub get_parent_resourcelist { $_[0]->{_parent_resourcelist}; }
# $self->get_locks( -owned => [0|1] );
@@ -929,6 +931,7 @@ sub _XML_parse_multistatus {
# Get href <!ELEMENT href (#PCDATA) >
my ($href,$href_a,$resource);
+ my $canonical_uri = $self->get_canonical_uri();
foreach my $node_href ( @nodes_href ) {
#my $node_href = $nodes_href->item($k);
@@ -948,7 +951,7 @@ sub _XML_parse_multistatus {
# Create a new Resource to put into the list
# Remove trailing slashes before comparing.
#print "Am about to compare $res_url and ". $self->get_uri ;
- if (HTTP::DAV::Utils::compare_uris($res_url, $self->get_uri ) ){
+ if (HTTP::DAV::Utils::canonical_uri($res_url) eq $canonical_uri) {
$resource = $self;
#print " Exists. $resource\n";
} else {
@@ -1010,8 +1013,7 @@ sub _XML_parse_multistatus {
$href_a);
}
- } # foreach propstat
-
+ } # foreach propstat
} # foreach response
diff -rup HTTP-DAV-0.31.orig/DAV/Utils.pm HTTP-DAV-0.31.new/DAV/Utils.pm
--- HTTP-DAV-0.31.orig/DAV/Utils.pm 2001-09-07 10:23:38.000000000 -0700
+++ HTTP-DAV-0.31.new/DAV/Utils.pm 2006-01-19 09:52:49.000000000 -0800
@@ -224,6 +224,12 @@ sub make_trail_slash {
return $uri;
}
+sub canonical_uri {
+ my ($uri) = @_;
+ $uri =~ s#\/$##g;
+ return $uri;
+}
+
sub compare_uris {
my ($uri1,$uri2) = @_;
$uri1 = make_uri($uri1);