Re: PHP 4.0 Bug #7113: count and pointers
| From: | Lars Torben Wilson | Date: | Wed, 11 Oct 2000 00:16:45 +0000 |
| Subject: | Re: PHP 4.0 Bug #7113: count and pointers | ||
| References: | 1 2 | Groups: | php.dev |
| Request: | Send a blank email to php-dev+get-34628@lists.php.net to get a copy of this message | ||
Dhr. CaPS Cappert writes:
> Now why would you do
> $blah = count(&$data)
> the '&' doesn't make sense here. The code above still
> wouldn't make it make sense. count() doesn't modify, NO SENSE
> in using it there.
With due respect, I believe that you are at least partially mistaken.
You might want to pass by reference for The Other Reason: avoiding
having to pass an 8-10MB array on the function call. Granted, you'd
either need to enable allow_call_time_pass_reference or mask out
E_COMPILE_WARNING in php.ini, but it can be done, works, and makes
sense. I am not, you should note, making any claims as to how
future-proof the operation is. :)
> This time difference I had can be achieved like this
> $file = file("whatever");
> $data = &$file;
> $count = count ($data);
Ah. So you're saying that creating a second name for the same 8-10MB
array and passing all that data (albeit by a different name) makes
sense? References in PHP aren't pointers or references like in C. They
are simply aliases. By creating a reference to the data, and then
passing that reference, all you are doing is creating a new name for
the same huge chunk of data, and then passing that data by its new
name. However, when you pass by reference (and there does seem to be a
difference in PHP between 'passing BY reference' and 'passing A
reference'), you are passing only a reference to that data's entry in
the symbol table--thereby skipping a potentially huge copy.
Granted, PHP 4 has deprecated support for call-time pass-by-reference,
so to get the code above to work, you would either need to enable
allow_call_time_pass_by_reference or mask out E_COMPILE_WARNING in
php.ini. In the current CVS of PHP 4, call-time pass-by-reference will
work anyway, even though it'll spit a big warning at you telling you
that it didn't work.
By changing BYREF_ALLOW to BYREF_FORCE in count()'s function entry in
basic_functions.c, I was able to get _all_ invocations of count() to
pass by reference automatically, removing the need to use the
deprecated syntax to get a reasonable speed out of the thing. I'm sure
there is some deep subtle reason for this not being the default,
since, as you mention, count() will never modify its argument and
therefore one might as well pass by reference--especially given that
the performance increase offered by doing so is at least a couple of
orders of magnitude.
> (Which seems like the PROPER way to do it.)
>
> This was on a binary file (A mp3 size 6.3mb)
> Running on a Celly 366 / 128M
>
> --CaPS
I've just tested both with a 13MB INBOX (straight ASCII) and a 6.5MB
.mp3 and I get similar results: passing by reference (either by
changing BYREF_ALLOW to BYREF_FORCE or by call-time pass-by-reference)
results in the INBOX file getting counted 4 times in 0.01-0.5 seconds;
using your method, 4 count()s take 6-7 seconds; and using normal
pass-by-value, 4 counts() take 10-11 seconds.
I will admit that there are things about the Zend-level reference
passing that I do not understand, and I certainly do not understand
why the ability to force call-by-reference has been deprecated (can
someone explain that to me?). I do not understand why you are getting
the timing results which you are getting. Perhaps there are deep magic
reasons for all of these things.
If you wish, I can send you the scripts with which I am testing this.
--
+----------------------------------------------------------------+
|Torben Wilson <torben@php.net> Netmill iTech|
|http://www.coastnet.com/~torben http://www.netmill.fi|
|Ph: 1 250 383-9735 torben@netmill.fi|
+----------------------------------------------------------------+