strpos() before str_replace()? Or, maybe strtr()? [message #184918] |
Sun, 16 February 2014 09:49 |
jwcarlton
Messages: 76 Registered: December 2010
Karma: 0
|
Member |
|
|
I know that I'm talking about microseconds here, so this is really just for the sake of furthering my own education.
I'm looping through roughly 100,000 values:
$userArr = array(
"something" => "anything",
...
);
foreach ($userArr as $key => $val) {
$firstname = str_replace($key, "****", $firstname);
$lastname = str_replace($key, "****", $lastname);
}
Both $firstname AND $lastname could contain any of the keys, but could only potentially contain one key each. It's likely, though, that neither will contain any of the keys.
Would it be faster to use strpos() before each str_replace(), like so?:
foreach ($userArr as $key => $val) {
if (strpos($firstname, $key) !== false)
$firstname = str_replace($key, "****", $firstname);
if (strpos($lastname, $key) !== false)
$lastname = str_replace($key, "****", $lastname);
}
My instinct is that it would be the same, if not marginally slower; allowing a potential computation time for 100,002 strpos() as opposed to 100,000 str_replace().
Or, would strtr() be faster? I've never actually used this function in practice; I think it's a slow function, but have never tested it, and don't remember where I read that:
$firstname = strtr($firstname, $userArr);
$lastname = strtr($lastname, $userArr);
Any other suggestions on what might be the fastest option?
TIA,
Jason
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184919 is a reply to message #184918] |
Sun, 16 February 2014 12:10 |
bill
Messages: 310 Registered: October 2010
Karma: 0
|
Senior Member |
|
|
On 2/16/2014 4:49 AM, Jason C wrote:
> I know that I'm talking about microseconds here, so this is really just for the sake of furthering my own education.
>
> I'm looping through roughly 100,000 values:
>
> $userArr = array(
> "something" => "anything",
> ...
> );
>
> foreach ($userArr as $key => $val) {
> $firstname = str_replace($key, "****", $firstname);
> $lastname = str_replace($key, "****", $lastname);
> }
>
> Both $firstname AND $lastname could contain any of the keys,
but could only potentially contain one key each. It's likely,
though,
that neither will contain any of the keys.
>
> Would it be faster to use strpos() before each str_replace(), like so?:
>
> foreach ($userArr as $key => $val) {
> if (strpos($firstname, $key) !== false)
> $firstname = str_replace($key, "****", $firstname);
>
> if (strpos($lastname, $key) !== false)
> $lastname = str_replace($key, "****", $lastname);
> }
>
> My instinct is that it would be the same, if not marginally slower;
allowing a potential computation time for 100,002 strpos() as
opposed to 100,000 str_replace().
>
> Or, would strtr() be faster? I've never actually used this function in practice;
I think it's a slow function, but have never tested it, and
don't remember where I read that:
>
> $firstname = strtr($firstname, $userArr);
> $lastname = strtr($lastname, $userArr);
>
> Any other suggestions on what might be the fastest option?
>
> TIA,
>
> Jason
>
Why would you want the opinion of a bunch of Old Farts (sorry
Jerry) when you could easily test it yourself and instruct us ?
-bill
Vetustior Humo
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184920 is a reply to message #184918] |
Sun, 16 February 2014 13:55 |
J.O. Aho
Messages: 194 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On 16/02/14 10:49, Jason C wrote:
> I know that I'm talking about microseconds here, so this is really just for the sake of furthering my own education.
>
> I'm looping through roughly 100,000 values:
>
> $userArr = array(
> "something" => "anything",
> ...
> );
>
> foreach ($userArr as $key => $val) {
> $firstname = str_replace($key, "****", $firstname);
> $lastname = str_replace($key, "****", $lastname);
> }
>
> Both $firstname AND $lastname could contain any of the keys, but could only potentially contain one key each. It's likely, though, that neither will contain any of the keys.
>
> Would it be faster to use strpos() before each str_replace(), like so?:
Yes, if you only make str_replace() when it really need it, then the
code will be faster and require less CPU cycles (of course the faster
the machine, the less of the ill effects you will notice, but it will
still be there).
> foreach ($userArr as $key => $val) {
> if (strpos($firstname, $key) !== false)
> $firstname = str_replace($key, "****", $firstname);
>
> if (strpos($lastname, $key) !== false)
> $lastname = str_replace($key, "****", $lastname);
> }
>
> My instinct is that it would be the same, if not marginally slower; allowing a potential computation time for 100,002 strpos() as opposed to 100,000 str_replace().
>
> Or, would strtr() be faster? I've never actually used this function in practice; I think it's a slow function, but have never tested it, and don't remember where I read that:
>
> $firstname = strtr($firstname, $userArr);
> $lastname = strtr($lastname, $userArr);
>
> Any other suggestions on what might be the fastest option?
Would value the CPU and time usage to be around the same as for
str_replace(), they both need to find the string and then build the new one.
--
//Aho
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184921 is a reply to message #184918] |
Sun, 16 February 2014 14:10 |
Thomas 'PointedEars'
Messages: 701 Registered: October 2010
Karma: 0
|
Senior Member |
|
|
Jason C wrote:
> I know that I'm talking about microseconds here, so this is really just
> for the sake of furthering my own education.
>
> I'm looping through roughly 100,000 values:
>
> $userArr = array(
> "something" => "anything",
> ...
> );
>
> foreach ($userArr as $key => $val) {
> $firstname = str_replace($key, "****", $firstname);
> $lastname = str_replace($key, "****", $lastname);
> }
>
> Both $firstname AND $lastname could contain any of the keys, but could
> only potentially contain one key each. It's likely, though, that neither
> will contain any of the keys.
I do not see the point of this code. Assuming complete code, $firstname and
$lastname are NULL in the first loop (issuing a notice each), therefore ''
in subsequent loops (str_replace() returns that when the “haystack” is
NULL). Even if they were not, what sense does it make to replace parts of
names, that match array keys, with “****”?
> Would it be faster to use strpos() before each str_replace(), like so?:
>
> foreach ($userArr as $key => $val) {
> if (strpos($firstname, $key) !== false)
> $firstname = str_replace($key, "****", $firstname);
>
> if (strpos($lastname, $key) !== false)
> $lastname = str_replace($key, "****", $lastname);
> }
Most certainly not.
> My instinct is that it would be the same,
Why do you think doing something twice would be as fast as doing it only
once?
> if not marginally slower;
It would obviously be slower, already because str_replace() has to search
for the substring before it can replace it. Even if str_pos() somehow
stored the position of the first occurrence of the substring, and
str_replace() would use that, a) it would still take additional time to
access that stored value and b) it would still be possible that there is
more than one occurrence of the substring in the string to be searched,
which str_pos() could not have stored.
> allowing a potential computation time for 100,002 strpos() as opposed to
> 100,000 str_replace().
Your logic is flawed: The worst case scenario is that *both* functions are
called.
> Or, would strtr() be faster? I've never actually used this function in
> practice; I think it's a slow function, but have never tested it, and
> don't remember where I read that:
>
> $firstname = strtr($firstname, $userArr);
> $lastname = strtr($lastname, $userArr);
It is possible that strtr() when called with a second array parameter could
be faster than str_replace(), but by contrast to str_replace() it has no way
of limiting the number of replacements. Also, str_replace() supports array
parameters both for “search” and “replace” as well.
<http://php.net/strtr>
<http://php.net/str_replace>
> Any other suggestions on what might be the fastest option?
Perhaps, if I could see the point of your code.
PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184922 is a reply to message #184918] |
Sun, 16 February 2014 14:15 |
Jerry Stuckle
Messages: 2598 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On 2/16/2014 4:49 AM, Jason C wrote:
> I know that I'm talking about microseconds here, so this is really just for the sake of furthering my own education.
>
> I'm looping through roughly 100,000 values:
>
> $userArr = array(
> "something" => "anything",
> ...
> );
>
> foreach ($userArr as $key => $val) {
> $firstname = str_replace($key, "****", $firstname);
> $lastname = str_replace($key, "****", $lastname);
> }
>
> Both $firstname AND $lastname could contain any of the keys, but could only potentially contain one key each. It's likely, though, that neither will contain any of the keys.
>
> Would it be faster to use strpos() before each str_replace(), like so?:
>
> foreach ($userArr as $key => $val) {
> if (strpos($firstname, $key) !== false)
> $firstname = str_replace($key, "****", $firstname);
>
> if (strpos($lastname, $key) !== false)
> $lastname = str_replace($key, "****", $lastname);
> }
>
> My instinct is that it would be the same, if not marginally slower; allowing a potential computation time for 100,002 strpos() as opposed to 100,000 str_replace().
>
> Or, would strtr() be faster? I've never actually used this function in practice; I think it's a slow function, but have never tested it, and don't remember where I read that:
>
> $firstname = strtr($firstname, $userArr);
> $lastname = strtr($lastname, $userArr);
>
> Any other suggestions on what might be the fastest option?
>
> TIA,
>
> Jason
>
The real question here is - what does it matter? Do you have a
performance problem? If so, what's the problem (I can about guarantee
it isn't here).
You can test it yourself, but that test is only going to be valid for
your current situation. Change versions of PHP, your OS or even the
means of calling PHP (i.e. CLI vs. Apache Module) may change the
results. And in this particular case, it will be highly dependent on
the data (i.e. the percentage of times your key appears in the strings).
You are much better off coding for clarity and testing. If you have a
performance problem, then is the time to find your performance problem
and fixing it. Donald Knuth had it right when he said "Premature
optimization is the root of all evil."
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex(at)attglobal(dot)net
==================
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184923 is a reply to message #184918] |
Sun, 16 February 2014 14:45 |
Christoph Michael Bec
Messages: 207 Registered: June 2013
Karma: 0
|
Senior Member |
|
|
Jason C wrote:
> I know that I'm talking about microseconds here, so this is really just for the sake of furthering my own education.
>
> I'm looping through roughly 100,000 values:
>
> $userArr = array(
> "something" => "anything",
> ...
> );
>
> foreach ($userArr as $key => $val) {
> $firstname = str_replace($key, "****", $firstname);
> $lastname = str_replace($key, "****", $lastname);
> }
>
> Both $firstname AND $lastname could contain any of the keys, but could only potentially contain one key each. It's likely, though, that neither will contain any of the keys.
>
> Would it be faster to use strpos() before each str_replace(), like so?:
>
> foreach ($userArr as $key => $val) {
> if (strpos($firstname, $key) !== false)
> $firstname = str_replace($key, "****", $firstname);
>
> if (strpos($lastname, $key) !== false)
> $lastname = str_replace($key, "****", $lastname);
> }
>
> My instinct is that it would be the same, if not marginally slower; allowing a potential computation time for 100,002 strpos() as opposed to 100,000 str_replace().
>
> Or, would strtr() be faster? I've never actually used this function in practice; I think it's a slow function, but have never tested it, and don't remember where I read that:
>
> $firstname = strtr($firstname, $userArr);
> $lastname = strtr($lastname, $userArr);
>
> Any other suggestions on what might be the fastest option?
Having the fastest option is surely less important than having a correct
solution, and there is an important semantic difference between
str_replace() and strtr(). Consider the following snippet:
$array = array('some' => 'any', 'anything' => 'nothing');
$name = 'something';
$keys = array_keys($array);
$values = array_values($array);
var_dump(str_replace($keys, $values, $name));
var_dump(strtr($name, $array));
This will output:
string(7) "nothing"
string(8) "anything"
--
Christoph M. Becker
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184924 is a reply to message #184918] |
Sun, 16 February 2014 15:08 |
Norman Peelman
Messages: 126 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On 02/16/2014 04:49 AM, Jason C wrote:
> I know that I'm talking about microseconds here, so this is really just for the sake of furthering my own education.
>
> I'm looping through roughly 100,000 values:
>
> $userArr = array(
> "something" => "anything",
> ...
> );
>
> foreach ($userArr as $key => $val) {
> $firstname = str_replace($key, "****", $firstname);
> $lastname = str_replace($key, "****", $lastname);
> }
>
> Both $firstname AND $lastname could contain any of the keys, but could only potentially contain one key each. It's likely, though, that neither will contain any of the keys.
>
> Would it be faster to use strpos() before each str_replace(), like so?:
>
> foreach ($userArr as $key => $val) {
> if (strpos($firstname, $key) !== false)
> $firstname = str_replace($key, "****", $firstname);
>
> if (strpos($lastname, $key) !== false)
> $lastname = str_replace($key, "****", $lastname);
> }
>
> My instinct is that it would be the same, if not marginally slower; allowing a potential computation time for 100,002 strpos() as opposed to 100,000 str_replace().
>
> Or, would strtr() be faster? I've never actually used this function in practice; I think it's a slow function, but have never tested it, and don't remember where I read that:
>
> $firstname = strtr($firstname, $userArr);
> $lastname = strtr($lastname, $userArr);
>
> Any other suggestions on what might be the fastest option?
>
> TIA,
>
> Jason
>
Per http://us1.php.net/manual/en/function.strstr.php - 'strpos()' is
faster than 'strstr()' if you only want to know if a string exists in
another string.
As far as using:
> foreach ($userArr as $key => $val) {
> if (strpos($firstname, $key) !== false)
> $firstname = str_replace($key, "****", $firstname);
>
> if (strpos($lastname, $key) !== false)
> $lastname = str_replace($key, "****", $lastname);
> }
It's slower because you are actually performing the same function
twice on each iteration. You are asking 'strpos()' to look for a string
and report its position (if it exists). It has to look through the
entire string to do so. Then you ask 'str_replace()' to do the same
thing only replacing the found string with a new string (if it exists).
It has to look through the entire string to do so. Since you are not
using the found position of said string ('str_replace()' can't use it)
then you are making a wasted call.
--
Norman
Registered Linux user #461062
-Have you been to www.php.net yet?-
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184925 is a reply to message #184923] |
Sun, 16 February 2014 16:23 |
Thomas 'PointedEars'
Messages: 701 Registered: October 2010
Karma: 0
|
Senior Member |
|
|
Christoph Michael Becker wrote:
> Jason C wrote:
>> foreach ($userArr as $key => $val) {
>> if (strpos($firstname, $key) !== false)
>> $firstname = str_replace($key, "****", $firstname);
>>
>> if (strpos($lastname, $key) !== false)
>> $lastname = str_replace($key, "****", $lastname);
>> }
>>
>> […]
>> Or, would strtr() be faster? I've never actually used this function in
>> practice; I think it's a slow function, but have never tested it, and
>> don't remember where I read that:
>>
>> $firstname = strtr($firstname, $userArr);
>> $lastname = strtr($lastname, $userArr);
>>
>> Any other suggestions on what might be the fastest option?
>
> Having the fastest option is surely less important than having a correct
> solution, and there is an important semantic difference between
> str_replace() and strtr(). Consider the following snippet:
>
> $array = array('some' => 'any', 'anything' => 'nothing');
> $name = 'something';
>
> $keys = array_keys($array);
> $values = array_values($array);
> var_dump(str_replace($keys, $values, $name));
>
> var_dump(strtr($name, $array));
>
> This will output:
>
> string(7) "nothing"
> string(8) "anything"
There *is* a semantic difference. He did not call str_replace() with array
parameters, though, nor did he suggest so.
PointedEars
--
Sometimes, what you learn is wrong. If those wrong ideas are close to the
root of the knowledge tree you build on a particular subject, pruning the
bad branches can sometimes cause the whole tree to collapse.
-- Mike Duffy in cljs, <news:Xns9FB6521286DB8invalidcom(at)94(dot)75(dot)214(dot)39>
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184926 is a reply to message #184925] |
Sun, 16 February 2014 16:41 |
Christoph Michael Bec
Messages: 207 Registered: June 2013
Karma: 0
|
Senior Member |
|
|
Thomas 'PointedEars' Lahn wrote:
> Christoph Michael Becker wrote:
>
>> Jason C wrote:
>>> foreach ($userArr as $key => $val) {
>>> if (strpos($firstname, $key) !== false)
>>> $firstname = str_replace($key, "****", $firstname);
>>>
>>> if (strpos($lastname, $key) !== false)
>>> $lastname = str_replace($key, "****", $lastname);
>>> }
>>>
>>> […]
>>> Or, would strtr() be faster? I've never actually used this function in
>>> practice; I think it's a slow function, but have never tested it, and
>>> don't remember where I read that:
>>>
>>> $firstname = strtr($firstname, $userArr);
>>> $lastname = strtr($lastname, $userArr);
>>>
>>> Any other suggestions on what might be the fastest option?
>>
>> Having the fastest option is surely less important than having a correct
>> solution, and there is an important semantic difference between
>> str_replace() and strtr(). Consider the following snippet:
>>
>> $array = array('some' => 'any', 'anything' => 'nothing');
>> $name = 'something';
>>
>> $keys = array_keys($array);
>> $values = array_values($array);
>> var_dump(str_replace($keys, $values, $name));
>>
>> var_dump(strtr($name, $array));
>>
>> This will output:
>>
>> string(7) "nothing"
>> string(8) "anything"
>
> There *is* a semantic difference. He did not call str_replace() with array
> parameters, though, nor did he suggest so.
Well, calling str_replace() in a loop as done by the OP has the same
semantic as calling str_replace() once with array parameters:
$array = array('some' => 'any', 'anything' => 'nothing');
$name = 'something';
foreach ($array as $key => $value) {
$name = str_replace($key, $value, $name);
}
var_dump($name); // string(7) "nothing"
(Using '****' instead of $value in the str_replace() might have similar
issues.)
Anyway, it is not clear to me what the OP wants to accomplish exactly.
--
Christoph M. Becker
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184927 is a reply to message #184924] |
Sun, 16 February 2014 19:21 |
Ben Bacarisse
Messages: 82 Registered: November 2013
Karma: 0
|
Member |
|
|
Norman Peelman <npeelman(at)cfl(dot)rr(dot)com> writes:
> On 02/16/2014 04:49 AM, Jason C wrote:
<snip>
>> foreach ($userArr as $key => $val) {
>> if (strpos($firstname, $key) !== false)
>> $firstname = str_replace($key, "****", $firstname);
>>
>> if (strpos($lastname, $key) !== false)
>> $lastname = str_replace($key, "****", $lastname);
>> }
>
>
> It's slower because you are actually performing the same function
> twice on each iteration.
Did you try it? In my tests it's faster (37ms vs 66ms). This may be
because of the assignment always being done.
I am not saying you could not have got different numbers, just that the
only way to be sure is to test with the real data in the real
environment.
--
Ben.
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184928 is a reply to message #184921] |
Sun, 16 February 2014 20:24 |
Ben Bacarisse
Messages: 82 Registered: November 2013
Karma: 0
|
Member |
|
|
Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
> Jason C wrote:
<snip>
>> I'm looping through roughly 100,000 values:
>>
>> $userArr = array(
>> "something" => "anything",
>> ...
>> );
>>
>> foreach ($userArr as $key => $val) {
>> $firstname = str_replace($key, "****", $firstname);
>> $lastname = str_replace($key, "****", $lastname);
>> }
>>
>> Both $firstname AND $lastname could contain any of the keys, but could
>> only potentially contain one key each. It's likely, though, that neither
>> will contain any of the keys.
<snip>
>> Would it be faster to use strpos() before each str_replace(), like so?:
>>
>> foreach ($userArr as $key => $val) {
>> if (strpos($firstname, $key) !== false)
>> $firstname = str_replace($key, "****", $firstname);
>>
>> if (strpos($lastname, $key) !== false)
>> $lastname = str_replace($key, "****", $lastname);
>> }
>
> Most certainly not.
And yet, when I measured it, it was faster. How can that be?
<snip>
--
Ben.
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184929 is a reply to message #184928] |
Sun, 16 February 2014 20:41 |
J.O. Aho
Messages: 194 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On 16/02/14 21:24, Ben Bacarisse wrote:
> Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
>
>> Jason C wrote:
> <snip>
>>> I'm looping through roughly 100,000 values:
>>>
>>> $userArr = array(
>>> "something" => "anything",
>>> ...
>>> );
>>>
>>> foreach ($userArr as $key => $val) {
>>> $firstname = str_replace($key, "****", $firstname);
>>> $lastname = str_replace($key, "****", $lastname);
>>> }
>>>
>>> Both $firstname AND $lastname could contain any of the keys, but could
>>> only potentially contain one key each. It's likely, though, that neither
>>> will contain any of the keys.
> <snip>
>>> Would it be faster to use strpos() before each str_replace(), like so?:
>>>
>>> foreach ($userArr as $key => $val) {
>>> if (strpos($firstname, $key) !== false)
>>> $firstname = str_replace($key, "****", $firstname);
>>>
>>> if (strpos($lastname, $key) !== false)
>>> $lastname = str_replace($key, "****", $lastname);
>>> }
>>
>> Most certainly not.
>
> And yet, when I measured it, it was faster. How can that be?
>
> <snip>
For strpos is faster than str_replace on finding the string.
--
//Aho
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184930 is a reply to message #184918] |
Sun, 16 February 2014 20:49 |
Ben Bacarisse
Messages: 82 Registered: November 2013
Karma: 0
|
Member |
|
|
Jason C <jwcarlton(at)gmail(dot)com> writes:
> I know that I'm talking about microseconds here, so this is really
> just for the sake of furthering my own education.
>
> I'm looping through roughly 100,000 values:
>
> $userArr = array(
> "something" => "anything",
> ...
> );
>
> foreach ($userArr as $key => $val) {
> $firstname = str_replace($key, "****", $firstname);
> $lastname = str_replace($key, "****", $lastname);
> }
>
> Both $firstname AND $lastname could contain any of the keys, but could
> only potentially contain one key each. It's likely, though, that
> neither will contain any of the keys.
>
> Would it be faster to use strpos() before each str_replace(), like so?:
>
> foreach ($userArr as $key => $val) {
> if (strpos($firstname, $key) !== false)
> $firstname = str_replace($key, "****", $firstname);
>
> if (strpos($lastname, $key) !== false)
> $lastname = str_replace($key, "****", $lastname);
> }
In a simple test, it seems to be a faster -- significantly faster in
relative terms but not much in absolute time. The exact numbers depend
on the length of the strings, whether one of the 100,000 strings really
is present or not, the exact keys used and so on, but in all cases that
I tested, checking strpos first pays off. A typical run: 64ms vs
33ms.
I first thought this might be because of the assignment, but it turns
out not to be. I think the cause is that str_replace has a high
overhead -- it does more before it ever gets going. If you can save
this overhead on 99,999 occasions, you save overall despite scanning the
string twice that one time.
Of course, as with all measurements like this, I may not have properly
duplicated your situation, and the result will depend on the machine,
the PHP version, and more besides, so take it with a pinch of salt.
(And note that if the key is numeric, strpos does not do what you
think!)
<snip>
> Or, would strtr() be faster? I've never actually used this function in
> practice; I think it's a slow function, but have never tested it, and
> don't remember where I read that:
>
> $firstname = strtr($firstname, $userArr);
> $lastname = strtr($lastname, $userArr);
In my test, about 89ms -- slower than either of the two above but if
it gives the right result (there is a slight difference in meaning as
pointed out elsethread) I'd probably use it for the clarity it brings.
> Any other suggestions on what might be the fastest option?
If you already have (or could have) the keys and the values in separate
arrays, using the array version of str_replace tested reasonably well
(66ms). However, as you start off by saying, it's all very marginal. I
would not normally measure this sort of thing; I'd just write the
simplest code and forget about it.
--
Ben.
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184931 is a reply to message #184929] |
Sun, 16 February 2014 20:51 |
Ben Bacarisse
Messages: 82 Registered: November 2013
Karma: 0
|
Member |
|
|
"J.O. Aho" <user(at)example(dot)net> writes:
> On 16/02/14 21:24, Ben Bacarisse wrote:
>> Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
>>
>>> Jason C wrote:
>> <snip>
>>>> I'm looping through roughly 100,000 values:
>>>>
>>>> $userArr = array(
>>>> "something" => "anything",
>>>> ...
>>>> );
>>>>
>>>> foreach ($userArr as $key => $val) {
>>>> $firstname = str_replace($key, "****", $firstname);
>>>> $lastname = str_replace($key, "****", $lastname);
>>>> }
>>>>
>>>> Both $firstname AND $lastname could contain any of the keys, but could
>>>> only potentially contain one key each. It's likely, though, that neither
>>>> will contain any of the keys.
>> <snip>
>>>> Would it be faster to use strpos() before each str_replace(), like so?:
>>>>
>>>> foreach ($userArr as $key => $val) {
>>>> if (strpos($firstname, $key) !== false)
>>>> $firstname = str_replace($key, "****", $firstname);
>>>>
>>>> if (strpos($lastname, $key) !== false)
>>>> $lastname = str_replace($key, "****", $lastname);
>>>> }
>>>
>>> Most certainly not.
>>
>> And yet, when I measured it, it was faster. How can that be?
>>
>> <snip>
>
> For strpos is faster than str_replace on finding the string.
Yes, though the question was rhetorical!
--
Ben.
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184932 is a reply to message #184927] |
Sun, 16 February 2014 20:53 |
Ben Bacarisse
Messages: 82 Registered: November 2013
Karma: 0
|
Member |
|
|
Ben Bacarisse <ben(dot)usenet(at)bsb(dot)me(dot)uk> writes:
> Norman Peelman <npeelman(at)cfl(dot)rr(dot)com> writes:
>
>> On 02/16/2014 04:49 AM, Jason C wrote:
> <snip>
>>> foreach ($userArr as $key => $val) {
>>> if (strpos($firstname, $key) !== false)
>>> $firstname = str_replace($key, "****", $firstname);
>>>
>>> if (strpos($lastname, $key) !== false)
>>> $lastname = str_replace($key, "****", $lastname);
>>> }
>>
>>
>> It's slower because you are actually performing the same function
>> twice on each iteration.
>
> Did you try it? In my tests it's faster (37ms vs 66ms). This may be
> because of the assignment always being done.
I'm pretty sure that it is simply the overhead of str_replace compared
to that of strpos, and not to do with the assignment.
<snip>
--
Ben.
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184933 is a reply to message #184931] |
Sun, 16 February 2014 21:16 |
Thomas 'PointedEars'
Messages: 701 Registered: October 2010
Karma: 0
|
Senior Member |
|
|
Ben Bacarisse wrote:
> "J.O. Aho" <user(at)example(dot)net> writes:
>> On 16/02/14 21:24, Ben Bacarisse wrote:
>>> Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
>>>> Jason C wrote:
>>> <snip>
>>>> > I'm looping through roughly 100,000 values:
>>>> >
>>>> > $userArr = array(
>>>> > "something" => "anything",
>>>> > ...
>>>> > );
>>>> >
>>>> > foreach ($userArr as $key => $val) {
>>>> > $firstname = str_replace($key, "****", $firstname);
>>>> > $lastname = str_replace($key, "****", $lastname);
>>>> > }
>>>> >
>>>> > Both $firstname AND $lastname could contain any of the keys, but could
>>>> > only potentially contain one key each. It's likely, though, that
>>>> > neither will contain any of the keys.
>>> <snip>
>>>> > Would it be faster to use strpos() before each str_replace(), like
>>>> > so?:
>>>> >
>>>> > foreach ($userArr as $key => $val) {
>>>> > if (strpos($firstname, $key) !== false)
>>>> > $firstname = str_replace($key, "****", $firstname);
>>>> >
>>>> > if (strpos($lastname, $key) !== false)
>>>> > $lastname = str_replace($key, "****", $lastname);
>>>> > }
>>>>
>>>> Most certainly not.
>>>
>>> And yet, when I measured it, it was faster. How can that be?
>>>
>>> <snip>
>>
>> For strpos is faster than str_replace on finding the string.
How, and why? Both search for the occurrence of a substring in a string.
> Yes, though the question was rhetorical!
The question was stupid.
PointeDears
--
Sometimes, what you learn is wrong. If those wrong ideas are close to the
root of the knowledge tree you build on a particular subject, pruning the
bad branches can sometimes cause the whole tree to collapse.
-- Mike Duffy in cljs, <news:Xns9FB6521286DB8invalidcom(at)94(dot)75(dot)214(dot)39>
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184934 is a reply to message #184933] |
Sun, 16 February 2014 23:13 |
Ben Bacarisse
Messages: 82 Registered: November 2013
Karma: 0
|
Member |
|
|
Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
> Ben Bacarisse wrote:
>
>> "J.O. Aho" <user(at)example(dot)net> writes:
>>> On 16/02/14 21:24, Ben Bacarisse wrote:
>>>> Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
>>>> > Jason C wrote:
>>>> <snip>
>>>> >> I'm looping through roughly 100,000 values:
>>>> >>
>>>> >> $userArr = array(
>>>> >> "something" => "anything",
>>>> >> ...
>>>> >> );
>>>> >>
>>>> >> foreach ($userArr as $key => $val) {
>>>> >> $firstname = str_replace($key, "****", $firstname);
>>>> >> $lastname = str_replace($key, "****", $lastname);
>>>> >> }
>>>> >>
>>>> >> Both $firstname AND $lastname could contain any of the keys, but could
>>>> >> only potentially contain one key each. It's likely, though, that
>>>> >> neither will contain any of the keys.
>>>> <snip>
>>>> >> Would it be faster to use strpos() before each str_replace(), like
>>>> >> so?:
>>>> >>
>>>> >> foreach ($userArr as $key => $val) {
>>>> >> if (strpos($firstname, $key) !== false)
>>>> >> $firstname = str_replace($key, "****", $firstname);
>>>> >>
>>>> >> if (strpos($lastname, $key) !== false)
>>>> >> $lastname = str_replace($key, "****", $lastname);
>>>> >> }
>>>> >
>>>> > Most certainly not.
>>>>
>>>> And yet, when I measured it, it was faster. How can that be?
>>>>
>>>> <snip>
>>>
>>> For strpos is faster than str_replace on finding the string.
>
> How, and why? Both search for the occurrence of a substring in a
> string.
Because strpos has a lower per-call overhead.
<snip>
--
Ben.
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184935 is a reply to message #184927] |
Sun, 16 February 2014 23:17 |
Norman Peelman
Messages: 126 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On 02/16/2014 02:21 PM, Ben Bacarisse wrote:
> Norman Peelman <npeelman(at)cfl(dot)rr(dot)com> writes:
>
>> On 02/16/2014 04:49 AM, Jason C wrote:
> <snip>
>>> foreach ($userArr as $key => $val) {
>>> if (strpos($firstname, $key) !== false)
>>> $firstname = str_replace($key, "****", $firstname);
>>>
>>> if (strpos($lastname, $key) !== false)
>>> $lastname = str_replace($key, "****", $lastname);
>>> }
>>
>>
>> It's slower because you are actually performing the same function
>> twice on each iteration.
>
> Did you try it? In my tests it's faster (37ms vs 66ms). This may be
> because of the assignment always being done.
>
> I am not saying you could not have got different numbers, just that the
> only way to be sure is to test with the real data in the real
> environment.
>
Thanks for pointing that out. I didn't think of it that way.
--
Norman
Registered Linux user #461062
-Have you been to www.php.net yet?-
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184936 is a reply to message #184932] |
Mon, 17 February 2014 01:44 |
Denis McMahon
Messages: 634 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On Sun, 16 Feb 2014 20:53:52 +0000, Ben Bacarisse wrote:
> Ben Bacarisse <ben(dot)usenet(at)bsb(dot)me(dot)uk> writes:
>
>> Norman Peelman <npeelman(at)cfl(dot)rr(dot)com> writes:
>>
>>> On 02/16/2014 04:49 AM, Jason C wrote:
>> <snip>
>>>> foreach ($userArr as $key => $val) {
>>>> if (strpos($firstname, $key) !== false)
>>>> $firstname = str_replace($key, "****", $firstname);
>>>>
>>>> if (strpos($lastname, $key) !== false)
>>>> $lastname = str_replace($key, "****", $lastname);
>>>> }
>>>
>>>
>>> It's slower because you are actually performing the same function
>>> twice on each iteration.
>>
>> Did you try it? In my tests it's faster (37ms vs 66ms). This may be
>> because of the assignment always being done.
>
> I'm pretty sure that it is simply the overhead of str_replace compared
> to that of strpos, and not to do with the assignment.
>
> <snip>
Not sure whether something like this could be faster or not:
foreach ( $userArr as $key => $val ) {
if ( ( $f = strpos( $firstname, $key ) ) !== false )
$firstname = substr( $firstname, 0, $f ) . "****" .
substr( $firstname, $f + strlen( $key ) );
if ( ( $l = strpos( $lastname, $key ) ) !== false )
$lastname = substr( $lastname, 0, $l ) . "****" .
substr( $lastname, $l + strlen( $key ) );
}
As I don't have representative data to test against.
You could use a function:
function replace_stars( $needle, $pos, $haystack ) {
return substr( $haystack, 0, $pos ) . "****" .
substr( $haystack, $pos + strlen( $needle ) );
}
foreach ( $userArr as $key => $val ) {
if ( ( $f = strpos( $firstname, $key ) ) !== false )
$firstname = replace_stars( $key, $f, $firstname );
if ( ( $l = strpos( $lastname, $key ) ) !== false )
$lastname = replace_stars( $key, $f, $lastname );
}
but that would be an extra function call, so I inlined the code instead.
p.s. Yes richard, I used an "=" inside an if test, but the difference is
that I know what I'm doing when I do that, and you don't!
--
Denis McMahon, denismfmcmahon(at)gmail(dot)com
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184937 is a reply to message #184936] |
Mon, 17 February 2014 02:19 |
Ben Bacarisse
Messages: 82 Registered: November 2013
Karma: 0
|
Member |
|
|
Denis McMahon <denismfmcmahon(at)gmail(dot)com> writes:
<snip>
> Not sure whether something like this could be faster or not:
>
> foreach ( $userArr as $key => $val ) {
>
> if ( ( $f = strpos( $firstname, $key ) ) !== false )
> $firstname = substr( $firstname, 0, $f ) . "****" .
> substr( $firstname, $f + strlen( $key ) );
>
> if ( ( $l = strpos( $lastname, $key ) ) !== false )
> $lastname = substr( $lastname, 0, $l ) . "****" .
> substr( $lastname, $l + strlen( $key ) );
>
> }
>
> As I don't have representative data to test against.
Given the structure of the data (lots of tests, with rate matches) I'd
expect this to be much like the strpos + str_replace solution, since the
speed of determining that there is no match dominates. The assignment
to $l might have a small effect, and that seems to be the case. The
timings show it's a few percent slower than the plain strpos+str_replace
solution.
The situation is an odd one. Matches are very rare, and this makes it
worthwhile avoiding as much work as possible when there is no match.
The positions $f and $l are only needed when there is a match, so,
oddly, it makes sense to re-calculate them rather than to assign them
every time. I.e. this unlikely pattern:
if (strpos( $firstname, $key) !== false ) {
$f = strpos($firstname, $key);
$firstname = substr($firstname, 0, $f) . "****" .
substr($firstname, $f + strlen($key));
}
is faster than the above (but by a small, if consistent, amount).
Avoiding 99,999 assignments at the cost of maybe one strpos call is a
win (though I am sure you can construct data sets that reduce or
eliminate this advantage). When there is no match at all (which the OP
describes as a likely event), avoiding 100,000 assignments at the cost
of nothing, can't be anything but a win!
<snip>
--
Ben.
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184938 is a reply to message #184931] |
Mon, 17 February 2014 05:35 |
J.O. Aho
Messages: 194 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On 16/02/14 21:51, Ben Bacarisse wrote:
> "J.O. Aho" <user(at)example(dot)net> writes:
>
>> On 16/02/14 21:24, Ben Bacarisse wrote:
>>> Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
>>>
>>>> Jason C wrote:
>>> <snip>
>>>> > I'm looping through roughly 100,000 values:
>>>> >
>>>> > $userArr = array(
>>>> > "something" => "anything",
>>>> > ...
>>>> > );
>>>> >
>>>> > foreach ($userArr as $key => $val) {
>>>> > $firstname = str_replace($key, "****", $firstname);
>>>> > $lastname = str_replace($key, "****", $lastname);
>>>> > }
>>>> >
>>>> > Both $firstname AND $lastname could contain any of the keys, but could
>>>> > only potentially contain one key each. It's likely, though, that neither
>>>> > will contain any of the keys.
>>> <snip>
>>>> > Would it be faster to use strpos() before each str_replace(), like so?:
>>>> >
>>>> > foreach ($userArr as $key => $val) {
>>>> > if (strpos($firstname, $key) !== false)
>>>> > $firstname = str_replace($key, "****", $firstname);
>>>> >
>>>> > if (strpos($lastname, $key) !== false)
>>>> > $lastname = str_replace($key, "****", $lastname);
>>>> > }
>>>>
>>>> Most certainly not.
>>>
>>> And yet, when I measured it, it was faster. How can that be?
>>>
>>> <snip>
>>
>> For strpos is faster than str_replace on finding the string.
>
> Yes, though the question was rhetorical!
Even if your question is rhetorical:
One of the send guys did release an pdf some year ago where he wes
recommending to strpos check before use of str_replace saying just that
the strpos was more optimized.
--
//Aho
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184940 is a reply to message #184938] |
Mon, 17 February 2014 14:14 |
Ben Bacarisse
Messages: 82 Registered: November 2013
Karma: 0
|
Member |
|
|
"J.O. Aho" <user(at)example(dot)net> writes:
<snip>
> One of the send guys did release an pdf some year ago where he wes
> recommending to strpos check before use of str_replace saying just
> that the strpos was more optimized.
I wonder if any cut-off point was mentioned. It must, at some point,
start to cost more than it saves. For example, if I reverse the
situation given by the OP so that replacements are very common rather
than very rare, adding the strpos call nearly doubles the run time.
Since it nearly haves it when replacements are very rare, I would not be
surprised to find that the break even point is when about half of the
tests will result in a replacement.
Still, the cost or benefit is likely to be insignificant for the vast
majority of PHP programs.
--
Ben.
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184941 is a reply to message #184940] |
Mon, 17 February 2014 17:55 |
J.O. Aho
Messages: 194 Registered: September 2010
Karma: 0
|
Senior Member |
|
|
On 17/02/14 15:14, Ben Bacarisse wrote:
> "J.O. Aho" <user(at)example(dot)net> writes:
> <snip>
>> One of the send guys did release an pdf some year ago where he wes
>> recommending to strpos check before use of str_replace saying just
>> that the strpos was more optimized.
>
> I wonder if any cut-off point was mentioned. It must, at some point,
> start to cost more than it saves. For example, if I reverse the
> situation given by the OP so that replacements are very common rather
> than very rare, adding the strpos call nearly doubles the run time.
Don't think he mentioned, I have the document on my PowerPC machine, but
that one hasn't been turned on for a year or so. I think there was
something about using the position you got from strpos() to limit the
scope for which you use str_replace(), but a bit unsure how it was in
the example.
> Since it nearly haves it when replacements are very rare, I would not be
> surprised to find that the break even point is when about half of the
> tests will result in a replacement.
I think it was that str_replace was slow on finding the string within
and it don't stop at the first find, but has to go through the whole
string, but ultimately there will be a break even point, but in normal
situations I don't think you will be there.
> Still, the cost or benefit is likely to be insignificant for the vast
> majority of PHP programs.
I think it's the philosophy that decides, one side like microsoft who do
not believe in optimization and thinks it's just throw more hardware if
there would be issues and another extreme who always goes for optimal
optimization and of course a lot of people in between.
I think optimization should be done (to a certain level where the time
spent will not be too great), as you never will know on what your code
will be run, a smart watch with some old SoC, then you will notice the
difference while on a TOP 500 Supercomputer you will not notice it, but
better be safe than sorry.
--
//Aho
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184942 is a reply to message #184938] |
Mon, 17 February 2014 18:30 |
Christoph Michael Bec
Messages: 207 Registered: June 2013
Karma: 0
|
Senior Member |
|
|
J.O. Aho wrote:
> On 16/02/14 21:51, Ben Bacarisse wrote:
>> "J.O. Aho" <user(at)example(dot)net> writes:
>>
>>> On 16/02/14 21:24, Ben Bacarisse wrote:
>>>> Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
>>>>
>>>> > Jason C wrote:
>>>> <snip>
>>>> >> I'm looping through roughly 100,000 values:
>>>> >>
>>>> >> $userArr = array(
>>>> >> "something" => "anything",
>>>> >> ...
>>>> >> );
>>>> >>
>>>> >> foreach ($userArr as $key => $val) {
>>>> >> $firstname = str_replace($key, "****", $firstname);
>>>> >> $lastname = str_replace($key, "****", $lastname);
>>>> >> }
>>>> >>
>>>> >> Both $firstname AND $lastname could contain any of the keys, but
>>>> >> could
>>>> >> only potentially contain one key each. It's likely, though, that
>>>> >> neither
>>>> >> will contain any of the keys.
>>>> <snip>
>>>> >> Would it be faster to use strpos() before each str_replace(), like
>>>> >> so?:
>>>> >>
>>>> >> foreach ($userArr as $key => $val) {
>>>> >> if (strpos($firstname, $key) !== false)
>>>> >> $firstname = str_replace($key, "****", $firstname);
>>>> >>
>>>> >> if (strpos($lastname, $key) !== false)
>>>> >> $lastname = str_replace($key, "****", $lastname);
>>>> >> }
>>>> >
>>>> > Most certainly not.
>>>>
>>>> And yet, when I measured it, it was faster. How can that be?
>>>>
>>>> <snip>
>>>
>>> For strpos is faster than str_replace on finding the string.
>>
>> Yes, though the question was rhetorical!
>
> Even if your question is rhetorical:
> One of the send guys did release an pdf some year ago where he wes
> recommending to strpos check before use of str_replace saying just that
> the strpos was more optimized.
Um, even if it is faster now that might change in the future -- after
all this seems to be an implementation issue.
Consider how the implementation of variable interpolation has changed
within a few years.[1][2]
[1] <http://blog.golemon.com/2006/06/how-long-is-piece-of-string.html>
[2]
< http://nikic.github.io/2012/01/09/Disproving-the-Single-Quotes-Performance- Myth.html>
--
Christoph M. Becker
|
|
|
Re: strpos() before str_replace()? Or, maybe strtr()? [message #184943 is a reply to message #184934] |
Tue, 18 February 2014 00:33 |
Thomas 'PointedEars'
Messages: 701 Registered: October 2010
Karma: 0
|
Senior Member |
|
|
Ben Bacarisse wrote:
> Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
>> Ben Bacarisse wrote:
>>> "J.O. Aho" <user(at)example(dot)net> writes:
>>>> On 16/02/14 21:24, Ben Bacarisse wrote:
>>>> > Thomas 'PointedEars' Lahn <PointedEars(at)web(dot)de> writes:
>>>> >> Jason C wrote:
>>>> >>> Would it be faster to use strpos() before each str_replace(), like
>>>> >>> so?:
>>>> >>>
>>>> >>> foreach ($userArr as $key => $val) {
>>>> >>> if (strpos($firstname, $key) !== false)
>>>> >>> $firstname = str_replace($key, "****", $firstname);
>>>> >>>
>>>> >>> if (strpos($lastname, $key) !== false)
>>>> >>> $lastname = str_replace($key, "****", $lastname);
>>>> >>> }
>>>> >>
>>>> >> Most certainly not.
>>>> >
>>>> > And yet, when I measured it, it was faster. How can that be?
>>>> >
>>>> > <snip>
>>>>
>>>> For strpos is faster than str_replace on finding the string.
>>
>> How, and why? Both search for the occurrence of a substring in a
>> string.
>
> Because strpos has a lower per-call overhead.
That is irrelevant regarding the question which function can *find* the
string faster, is it not?
PointedEars
--
Danny Goodman's books are out of date and teach practices that are
positively harmful for cross-browser scripting.
-- Richard Cornford, cljs, <cife6q$253$1$8300dec7(at)news(dot)demon(dot)co(dot)uk> (2004)
|
|
|