Skip Menu |

This queue is for tickets about the HTTP-DAV CPAN distribution.

Report information
The Basics
Id: 17171
Status: resolved
Worked: 5 min
Priority: 0/
Queue: HTTP-DAV

People
Owner: OPERA [...] cpan.org
Requestors: axc [...] rentrak.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



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);
I hope the original author of this ticket is still around... :-) Your patch is very interesting. However, we just found a problem with propfind() that had to do with incorrect "-depth" argument handling. It was set to 1 even if you passed zero. If you're still using this module, I encourage you to try out v0.36, soon on CPAN. Thanks!
No answer. Closing.
Subject: Re: [rt.cpan.org #17171] propfind performance problems
Date: Tue, 24 Mar 2009 21:35:59 -0700
To: bug-HTTP-DAV [...] rt.cpan.org
From: pcollins [...] cpan.org
the best way to fix propfind's performance problems is to swap out xml::dom library with xml::twig or xml::sax. This would fix memory leaks too. I have a lot of thoughts about how to do that. I started doing this a few times but never completed. It would make a big difference to the library as it would enable it to support namespaces properly as well. Patrick. 2009/3/24 Opera Software ASA via RT <bug-HTTP-DAV@rt.cpan.org> Show quoted text
> Queue: HTTP-DAV > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=17171 > > > No answer. Closing. >
Hi Patrick, that's fine, but did you try the new version of propfind() from 0.36 on? I have seen that it's much faster than before, due to the `depth' argument fix. Right now I don't have time to look into this big task, maybe in the future... At least for now propfind() is fast enough for us. -- Cosimo
Subject: Re: [rt.cpan.org #17171] propfind performance problems
Date: Wed, 25 Mar 2009 08:31:48 -0700
To: "bug-HTTP-DAV [...] rt.cpan.org" <bug-HTTP-DAV [...] rt.cpan.org>
From: Patrick Collins <pcollins1 [...] gmail.com>
Ok great. Yes it is a big task :) making the switch of xml libraries would enable it to support deltav and hence also be an svn browser. Sent from my iPhone On Mar 25, 2009, at 1:55 AM, "Opera Software ASA via RT" <bug-HTTP-DAV@rt.cpan.org Show quoted text
> wrote:
Show quoted text
> Queue: HTTP-DAV > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=17171 > > > Hi Patrick, > > that's fine, but did you try the new version of propfind() from 0.36 > on? > I have seen that it's much faster than before, due to the `depth' > argument fix. > > Right now I don't have time to look into this big task, maybe in the > future... At least for now propfind() is fast enough for us. > > -- > Cosimo >