Skip Menu |

This queue is for tickets about the Var-Pairs CPAN distribution.

Report information
The Basics
Id: 94459
Status: resolved
Priority: 0/
Queue: Var-Pairs

People
Owner: Nobody in particular
Requestors: perl [...] toby.ink
Cc:
AdminCc:

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



Subject: Use a blessed arrayref for Var::Pairs::Pair instead of an inside-out object
The attached script (bench.pl) takes 17 seconds to run (on my netbook) using the current CPAN release of Var::Pairs. Patching it to use a blessed array reduces the run time to 9 seconds. Pros: - Speed. - Allows my($k,$v)=@$pair to "just work". This seems a natural idiom. - Data::Dumper-friendly output. - Possible future speed improvements using Class::XSAccessor::Array.(Current version seems slightly buggy for lvalues.) Cons: - General encapsulation concerns regarding non-inside-out objects apply. - More specifically, people might think that assigning to $pair->[0] or $pair->[1] or even @$pair will do something useful. (It won't; it will just break the object subtly.)
Subject: bench.pl
use Var::Pairs qw(each_pair); my @vals = 1..500; for my $v (@vals) { while (my $pair = each_pair @vals) { my $x = $pair->index + $pair->value; $pair->value = $x; } }
Subject: var-pairs-pair-blessed-arrayref.diff
diff -urN Var-Pairs-0.001005/lib/Var/Pairs.pm Var-Pairs-0.001005-mine/lib/Var/Pairs.pm --- Var-Pairs-0.001005/lib/Var/Pairs.pm 2014-03-11 10:17:52.000000000 +0000 +++ Var-Pairs-0.001005-mine/lib/Var/Pairs.pm 2014-04-05 13:51:06.139957217 +0100 @@ -279,32 +279,26 @@ # Class implementing each key/value pair... package Var::Pairs::Pair { - use Hash::Util qw< fieldhash >; use Scalar::Util qw< looks_like_number >; use Data::Alias; use Carp; - # Each pair object has two attributes... - fieldhash my %key_for; - fieldhash my %value_for; - # Accessors for the attributes (value is read/write)... - sub value :lvalue { $value_for{shift()} } - sub index { $key_for{shift()} } - sub key { $key_for{shift()} } + sub value :lvalue { shift->[1] } + sub index { shift->[0] } + sub key { shift->[0] } - # The usual inside-out constructor... sub new { my ($class, $key, $container_ref, $container_type) = @_; - # Create a scalar based object... - my $new_obj = bless \do{ my $scalar }, $class; + # Create an array based object... + my $new_obj = bless [], $class; # Initialize its attributes (value needs to be an alias to the original)... - $key_for{$new_obj} = $key; - alias $value_for{$new_obj} = $container_type eq 'array' ? $container_ref->[$key] - : $container_type eq 'none' ? $_[2] - : $container_ref->{$key}; + $new_obj->[0] = $key; + alias $new_obj->[1] = $container_type eq 'array' ? $container_ref->[$key] + : $container_type eq 'none' ? $_[2] + : $container_ref->{$key}; return $new_obj; } @@ -314,18 +308,18 @@ # As a string, a pair is just: key => value q{""} => sub { my $self = shift; - my $value = $value_for{$self}; + my $value = $self->[1]; $value = ref $value ? ref $value : looks_like_number($value) ? $value : qq{"$value"}; - return "$key_for{$self} => $value"; + return "$self->[0] => $value"; }, # Can't numerify a pair (make it a hanging offence)... q{0+} => sub { croak "Can't convert Pair(".shift.") to a number" }, # All pairs are true (just as in Perl 6)... - q{bool} => sub { 1 }, + q{bool} => sub { !!1 }, # Everything else as normal... fallback => 1,
Subject: Re: [rt.cpan.org #94459] Use a blessed arrayref for Var::Pairs::Pair instead of an inside-out object
Date: Sat, 5 Apr 2014 17:31:36 +0200
To: bug-Var-Pairs [...] rt.cpan.org
From: Damian Conway <damian [...] conway.org>
On 5 April 2014 15:04, Toby Inkster via RT <bug-Var-Pairs@rt.cpan.org> wrote: Show quoted text
> The attached script (bench.pl) takes 17 seconds to run (on my netbook) using the current CPAN release of Var::Pairs. > Patching it to use a blessed array reduces the run time to 9 seconds.
Much appreciated, Toby. I'm unwilling to give up the inside-out encapsulation, but I really wanted that performance boost. ;-) So I've reimplemented using array-based inside-out instead. The performance appears to be more-or-less identical to your proposal, but we still keep the encapsulation of pair objects. Addressing your analysis: Show quoted text
> Pros: > - Speed.
Same gains as for unencapsulated array-based objects. Show quoted text
> - Allows my($k,$v)=@$pair to "just work". This seems a natural idiom.
I added a ->kv method to pair objects to provide this: my($k,$v)=$pair->kv; Show quoted text
> - Data::Dumper-friendly output.
Not supported at the moment. Data::Dumper *really* needs a simple way of allowing individual classes to tell it how to dump their objects! :-( Show quoted text
> - Possible future speed improvements using Class::XSAccessor::Array.( > Current version seems slightly buggy for lvalues.)
If this proves feasible, I may eventually prevail upon the developers to support this for inside-out arrays as well. ;-) Show quoted text
> Cons: > > - General encapsulation concerns regarding non-inside-out objects apply.
Not an issue. New approach is still encapsulated. Show quoted text
> - More specifically, people might think that assigning to $pair->[0] > or $pair->[1] or even @$pair will do something useful. (It won't; it > will just break the object subtly.)
Not an issue. New approach is still encapsulated. I very much appreciated the report (especially with a patch!), Toby. Even though I ultimately chose a different solution, your work spurred me to accelerate the module, for which I'm extremely grateful. v0.002 is now up on CPAN. I would, of course, welcome any further feedback on it. However, you should now find its performance comparable to your "raw arrays" patch. Thanks, Damian