[32632] in Perl-Users-Digest
Perl-Users Digest, Issue: 3907 Volume: 11
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Mar 21 21:09:27 2013
Date: Thu, 21 Mar 2013 18:09:14 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Thu, 21 Mar 2013 Volume: 11 Number: 3907
Today's topics:
Re: a trival array/ hash benchmark <rweikusat@mssgmbh.com>
Re: a trival array/ hash benchmark <rweikusat@mssgmbh.com>
Re: a trival array/ hash benchmark <rweikusat@mssgmbh.com>
die alias <nospam.gravitalsun.noadsplease@hotmail.noads.com>
Re: die alias <jurgenex@hotmail.com>
Re: die alias <glex_no-spam@qwest-spam-no.invalid>
Re: die alias <rweikusat@mssgmbh.com>
Re: die alias <rweikusat@mssgmbh.com>
Re: die alias <justin.1303@purestblue.com>
Re: die alias <ben@morrow.me.uk>
Re: die alias <derykus@gmail.com>
Re: die alias <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Re: die alias <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Re: die alias <ben@morrow.me.uk>
Re: die alias <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Re: die alias <kkeller-usenet@wombat.san-francisco.ca.us>
Re: die alias <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Re: die alias <ben@morrow.me.uk>
Re: die alias <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Re: die alias <glex_no-spam@qwest-spam-no.invalid>
Object attribute representation [was: a trival array/ h <ben@morrow.me.uk>
Re: Object attribute representation <rweikusat@mssgmbh.com>
Re: Object attribute representation <ben@morrow.me.uk>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Thu, 21 Mar 2013 14:08:35 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: a trival array/ hash benchmark
Message-Id: <87vc8ku9p8.fsf@sapphire.mobileactivedefense.com>
Eli the Bearded <*@eli.users.panix.com> writes:
> In comp.lang.perl.misc, Rainer Weikusat <rweikusat@mssgmbh.com> wrote:
>> When running the trivial microbenchmark
>
> I love these sorts of things, so I tried to duplicate your results.
>
>> -----------
>> use Benchmark;
>>
>> my $h = { Worschtsupp => 4 };
>> my $a = [4];
>>
>> timethese(-5,
>> {
>> h => sub { return $h->{Worschtsupp}; },
>> a => sub { return $a->[0]; }});
>> ------------
>>
>> on 'some computer', the result of three runs was that the hash lookup
>> ran at about 28.31% of the speed of the array access on average.
>
> Why not post actual results?
They are not really meaningful anywhere except on the computer where I
tested this _and_ with the perl version where I tested this.
> When I run it three times:
>
> a: 5 wallclock secs ( 5.30 usr + 0.00 sys = 5.30 CPU) @ 18706996.60/s (n=99147082)
> h: 4 wallclock secs ( 5.24 usr + 0.00 sys = 5.24 CPU) @ 15713758.59/s (n=82340095)
>
> a: 6 wallclock secs ( 5.57 usr + 0.00 sys = 5.57 CPU) @ 28009483.30/s (n=156012822)
> h: 6 wallclock secs ( 5.27 usr + 0.00 sys = 5.27 CPU) @ 24815075.90/s (n=130775450)
>
> a: 5 wallclock secs ( 5.21 usr + 0.00 sys = 5.21 CPU) @ 19115772.55/s (n=99593175)
> h: 4 wallclock secs ( 5.03 usr + 0.00 sys = 5.03 CPU) @ 22237998.61/s (n=111857133)
Eg, this suggests that 5.14.2 does something more intelligent (for a
certain definition of 'intelligent') for a static hash lookup than 'do
it from scratch every time', possibly even because hordes of "stupid
hash users" (like herds of mooses) made it more worthwhile to put an
effort into this. This could lead to an 'interesting' arms race where
some people devise more elaborate benchmarks in order to 'catch them
red-handed' while the people supposed to be caught devise more
elaborate ways to fool benchmarks.
The point of this posting was mainly to provide others with a way to
determine what the difference is for them with some simple test case
and to demonstrate that there's a difference at all (When in court, at
least in a civil case, a 'good' lawyer in a losing position will
simply deny everything the other party claims[*], including that the
sun rises in the morning, because this means everything had to be
proven which ensures that the case will grind down to a halt in
technicalities 'for a long time'. This tactic is even more useful to
cover unwelcome statements on USENET with surreptitious noise so that
nobody hears them).
[*] Real world example: I had the mispleasure to be in a court case
because somebody ran his car into my car because he ignored certain
traffic sign some ten years ago. Among the things which were denied
by the lawyer of the other party was that a road running uphill to the
next village right at the edge of the town would actually run uphill
and that the ignored traffic sign stood there at all.
------------------------------
Date: Thu, 21 Mar 2013 14:25:33 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: a trival array/ hash benchmark
Message-Id: <87r4j8u8wy.fsf@sapphire.mobileactivedefense.com>
Ben Morrow <ben@morrow.me.uk> writes:
> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>> When running the trivial microbenchmark
>>
>> -----------
>> use Benchmark;
>>
>> my $h = { Worschtsupp => 4 };
>> my $a = [4];
>>
>> timethese(-5,
>> {
>> h => sub { return $h->{Worschtsupp}; },
>> a => sub { return $a->[0]; }});
>> ------------
>>
>> on 'some computer', the result of three runs was that the hash lookup
>> ran at about 28.31% of the speed of the array access on average.
>> 10,000,000 hash lookups are needed in order to spend 1s of processing
>> time solely on that and about 33,333,333 could have been done in the
>> same time.
>
> Like most microbenchmarks, this tells you very little about real code.
> Try something a bit more realistic, like
>
> #!/opt/perl/bin/perl
>
> use Benchmark qw/cmpthese/;
>
> sub one_a { my ($self) = @_; $self->[0]; }
> sub one_h { my ($self) = @_; $self->{a}; }
> sub two_a { my ($self) = @_; $self->one_a; }
> sub two_h { my ($self) = @_; $self->one_h; }
> sub if_a { my ($self) = @_; if (rand > 0.2) { $self->two_a } }
> sub if_h { my ($self) = @_; if (rand > 0.2) { $self->two_h } }
This includes all kinds of unrelated effects in the test case and, as
you yourself admitted ('as I suspected ...'), even unrelated effects
you specifically included because you expected them to render the
result useless for comparing hash and array lookups. Unsurprisingly,
it became (almost) useless for this particular purpose.
[numbers deleted]
> the method-call overhead completely dominates the
> overhead of the hash lookup. If you can save one method call, you will
> save more time than you would have saved by using an arrayref;
Putting this in another way: The overhead of decoupling the so-called
'classs methods' from 'the object representation' with a layer of
'more privileged core class methods' aka 'accessors' is so high that
the actual representation doesn't matter anymore which means that the
theoretical benefit of that ('the representation could be changed
without affecting the 'set of general-purpose subroutines needlessly
tied to the so-called class) isn't worthwhile: The cure is worse than
the disease.
------------------------------
Date: Thu, 21 Mar 2013 18:33:12 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: a trival array/ hash benchmark
Message-Id: <874ng41u3b.fsf@sapphire.mobileactivedefense.com>
Rainer Weikusat <rweikusat@mssgmbh.com> writes:
> Ben Morrow <ben@morrow.me.uk> writes:
>> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
[...]
>>> -----------
>>> use Benchmark;
>>>
>>> my $h = { Worschtsupp => 4 };
>>> my $a = [4];
>>>
>>> timethese(-5,
>>> {
>>> h => sub { return $h->{Worschtsupp}; },
>>> a => sub { return $a->[0]; }});
>>> ------------
[...]
>> Like most microbenchmarks, this tells you very little about real code.
>> Try something a bit more realistic, like
[...]
>> the method-call overhead completely dominates the
>> overhead of the hash lookup. If you can save one method call, you will
>> save more time than you would have saved by using an arrayref;
>
> Putting this in another way: The overhead of decoupling the so-called
> 'classs methods' from 'the object representation' with a layer of
> 'more privileged core class methods' aka 'accessors' is so high that
> the actual representation doesn't matter anymore which means that the
> theoretical benefit of that ('the representation could be changed
> without affecting the 'set of general-purpose subroutines needlessly
> tied to the so-called class) isn't worthwhile: The cure is worse than
> the disease.
Two things which kept bothering me about this:
1. My statement above is a little disingenious in this context: The
method call overhead is higher and the 'The cure ...' is - at best -
an attempt to change the topic of the converstation and - at worst -
some piece of not that easily discardable nonsense (both
intentionally).
2. The 'Like most ...' statement is wrong: The example code I gave
should be identical to the code in a typical 'getter' method.
------------------------------
Date: Thu, 21 Mar 2013 17:38:52 +0200
From: George Bouras <nospam.gravitalsun.noadsplease@hotmail.noads.com>
Subject: die alias
Message-Id: <kif9h0$bq2$1@news.ntua.gr>
I want to to have my die, the following does not work
use strict;
use warnings;
sub die;
die "oups";
sub die {
print "There was a problem : $_[0]\n";
}
------------------------------
Date: Thu, 21 Mar 2013 09:21:22 -0700
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: die alias
Message-Id: <hfcmk8h2okk9v036is1l4i3kcdmkr22apl@4ax.com>
George Bouras <nospam.gravitalsun.noadsplease@hotmail.noads.com> wrote:
>I want to to have my die, the following does not work
"Does not work" is about the worst problem description imaginable.
Do you also walk into a garage and say just "My car doesn't work" and
expect the mechanic to fix whatever problem there is without even
telling him what the problem is?
You provided code, well, that's one step in the right direction.
But you should always also describe what you expected the code to do and
what behaviour you observed instead.
Without that the mechanic may fix the rattling ash tray without ever
noticing the leaking radiator simply because you didn't tell him about
it.
jue
------------------------------
Date: Thu, 21 Mar 2013 11:36:08 -0500
From: "J. Gleixner" <glex_no-spam@qwest-spam-no.invalid>
Subject: Re: die alias
Message-Id: <514b36f8$0$63191$815e3792@news.qwest.net>
On 03/21/13 10:38, George Bouras wrote:
> I want to to have my die, the following does not work
>
>
> use strict;
> use warnings;
> sub die;
>
> die "oups";
>
> sub die {
> print "There was a problem : $_[0]\n";
> }
You might find this useful:
http://www.effectiveperlprogramming.com/blog/1310
------------------------------
Date: Thu, 21 Mar 2013 16:58:37 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: die alias
Message-Id: <87ppys1ygy.fsf@sapphire.mobileactivedefense.com>
George Bouras <nospam.gravitalsun.noadsplease@hotmail.noads.com>
writes:
> I want to to have my die, the following does not work
>
>
> use strict;
> use warnings;
> sub die;
>
> die "oups";
>
> sub die {
> print "There was a problem : $_[0]\n";
> }
The short answer is
*CORE::GLOBAL::die = sub { print "There was a problem : $_[0]\n"; }
more details are in the CORE manpage ('perldoc CORE').
------------------------------
Date: Thu, 21 Mar 2013 17:06:43 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: die alias
Message-Id: <87hak41y3g.fsf@sapphire.mobileactivedefense.com>
Rainer Weikusat <rweikusat@mssgmbh.com> writes:
> George Bouras <nospam.gravitalsun.noadsplease@hotmail.noads.com>
> writes:
>> I want to to have my die, the following does not work
>>
>>
>> use strict;
>> use warnings;
>> sub die;
>>
>> die "oups";
>>
>> sub die {
>> print "There was a problem : $_[0]\n";
>> }
>
> The short answer is
>
BEGIN {
> *CORE::GLOBAL::die = sub { print "There was a problem : $_[0]\n"; }
}
------------------------------
Date: Thu, 21 Mar 2013 16:49:00 +0000
From: Justin C <justin.1303@purestblue.com>
Subject: Re: die alias
Message-Id: <s8qr1a-68i.ln1@zem.masonsmusic.co.uk>
On 2013-03-21, George Bouras <nospam.gravitalsun.noadsplease@hotmail.noads.com> wrote:
> I want to to have my die, the following does not work
>
>
> use strict;
> use warnings;
BEGIN {
*CORE::GLOBAL::die = sub {
print "There was a problem : $_[0]\n";
}
> die "oups";
But is it a good idea?
Justin.
--
Justin C, by the sea.
------------------------------
Date: Thu, 21 Mar 2013 18:15:24 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: die alias
Message-Id: <savr1a-6da2.ln1@anubis.morrow.me.uk>
Quoth George Bouras <nospam.gravitalsun.noadsplease@hotmail.noads.com>:
Please use a consistent posting identity. I already have a killfile
entry for
"George Mpouras" <nospam.gravitalsun.antispam@hotmail.com.nospam>
, I don't particularly want to have to create a whole lot more.
Ben
------------------------------
Date: Thu, 21 Mar 2013 11:54:19 -0700 (PDT)
From: "C.DeRykus" <derykus@gmail.com>
Subject: Re: die alias
Message-Id: <8e75c5da-4ddf-48b3-8ae1-93c3a1493be3@googlegroups.com>
On Thursday, March 21, 2013 8:38:52 AM UTC-7, George Bouras wrote:
> I want to to have my die, the following does not work
>
>
>
>
>
> use strict;
>
> use warnings;
>
> sub die;
>
>
>
> die "oups";
>
>
>
> sub die {
>
> print "There was a problem : $_[0]\n";
>
> }
Does "not work" refer to the warning:
Ambiguous call resolved as CORE::die(), qualify as such or use & at die.pl line 8.
oops at die.pl line 8.
Add 'use diagnostics' for further info.
--
Charles DeRykus
------------------------------
Date: Thu, 21 Mar 2013 21:23:25 +0200
From: "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Subject: Re: die alias
Message-Id: <kifmnd$29dk$1@news.ntua.gr>
I must also a print alias; the same method does not work.
#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
*CORE::GLOBAL::die = \&error;
*CORE::GLOBAL::print = \&NotifyAll
};
die "oups";
sub error { print "There was a problem : $_[0]" }
sub NotifyAll { CORE::print ">>$_[0]<<"; }
------------------------------
Date: Thu, 21 Mar 2013 21:27:42 +0200
From: "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Subject: Re: die alias
Message-Id: <kifmve$2ahd$1@news.ntua.gr>
There is no other way. It is a apache xml interface between different
systems , where some existing 3rd party code must wraped and run as it is to
send back messages
------------------------------
Date: Thu, 21 Mar 2013 19:45:16 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: die alias
Message-Id: <cj4s1a-08b2.ln1@anubis.morrow.me.uk>
Quoth Justin C <justin.1303@purestblue.com>:
> On 2013-03-21, George Bouras
> <nospam.gravitalsun.noadsplease@hotmail.noads.com> wrote:
> > I want to to have my die, the following does not work
> >
> >
> > use strict;
> > use warnings;
>
> BEGIN {
> *CORE::GLOBAL::die = sub {
> print "There was a problem : $_[0]\n";
> }
For the problem as posted, there's no need to go as far as CORE::GLOBAL,
you just need to import &die from some other package. use subs is
sufficient for this, and the OP's code as posted works as expected for
me.
If you *are* going to override CORE::GLOBAL, you need to make sure you
do so before the code which should use the new definition is compiled.
You should probably also arrange to compile this code in the scope of a
'local *CORE::GLOBAL::die', so as not to affect other code.
For the specific case of die, a slightly cleaner hook is $SIG{__DIE__},
which can at least be localised at runtime. Make sure you read the
warning in perlvar about __DIE__ being called for parse errors, and at
least check defined($^S) before doing anything.
Ben
------------------------------
Date: Thu, 21 Mar 2013 22:24:33 +0200
From: "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Subject: Re: die alias
Message-Id: <kifqa1$2ott$1@news.ntua.gr>
> BEGIN { *CORE::GLOBAL::die = sub { ... } };
is great, can we make it work with print also ?
------------------------------
Date: Thu, 21 Mar 2013 14:53:33 -0700
From: Keith Keller <kkeller-usenet@wombat.san-francisco.ca.us>
Subject: Re: die alias
Message-Id: <t3cs1ax7kn.ln2@goaway.wombat.san-francisco.ca.us>
On 2013-03-21, George Mpouras <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam> wrote:
> There is no other way.
Whenever I think this is true, I usually stop for a moment and try to
figure out whether it's actually true. It almost always ends up false.
In this case, did you look into $SIG{__DIE__} as others have suggested?
perldoc -f die and perldoc perlvar (search for __DIE__) for details.
--keith
--
kkeller-usenet@wombat.san-francisco.ca.us
(try just my userid to email me)
AOLSFAQ=http://www.therockgarden.ca/aolsfaq.txt
see X- headers for PGP signature information
------------------------------
Date: Fri, 22 Mar 2013 00:01:21 +0200
From: "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Subject: Re: die alias
Message-Id: <kifvvh$geg$1@news.ntua.gr>
perldoc -f die and perldoc perlvar (search for __DIE__) for details.
die is solved . Now I have to solve the print alias
------------------------------
Date: Thu, 21 Mar 2013 23:17:17 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: die alias
Message-Id: <t0hs1a-1id2.ln1@anubis.morrow.me.uk>
Quoth "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>:
> I must also a print alias; the same method does not work.
>
>
> #!/usr/bin/perl
> use strict;
> use warnings;
>
> BEGIN {
> *CORE::GLOBAL::die = \&error;
> *CORE::GLOBAL::print = \&NotifyAll
> };
>
> die "oups";
>
> sub error { print "There was a problem : $_[0]" }
> sub NotifyAll { CORE::print ">>$_[0]<<"; }
CORE::GLOBAL only works for some builtins. print is not one of them,
because it has special syntax.
You can sometimes hijack print by selecting a tied filehandle, or by
tying STDOUT, depending on where the code you are calling prints to.
Ben
------------------------------
Date: Fri, 22 Mar 2013 01:29:39 +0200
From: "George Mpouras" <nospam.gravitalsun.antispam@spamno.hotmail.anispam.com.nospam>
Subject: Re: die alias
Message-Id: <kig552$154s$1@news.ntua.gr>
dead end here
------------------------------
Date: Thu, 21 Mar 2013 18:39:54 -0500
From: "J. Gleixner" <glex_no-spam@qwest-spam-no.invalid>
Subject: Re: die alias
Message-Id: <514b9a4a$0$75663$815e3792@news.qwest.net>
On 03/21/13 17:01, George Mpouras wrote:
> perldoc -f die and perldoc perlvar (search for __DIE__) for details.
>
> die is solved . Now I have to solve the print alias
How many times are you going to post that?? Once is enough...
http://lmgtfy.com/?q=perl+override+print
I didn't really read about Devel::UncheckedOps because I'd never go that
route.
But seriously, it's going way beyond *normal* to go this route. Maybe a
search/replace of 'print' to 'my_print' or something simple like that
is enough.
------------------------------
Date: Thu, 21 Mar 2013 21:31:59 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Object attribute representation [was: a trival array/ hash benchmark]
Message-Id: <fras1a-7dc2.ln1@anubis.morrow.me.uk>
Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> Rainer Weikusat <rweikusat@mssgmbh.com> writes:
> > Ben Morrow <ben@morrow.me.uk> writes:
> >> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>
> >>> -----------
> >>> use Benchmark;
> >>>
> >>> my $h = { Worschtsupp => 4 };
> >>> my $a = [4];
> >>>
> >>> timethese(-5,
> >>> {
> >>> h => sub { return $h->{Worschtsupp}; },
> >>> a => sub { return $a->[0]; }});
> >>> ------------
>
> >> Like most microbenchmarks, this tells you very little about real code.
> >> Try something a bit more realistic, like
> [...]
> >> the method-call overhead completely dominates the
> >> overhead of the hash lookup. If you can save one method call, you will
> >> save more time than you would have saved by using an arrayref;
> >
> > Putting this in another way: The overhead of decoupling the so-called
> > 'classs methods' from 'the object representation' with a layer of
> > 'more privileged core class methods' aka 'accessors' is so high that
> > the actual representation doesn't matter anymore which means that the
> > theoretical benefit of that ('the representation could be changed
> > without affecting the 'set of general-purpose subroutines needlessly
> > tied to the so-called class) isn't worthwhile: The cure is worse than
> > the disease.
>
> Two things which kept bothering me about this:
>
> 1. My statement above is a little disingenious in this context: The
> method call overhead is higher and the 'The cure ...' is - at best -
> an attempt to change the topic of the converstation and - at worst -
> some piece of not that easily discardable nonsense (both
> intentionally).
Apology accepted.
> 2. The 'Like most ...' statement is wrong: The example code I gave
> should be identical to the code in a typical 'getter' method.
That's not the point, though. The interesting question is not 'Are array
derefs faster than hash derefs?': everyone already knows they are. The
interesting questions are 'How much difference would it make to the
overall performance of my application if I switched from hashref to
arrayref objects?' and 'Does that make it worth putting up with the
limitations of arrayref objects?'. My benchmark suggests the answer to
the first is 'maybe 2 or 3%, for an app which is CPU-bound rather than
IO-bound'; and unless the answer to the first was something huge, like a
50x speed increase, my answer to the second would be an unqualified
'No'.
Of course, *if* someone were to produce a system for building arrayref
objects which *didn't* place any limits on their flexibility, I would
take the speed increase no matter how small. This is why, throughout
this conversation, I have only been interested in complete solutions: so
far, AFAIC, the potential benefits of arrayref objects (a negligible
speed increase and an as-yet-undetermined memory decrease) aren't
sufficient to outweigh even a minor disadvantage, so I'm not interested
in the idea unless it can be implemented without limitations.
To change the subject a little back to something more interesting,
here's a sketch of an idea I was playing with a while ago for a
completely different way of representing attributes. It provides as-
cheap-as-possible attribute access, automatic and transparent allocation
of slots in the underlying arrays, complete encapsulation of the
attributes from code outside the class, and entirely avoids the problem
of attribute collisions with methods defined in other classes. It can
also be relatively easily extended to provide, among other things,
proper separation of class and object methods, roles, and runtime role
application to instances without needing to create 'anonymous' classes.
Note that this is just a sketch: I've simplified it a great deal, and I
don't know that this version still works properly.
package Object::Closures;
use Carp;
my @EXPORT = qw/BUILD self construct method inherit/;
sub import {
my $to = caller;
no strict "refs";
@{"$to\::ISA"} = "Object::Closures::Class";
*{"$to\::$_"} = \&$_ for @EXPORT;
namespace::clean->import(-cleanee => $to);
}
my %BUILD;
sub BUILD (&) { $BUILD{+caller} = $_[0] }
our $SELF;
sub self { $SELF }
sub construct {
my ($class, @args) = @_;
local $SELF = bless {}, $class;
$BUILD{$class}(@args);
$SELF;
}
sub method {
my ($meth, $cv) = @_;
$SELF->{$meth} = $cv;
}
sub inherit {
my ($parent, @args) = @_;
$BUILD{$parent}(@_);
}
package Object::Closures::Class;
require Carp;
our $AUTOLOAD;
sub AUTOLOAD {
my ($self, @args) = @_;
$AUTOLOAD =~ s/.*:://;
my $meth = $self->{$AUTOLOAD} or croak "No such method";
local $SELF = $self;
$meth->(@args);
}
It's used like this:
package Foo;
use Object::Closures;
BUILD {
my $att = $_[0];
method get_att => sub { $att };
method set_att => sub { $att = $_[0] };
};
sub new { construct @_ }
The most important disadvantages are that it makes method calls even
more expensive, and that with this sort of dispatch-hijacking it's
harder than it seems to get the UNIVERSAL methods to behave properly.
(You will notice I haven't included any implementation of them here.)
This is one of the reasons I was interested when the question of making
it possible to hijack mathod dispatch in a more straightforward way came
up on p5p.
Ben
------------------------------
Date: Thu, 21 Mar 2013 23:30:46 +0000
From: Rainer Weikusat <rweikusat@mssgmbh.com>
Subject: Re: Object attribute representation
Message-Id: <87a9pwz5y1.fsf@sapphire.mobileactivedefense.com>
Ben Morrow <ben@morrow.me.uk> writes:
> Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
[...]
>> 2. The 'Like most ...' statement is wrong: The example code I gave
>> should be identical to the code in a typical 'getter' method.
>
> That's not the point, though. The interesting question is not 'Are array
> derefs faster than hash derefs?': everyone already knows they are. The
> interesting questions are 'How much difference would it make to the
> overall performance of my application if I switched from hashref to
> arrayref objects?' and 'Does that make it worth putting up with the
> limitations of arrayref objects?'. My benchmark suggests the answer to
> the first is 'maybe 2 or 3%, for an app which is CPU-bound rather than
> IO-bound'; and unless the answer to the first was something huge, like a
> 50x speed increase, my answer to the second would be an unqualified
> 'No'.
This 'overall performance' idea is too simplistic. Eg, assume the
application is a server whose purpose is to make 'policy descisions'
for HTTP requests, that is, deny or allow them based on 'some
criterion' like 'URL black- or whitelisted' or 'classified as
belonging to a page of content-category ...'. Ideally, 'making the
policy descision shouldn't add any noticeably latency to requests AND
the measurable latency should be so small that it is possible to point
people at the fact that this can't be causing their 'internet
performance problems' even despite they suspect otherwise (which they
are going to do). Also, the descision really shouldn't add any latency
because only one such question can be processed at any given time and
this then becomes a question of 'how many requests can be processed per
second', considering that adding a latency of 1s is WAY too much. In
addition, all of this may need to run on relatively low-spec (that
is, cheap to mass-produce, hardware) and people are going to expect
that it will support at least a couple of thousands of concurrent
users (this is not a contrived example).
Taking this into account, what is more worthwhile? Using
datastructures with minimally faster access times (and less memory
requirements) or 'genuflecting before the god of code bumming', that
is "de-structuring the code" by 'inlining everything which can
conceivably be inlined'. Do I rather put up with the perceived
limitations of the former in order to avoid the latter for as long as
humanly possible, ie, am I willing to make a concsious effort to avoid
wasteing time on stuff where 'wasting time' doesn't buy me anything so
that I can afford to waste time on stuff where it does by me
something?
In line with this reflection, using anonymous arrays also enables
creating objects which retain direct access to their properties
without ad hoc hackery like
use constant NAME => __PACKAGE__.'name';
$h->{+NAME} = ...
because, just like structures in C, arrays provide an ordered set of
slots which means that something like 'use the next five free slots'
is possible which can't be done with hashes in a straight-forward way.
> Of course, *if* someone were to produce a system for building arrayref
> objects which *didn't* place any limits on their flexibility,
The idea to use anonymous arrays in order to enable 'nested superclass
attributes' is inherently limited to single-inheritance data
inheritance. This implies that everything which can be done in Java
can be done in this way in Perl, too, and even easier because
contortions like 'interfaces' aren't needed. Considering that this
language isn't entirely unused, discarding single-inheritance out of
hand as 'not good enough for me' seems a little preposterous. And -
since Perl isn't a "one size for all and users are fitted to it as
necessary" - the option to use other object representation where it
actually matters is always available.
[...]
> To change the subject a little back to something more interesting,
> here's a sketch of an idea I was playing with a while ago for a
> completely different way of representing attributes.
[...]
> package Foo;
> use Object::Closures;
>
> BUILD {
> my $att = $_[0];
>
> method get_att => sub { $att };
> method set_att => sub { $att = $_[0] };
> };
>
> sub new { construct @_ }
>
> The most important disadvantages are that it makes method calls even
> more expensive,
According to some text I read on the web some
years ago[*], the main problem with this is that every object uses
two additional lexical pads for each of its attributes in this way.
[*] Unfortunately, I can't quote this here because doing so would
seriously upset 'certain people' who prefer keeping their heads firmly
dug into the sand wrt what is or isn't available for free on the
internet (this means they claim that this 'free availability' would
be a serious problems but - for some reason - they don't consider it
worthwhile to do something against it ...).
------------------------------
Date: Fri, 22 Mar 2013 01:02:56 +0000
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: Object attribute representation
Message-Id: <07ns1a-bbf2.ln1@anubis.morrow.me.uk>
Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
> Ben Morrow <ben@morrow.me.uk> writes:
> > Quoth Rainer Weikusat <rweikusat@mssgmbh.com>:
>
> >> 2. The 'Like most ...' statement is wrong: The example code I gave
> >> should be identical to the code in a typical 'getter' method.
> >
> > That's not the point, though. The interesting question is not 'Are array
> > derefs faster than hash derefs?': everyone already knows they are. The
> > interesting questions are 'How much difference would it make to the
> > overall performance of my application if I switched from hashref to
> > arrayref objects?' and 'Does that make it worth putting up with the
> > limitations of arrayref objects?'. My benchmark suggests the answer to
> > the first is 'maybe 2 or 3%, for an app which is CPU-bound rather than
> > IO-bound'; and unless the answer to the first was something huge, like a
> > 50x speed increase, my answer to the second would be an unqualified
> > 'No'.
>
> This 'overall performance' idea is too simplistic. Eg, assume the
> application is a server whose purpose is to make 'policy descisions'
> for HTTP requests, that is, deny or allow them based on 'some
> criterion' like 'URL black- or whitelisted' or 'classified as
> belonging to a page of content-category ...'. Ideally, 'making the
> policy descision shouldn't add any noticeably latency to requests AND
> the measurable latency should be so small that it is possible to point
> people at the fact that this can't be causing their 'internet
> performance problems' even despite they suspect otherwise (which they
> are going to do). Also, the descision really shouldn't add any latency
> because only one such question can be processed at any given time
Why? That seems like bad design, especially if the policy requires any
IO or network activity to make its decision.
> and
> this then becomes a question of 'how many requests can be processed per
> second', considering that adding a latency of 1s is WAY too much. In
> addition, all of this may need to run on relatively low-spec (that
> is, cheap to mass-produce, hardware) and people are going to expect
> that it will support at least a couple of thousands of concurrent
> users (this is not a contrived example).
If the question is 'how many requests can be processed per second' then
overall performance is, in fact, all that matters. If using arrayrefs
won't increase that number significantly (or at all, as is likely if the
app does any IO to make its decision), while inlining one or two methods
on the critical path, or adding a cache somewhere, or using one of the
CPAN HTTP proxy modules which parse the header in XS will, then
obviously you should do the latter.
Of course, if you have profiled your app (not always easy, but it can be
done; Devel::NYTProf is a good module for this) and found that it spends
most of its time doing attribute lookups, and there is no sensible way
to reduce the number of attribute lookups on the critical path by
changing the algorithm, it might be worth using arrayrefs. I just don't
think that's very likely to be the case.
> Taking this into account, what is more worthwhile? Using
> datastructures with minimally faster access times (and less memory
> requirements) or 'genuflecting before the god of code bumming', that
> is "de-structuring the code" by 'inlining everything which can
> conceivably be inlined'.
Inlining everything would be stupid. I already said that under normal
circumstances I wouldn't hesitate to split a method if it made the code
cleaner or more flexible. Inlining one or two methods, when you've
determined (by measurement) that will make a significant difference to
performance, is often sensible.
> Do I rather put up with the perceived
> limitations of the former in order to avoid the latter for as long as
> humanly possible, ie, am I willing to make a concsious effort to avoid
> wasteing time on stuff where 'wasting time' doesn't buy me anything so
> that I can afford to waste time on stuff where it does by me
> something?
They are not 'perceived' limitations, they are actual limitations. If
you don't find them a problem, then by all means use arrayrefs; noone is
trying to stop you. I do find them a problem in non-trivial cases, so I
shall continue to avoid them in those cases, unless I see a general
solution which avoids the limitations.
> In line with this reflection, using anonymous arrays also enables
> creating objects which retain direct access to their properties
> without ad hoc hackery like
>
> use constant NAME => __PACKAGE__.'name';
>
> $h->{+NAME} = ...
>
> because, just like structures in C, arrays provide an ordered set of
> slots which means that something like 'use the next five free slots'
> is possible which can't be done with hashes in a straight-forward way.
I don't understand this comment. Anything which can be stored in an
array can be stored in a hash, unless preserving the order of insertion
is important, which it isn't in this case. You are using an array as a
map from integers to values rather than as a frozen list; this alone
would be enough to suggest to me that perhaps you should be using a hash
instead.
> > Of course, *if* someone were to produce a system for building arrayref
> > objects which *didn't* place any limits on their flexibility,
>
> The idea to use anonymous arrays in order to enable 'nested superclass
> attributes' is inherently limited to single-inheritance data
> inheritance.
I don't consider single inheritance (without roles) to be worth having
for non-trivial cases, even just for attributes. Roles which add an
attribute or two and a few methods to manipulate them are a very useful
way to factor out functionality I want to use in several classes.
> This implies that everything which can be done in Java
> can be done in this way in Perl, too, and even easier because
> contortions like 'interfaces' aren't needed. Considering that this
> language isn't entirely unused, discarding single-inheritance out of
> hand as 'not good enough for me' seems a little preposterous.
This is the 'argumentum ad populum' you are so fond of accusing me of. I
don't care what Java can or cannot do; I don't use Java, because I
consider it a grotesquely limited and ugly language.
> And - since Perl isn't a "one size for all and users are fitted to it
> as necessary" - the option to use other object representation where it
> actually matters is always available.
Yes. So why are you arguing so strongly in favour of arrayrefs? They can
be used when they are useful; IMHO most of the time they are not; if you
disagree, that's fine, you go ahead and use them. Where's the problem?
> > To change the subject a little back to something more interesting,
> > here's a sketch of an idea I was playing with a while ago for a
> > completely different way of representing attributes.
>
> [...]
>
> > package Foo;
> > use Object::Closures;
> >
> > BUILD {
> > my $att = $_[0];
> >
> > method get_att => sub { $att };
> > method set_att => sub { $att = $_[0] };
> > };
> >
> > sub new { construct @_ }
> >
> > The most important disadvantages are that it makes method calls even
> > more expensive,
>
> According to some text I read on the web some
> years ago[*], the main problem with this is that every object uses
> two additional lexical pads for each of its attributes in this way.
Yes, there is a space cost as well as a performance cost; specifically
one CV per object per method, and one SV per object per method per
attribute-used-by-that-method. This is not a great deal; note that the
attributes are not copied into the pads, they are aliased, so there's no
duplication of the actual attribute values.
My main interest in this method was that it makes attributes available as
lexicals directly, which is much more convenient than either a method
call or a deref, and that it completely avoids the problem of attribute
conflicts between packages.
> [*] Unfortunately, I can't quote this here because doing so would
> seriously upset 'certain people' who prefer keeping their heads firmly
> dug into the sand wrt what is or isn't available for free on the
> internet (this means they claim that this 'free availability' would
> be a serious problems but - for some reason - they don't consider it
> worthwhile to do something against it ...).
Ummm...
a. Who, exactly, do you think cares about this little rant?
b. You don't need to quote anything, I already know how pads and
closures work.
c. If you do feel the need to back up your explanation, you can
always quote pad.c.
Ben
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V11 Issue 3907
***************************************