use threads;
the overload.pm gets loaded just for the event that you _might_ want to
compare two thread objects with "==".
This is one of the few cases where I couldn't run the
Benchmark::Thread::Size directly, so I ran it twice: the first with a
standard "threads.pm", the second time with the following lines removed
from threads.pm:
use overload
'==' => \&equal,
'fallback' => 1;
The benchmark shows:
# (release)
0 2171 Ä… 4
1 2631 Ä… 4
2 3000
5 4126 Ä… 6
10 5979 Ä… 6
20 9695 Ä… 4
50 20836 Ä… 6
100 39392 Ä…10
# (without overload.pm)
0 2112
1 2543 Ä… 4
2 2888
5 3924 Ä… 4
10 5674 Ä… 4
20 9156 Ä… 4
50 19596 Ä… 4
100 36994 Ä…10
or in other words: 60K less memory (almost 3%) without any additional
threads running, going up to 2398K less memory (more than 6%) with 100
threads running.
I would propose that the "==" functionality be removed from
threads.pm. Personally, I've never felt the need to be comparing threads
objects in the past 3 months that I have been programming perl threads
(rather heavily, I might add).
Liz
I'm confused why the overload is needed at all; how do you get two
different objects with the same tid in the first place?
Hugo
use threads;
my $thread = threads->new( sub {} );
my $thread2 = $thread;
print "Equal!\n" if $thread == $thread2;
Whether this makes sense, I don't know. Maybe Arthur can enlighten us?
Liz
Moin,
Liz wrote:
Yeah, but why do you need overload for this?
te@null:~> perl equal.pl
Equal!
te@null:~> cat equal.pl
package threads;
sub new
{
my $class = shift;
return bless {}, $class;
}
package main;
my $thread = threads->new( sub {} );
my $thread2 = $thread;
print "Equal!\n" if $thread == $thread2;
te@null:~>
HTH,
Tels
- --
perl -MMath::String -e 'print \
Math::String->from_number("215960156869840440586892398248"),"\n"'
http://bloodgate.com/perl My current Perl projects
PGP key available on http://bloodgate.com/tels.asc or via email.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl.
iQEVAwUBPZImK3cLPEOTuEwVAQF6gQf+PKMJgSApZAl5lgv5KBrl10QooRb2epoZ
s8R5bJIBBS4EuFTAP7txkzEINKW5GpXcM3640Au+WAmVOAObd3kdUc6vXqtYNENS
1JzlMfmchIjmzqIM9w6P+Lz1kRocyFuNphcxb/OZhw3QQe9WdtQKe/7BNXtspX8M
CHFtfmc0vFQsFtdSWyo6pwKwY4zvZl3vqFaN1me9EVhMrgDuS5rdkeZ1J9FfluCu
TJ8YAuVt1zX1VrgiHjEn4igHXuUSpd0J3ggIXcMfr99f7mkUe5rU+qZ54Fzdd7Oh
Q5fmcsn92xIdXpjLOe/vnwAGFABhZdHPv+8scwk7J1eCgOal3RiDSA==
=AXvl
-----END PGP SIGNATURE-----
Because then you're comparing the stringifications of the string objects in
numeric context. Which is always true.
$ perl -e 'print "Equal!\n" if "a" == "b"'
Equal!
Maybe the overload is more intended to check for inequality?
use threads;
my $thread1 = threads->new( sub {} );
my $thread2 = $thread1;
my $thread3 = threads->new( sub {} );
print "$thread1 $thread2 $thread3\n";
print "1 == 2: Equal!\n" if $thread1 == $thread2;
print "1 != 3: Not Equal!\n" if $thread1 != $thread3;
But indeed, the more I think about it, the more it makes sense to me to
remove the overload.pm dependency in threads.pm.
Liz
References numify to their addresses. (you may not have been aware of this)
perl -le 'print \$a == \$b; print \$a == \$a'
1
So if the thread objects don't have any overloading then they should behave
nicely with == (and friends).
[I don't know enough about overloading to know what happens if you have an
object with stringify overloaded but not numify]
Nicholas Clark
--
Even better than the real thing: http://nms-cgi.sourceforge.net/
Numification is then implemented in terms of stringification. (And
becomes useless, because you're back to the "a"+0; case).
This is buried deep inside the overload magic, and there's not much
that can be done about it.
-R
Yup; as I see it, this'll work except if there is some way to get two
objects with distinct storage addresses but the same tid. I don't see
one offhand (short of an encapsulation-breaking C< my $t2 = bless {
%$t1 }, ref $t1 >, which I'm perfectly happy to break), hence my
question.
Arthur, any thoughts on this? The question is whether there is some way
to get two threads.pm objects with different addresses but the same tid.
If not, I don't see any reason why the '==' overload is needed.
Hugo
Hmm... what about:
my @thr = threads->list;
my $slf = threads->self;
Will the same *objects* be returned from these?
Or different objects refering to the same threads?
--
Announcement in the Zoo:
"Please don't scare the ostriches! Cement floor!"
If you remove those lines, what happens when you do:
print 0+(threads->self() == threads->self());
?
Does ->self always return the same object, or does it return a new
object each time, but with the same thread id?
[snip]
> or in other words: 60K less memory (almost 3%) without any additional
> threads running, going up to 2398K less memory (more than 6%) with 100
> threads running.
>
> I would propose that the "==" functionality be removed from
> threads.pm.
Or at least, don't use overload.pm for it.
I think that it *might* be worth breaking the encapsulation that
overload.pm provides to do what it does ourself, directly...
That is, replace the 'use overload ....' with equivilant code:
BEGIN {
# by touching the %OVERLOAD hash, the next time an object is
# blessed into this class, our overload magic will be updated.
$OVERLOAD{dummy}++;
# Perl tests for the presence of overloading on a package by
# doing $package->can('()').
*{"()"} = \&overload::nil;
# The purpose of this line should be obvious :)
*{"(=="} = \&equal;
# This is what fallback => 1 does.
${"()"} = 1;
}
[note that &overload::nil merely a sentinel, it's not ever actually
called; there's no need to load overload.pm to get it's body.]
This will of course use a few more bytes than leaving it out, and *lots*
fewer bytes than loading up all of overload.pm.
Because threads.pm and overload.pm are both in perl's core, we can add
comments to both modules telling ourselves that if the implementation of
overloading ever changes, we need to change the few lines inside of
threads.pm, which depends on the old behavior.
> Personally, I've never felt the need to be comparing threads
> objects in the past 3 months that I have been programming perl threads
> (rather heavily, I might add).
Have you ever used any of the following:
threads->object( id ); # for any purpose whatsoever
threads->self; # for some purpose other than detaching yourself.
threads->list; # for some purpose other than joining all threads.
?
If not, does that mean that they are useless?
PS: Does anyone know a reason why detaching a thread is a seperate step
from creating it? Wouldn't it have made more sense to have a method
like threads->create_detached(...), instead?
Indeed, they are never the same (see previous response)...
> > I would propose that the "==" functionality be removed from
> > threads.pm.
>Or at least, don't use overload.pm for it.
>I think that it *might* be worth breaking the encapsulation that
>overload.pm provides to do what it does ourself, directly...
>That is, replace the 'use overload ....' with equivilant code:
> BEGIN {
I needed to add a "no strict;" here to get it to compile and execute...
> # by touching the %OVERLOAD hash, the next time an object is
> # blessed into this class, our overload magic will be updated.
> $OVERLOAD{dummy}++;
> # Perl tests for the presence of overloading on a package by
> # doing $package->can('()').
> *{"()"} = \&overload::nil;
> # The purpose of this line should be obvious :)
> *{"(=="} = \&equal;
> # This is what fallback => 1 does.
> ${"()"} = 1;
> }
>[note that &overload::nil merely a sentinel, it's not ever actually
>called; there's no need to load overload.pm to get it's body.]
>
>This will of course use a few more bytes than leaving it out, and *lots*
>fewer bytes than loading up all of overload.pm.
threads->self == threads->self doesn't work with your patch... ;-( Since
this magic is way over my head, I can't even begin to give you a clue why
not...
>Have you ever used any of the following:
> threads->object( id ); # for any purpose whatsoever
> threads->self; # for some purpose other than detaching yourself.
> threads->list; # for some purpose other than joining all threads.
>?
>If not, does that mean that they are useless?
I have used all three of them extensively (just search for Thread:: on
CPAN...) It's just that I've never felt the need to compare thread
objects at all. I assume my reason for this is that you cannot share
thread objects, i.e. you cannot put a thread object in a shared variable:
use threads;
use threads::shared;
my $shared : shared = threads->self;
gives you:
Invalid value for shared scalar at foo line 3.
So, if you need other threads to be aware of a specific (monitoring)
thread, you can only share its tid.
use threads;
use threads::shared;
my $shared : shared = threads->tid;
(no problem)
Tids are easy to compare, so once you have them, there is no point turning
them into objects before comparing. Which is probably why I've never run
into it...
>PS: Does anyone know a reason why detaching a thread is a seperate step
>from creating it? Wouldn't it have made more sense to have a method
>like threads->create_detached(...), instead?
With the current way, you can have a parent thread decide to detach one of
its children, or have the child thread deteach itself when it wants. From
experience I found however that you hardly ever want to detach a thread:
you lose all control over it so a guaranteed clean shutdown becomes almost
impossible (because of thread inertia issues).
Liz
Hit the nail on the head there:
============================================================
use threads;
threads->new( sub { sleep( 86400 ) } ) foreach 1..3;
my @thread = threads->list;
my @thread2 = threads->list;
print "@thread\n@thread2\n";
<>;
============================================================
prints:
threads=SCALAR(0x8125fb8) threads=SCALAR(0x8125df0) threads=SCALAR(0x81bec48)
threads=SCALAR(0x8125ed4) threads=SCALAR(0x81bec78) threads=SCALAR(0x81bec90)
So yes, threads->list is returning different objects with the same
tid. Which explains why the overload is there.
Liz
I was at one point, a few months ago when I was seeing large numbers appear
where they shouldn't (turned out to be numified threads objects). Thanks
for the reminder. And Tels, sorry for the incorrect correction...
Liz
Moin,
On 26-Sep-02 Elizabeth Mattijsen carved into stone:
You are welcome. I should have put up a better explanation and an unequal
example, too. Don't worry, me too didn't know about references in numerical
context not long ago...
Cheers,
Tels
- --
perl -MDev::Bollocks -le'print Dev::Bollocks->rand()'
carefully optimize end-to-end content
http://bloodgate.com/perl My current Perl projects
PGP key available on http://bloodgate.com/tels.asc or via email
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl.
iQEVAwUBPZLaKXcLPEOTuEwVAQE/LQf+K+SPVztGBhAOTj2iK1enczYJPWKpYLc1
kUNhSrMc28X0Z7nK6sFFfqP2p8HBADlUYaOEWq972LUbyNn3Uxj7VO7+FNM4MEhT
bdyAxA9hpz6fCsU+rqfUQeAhq5ZxN6rSh/0e0NFmegkDSB1qcQ8Qs7j2bOLVJonC
8t5oI/v6CVv7s5MlL49FRo+gKmjlW0x8inMRx2chS/ic1yt1lU+kLKYo+sz394eF
Rs/qXfF5RezVmPjhf8HBpbDgz0BnpyHZ4cpny+aYjnpRKU99rYQO2+RY3yl8R8zm
DfKLv34L6JDmyI2M6HD2LCR37ISCEUEl1gZ2dV0Lirz8/y07bE1KLw==
=7A8/
-----END PGP SIGNATURE-----
Moin,
At 10:02 PM 9/25/02 -0400, Benjamin Goldberg wrote:
>h...@crypt.org wrote:
>>
>> Elizabeth Mattijsen <l...@dijkmat.nl> wrote:
>> :Being able to compare two thread objects with "==" (rather than by
>> :using the "equal" method), is _very_ wasteful with regards to memory.
>> :Since threads.pm is the _only_ module that uses overload.pm, if
>> :you're just doing
>> :
>> : use threads;
>> :
>> :the overload.pm gets loaded just for the event that you _might_ want
>> :to compare two thread objects with "==".
>>
>> I'm confused why the overload is needed at all; how do you get two
>> different objects with the same tid in the first place?
>
>Hmm... what about:
> my @thr = threads->list;
> my $slf = threads->self;
>Will the same *objects* be returned from these?
>Or different objects refering to the same threads?
>
Liz wrote:
>So yes, threads->list is returning different objects with the same
>tid. Which explains why the overload is there.
In Math::BigInt, I had some similiar situation like:
$y = $x->bmod(5);
And afterwards $x and $y were pointing to different objects, with different
values.
So, you should ask yourself (sorry, no experience with threads at all)
whether ->list() and ->self() *should* return the same reference or a
different one pointing to the same object.
In my past experience, returning a different reference to the same object
(or even a different object) was always a bug :-)
If you can change this, you can get rid of overload.pm, which is much more
simple as adding "hacks" at the top of threads.pm. I would vote against the
latter, instead look for other easier ways to preservere memory (you are on
the right track though!). The reason is that these hacks only can add bugs
and problems later on, and probably nobody will understand the hack later
on, even with the (cryptic) comments. I mean, if we are puzzled why an
overload statement is there, what will future maintainers think of the
"16-lines-magic-hack"?
Just my 0.02 Euro,
Tels
- --
Announcement in the Zoo:
"Please don't scare the ostriches! Cement floor!"
- --
perl -MMath::String -e 'print \
Math::String->from_number("215960156869840440586892398248"),"\n"'
http://bloodgate.com/perl My current Perl projects
PGP key available on http://bloodgate.com/tels.asc or via email.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl.
iQEVAwUBPZLceHcLPEOTuEwVAQHu/wf8CH0RIBInoigwHeqg+s+m/1/gkAsrR6mL
iHgkIcLuGxZx5YzaSDr50aXRF4osmr/+RhTaLbGF3QvqD/9V+y5hQ6mothL1exo7
RMofUZwylEn2KldgZUlkaeY1Lq2yEwG0fBsF4zY8oTjEyf9eJV5Do3+twR3viYIW
8+SnGXJZqZ4DBXtFQnewnzxdbP/JacJyteV4iuWMmCL0SjydJE8e5wmhzmm2+2UL
tbvGZi+cNcnxyszs0ywrnw8WZLeZ1punuvx2krto6f9DYyUV0//QKyMCBGAJLE0R
kywtZUtkROuNaP7nlsutVbHUKzLg6Zkgp7nNM5clahK2GmEH0AOX3A==
=p8EM
-----END PGP SIGNATURE-----
Well, you would expect that ->self at least would always return the same
object, within the same thread of course. And the odd thing is that it is
not that difficult in threads to do: a package lexical (inside threads.pm)
would do the trick. The CLONE subroutine should reset it and the ->self
method would set it if it was not set yet. Something like
my $self;
sub CLONE { undef( $self ) }
sub self { $self ||= shift->(old self method) }
I use this technique already quite frequently for the tid of a thread.
>In my past experience, returning a different reference to the same object
>(or even a different object) was always a bug :-)
I wonder what the rationale was behind this. Maybe Arthur or Nick I-S
remember?
>If you can change this, you can get rid of overload.pm, which is much more
>simple as adding "hacks" at the top of threads.pm. I would vote against the
>latter, instead look for other easier ways to preservere memory (you are on
>the right track though!). The reason is that these hacks only can add bugs
>and problems later on, and probably nobody will understand the hack later
>on, even with the (cryptic) comments. I mean, if we are puzzled why an
>overload statement is there, what will future maintainers think of the
>"16-lines-magic-hack"?
I would agree, normally. But since threads.pm and threads::shared.pm are
_so_ very important for the memory usage of threads in general, I think I
could live with a 16 line magic hack, at least until we can come up with
something better.
Liz
Didn't you read the invisible text saying [untested]? :)
Hmm, lemon juice works as invisible ink, but how do you make invisible
bits? :)
> Since this magic is way over my head, I can't even begin to give you a
> clue why not...
I'm looking at the source code of overload.pm in 5.6.1 (I don't have
5.8.0 installed on my machine)... The code in the BEGIN block does
exactly the same thing as overload::OVERLOAD() does. I don't see why it
doesn't work.
[snip]
> >PS: Does anyone know a reason why detaching a thread is a seperate
> >step from creating it? Wouldn't it have made more sense to have a
> >method like threads->create_detached(...), instead?
>
> With the current way, you can have a parent thread decide to detach
> one of its children, or have the child thread deteach itself when it
> wants.
Sure, but how often does a "decision" really need to be made? Usually,
you either detach right after creating a thread, or you don't detach it
at all. I've never seen a program where a thread was created, and some
arbitrary time afterwards was a decision to detach or not made.
> From experience I found however that you hardly ever want to detach a
> thread: you lose all control over it so a guaranteed clean shutdown
> becomes almost impossible (because of thread inertia issues).
Yes, generally you only detach a thread where you don't *need* clean
shutdown -- eg, suppose that have a thread which prints somethine like
"still running ".localtime()."\n" to a logfile every minute... there's
no need to shut it down cleanly; it just dies when the program dies.
It can happen that you have two different thread objects that point to
the same tid, mainly because you can get at thread objects from
different threads and then pass threads to each other.
use threads;
my $thread = threads->new(sub {});
threads->new(
sub { for(threads->list) {
print "The same\n" if($_[0] == $_) }
}, $thread)->join();
$thread->join();
That won't work without overloading.
Ofcourse we could force the user to to $_[0]->equals($_), or something
else.
However I think that most perl programs will end up using the overload
module anyway so the savings isn't that big. (Many modules use
overload).
Arthur
Like this:
> > Since this magic is way over my head, I can't even begin to give you a
> > clue why not...
>I'm looking at the source code of overload.pm in 5.6.1 (I don't have
>5.8.0 installed on my machine)... The code in the BEGIN block does
>exactly the same thing as overload::OVERLOAD() does. I don't see why it
>doesn't work.
Ok, I'll have a stab at it myself some more.
> > With the current way, you can have a parent thread decide to detach
> > one of its children, or have the child thread deteach itself when it
> > wants.
>Sure, but how often does a "decision" really need to be made? Usually,
>you either detach right after creating a thread, or you don't detach it
>at all. I've never seen a program where a thread was created, and some
>arbitrary time afterwards was a decision to detach or not made.
Agree. But by making it a seperate method, Perl allows you to do all of
that. I.e. enough rope...
Liz
Forcing
$thread->equals( $otherthread )
in this particular case, with the current memory limitations of threaded
Perl, sounds fine to me. It is a small price to pay. Ideal would of
course be if we could make it conditional, as Benjamin proposed in his
untested patch.
>However I think that most perl programs will end up using the overload
>module anyway so the savings isn't that big. (Many modules use overload).
I guess I'm not much of an overloading person, or haven't gotten to that
level of perl wizardry yet, but I've never used overload in any program
myself. So my programs, at least, are carrying that overhead needlessly.
A cursory grep on the 5.8.0 distribution, reveals that the following .pm
files contain the string 'use overload':
bigint.pm
CGI.pm
CGI/Cookie.pm
Encode/Encoder.pm
I18N/Collate.pm
Math/BigFloat.pm
Math/BigFloat/Trace.pm
Math/BigInt.pm
Math/BigInt/Trace.pm
Math/BigRat.pm
Math/Complex.pm
overload.pm
Switch.pm
Text/Balanced.pm
threads.pm
bigint and Math/* make sense to me. CGI* doesn't really (I haven't looked
at CGI.pm for the past 7 years, so I'm not really that familiar with
it). The only one, apart from threads.pm, that I might actually use in a
threaded application, is Text/Balanced.pm.
Maybe I should just add the removing of the three lines from threads.pm as
a performance enhancing tip in the faq?
Liz
> At 08:41 AM 9/27/02 +0200, Arthur Bergman wrote:
>> Ofcourse we could force the user to to $_[0]->equals($_), or
>> something else.
>
> Forcing
>
> $thread->equals( $otherthread )
>
> in this particular case, with the current memory limitations of
> threaded Perl, sounds fine to me. It is a small price to pay. Ideal
> would of course be if we could make it conditional, as Benjamin
> proposed in his untested patch.
>
I am sorry, I don't consider or read untested patches from people
without a reputation of producing working and applyable patches so I
have no idea what this means.
>
>> However I think that most perl programs will end up using the
>> overload module anyway so the savings isn't that big. (Many modules
>> use overload).
>
> I guess I'm not much of an overloading person, or haven't gotten to
> that level of perl wizardry yet, but I've never used overload in any
> program myself. So my programs, at least, are carrying that overhead
> needlessly.
>
>
> A cursory grep on the 5.8.0 distribution, reveals that the following
> .pm files contain the string 'use overload':
>
> bigint and Math/* make sense to me. CGI* doesn't really (I haven't
> looked at CGI.pm for the past 7 years, so I'm not really that familiar
> with it). The only one, apart from threads.pm, that I might actually
> use in a threaded application, is Text/Balanced.pm.
>
>
> Maybe I should just add the removing of the three lines from
> threads.pm as a performance enhancing tip in the faq?
>
No, rather perhaps a conditional statement saying not to use
overload.pm, are you only using core modules, what more modules on cpan
use overload?
The question should rather be, assume overload.pm has been loaded, how
much extra memory does it take to use it in threads.pm?
Arthur
It was all done as XS code and XS access to lexicals it obscure.
When (now) we have an API for PADs it will be easy.
I did consider having a "table" of objects - but the snag was where to
store it without making threads.xs depend on shared.xs
--
Nick Ing-Simmons
http://www.ni-s.u-net.com/