Forum Moderators: coopster

Message Too Old, No Replies

Which function is faster: eregi [or] stristr?

Which should I use for high traffic pages?

         

Mr_PHP

8:15 pm on Jan 23, 2005 (gmt 0)

10+ Year Member



Which is a faster alternative for determining if a specific string is contained in another, case-insensitively...

eregi(pattern,string) [OR] stristr(string,string)

It's intended for matching multiple parts of user agent names (in an array) against $_SERVER['HTTP_USER_AGENT']

For example:


$agent = $_SERVER['HTTP_USER_AGENT'];
$block = array('asp search','websearch','etcetera');
$blocked=false;

for($i=0; $i<count($block); $i++)
{
// EITHER THIS:
if( eregi("/$block[$i]/i",$agent) ) {
$blocked=true; break;
}
// ... OR:
if( stristr($block[$i],$agent) ) {
$blocked=true; break;
}
}

Nikke

10:41 pm on Jan 23, 2005 (gmt 0)

10+ Year Member



I am using eregi for blocking referral spammers from my site. It's still fast enough, but since I now have a list of over 75 sites that I'm blocking, I'm asking myself the same question as MrPHP.

eregi isn't really needed for parsing domains. Would string searching be faster?

Mr_PHP

10:51 pm on Jan 23, 2005 (gmt 0)

10+ Year Member



Thanks Nikke.

Anyone else is is using either eregi or stristr? Which is faster?

The blocked bots list (parts of their names) which I just created is not too long, it's: "asp search", "Alexibot", "Bullseye", "CherryPicker", "Collector","Copier", "Crescent", "Download", "Email", "Extractor", "Grabber", "Harvest", "Leacher", "Mechanic", "Mozilla/2", "MSIECrawler", "MSProxy", "NICErsPRO", "Offline", "Openfind", "psbot", "Teleport", "Telesoft", "Bandit", "WebEMailExtrac", "WebFetch", "websearch", "Webster", "WebViewer", "WebZIP", "Widow", "Wget", "Zeus"

Mr_PHP

10:38 am on Jan 24, 2005 (gmt 0)

10+ Year Member



Maybe it's not so relevant here, but for anyone interested, here's an improved list of the above: "alexibot", "bullseye", "cherrypicker", "collector" ,"convera", "copier", "crescent", "curl", "download", "email", "extractor", "grabber", "harvest", "internet explore ", "fetcher", "leacher", "mechanic", "msiecrawler" ,"msproxy", "nicerspro", "offline", "php", "picaloader", "psbot", "spidersoft", "teleport", "telesoft", "bandit", "webemailextrac", "webfetch", "websearch", "webster", "webviewer", "webzip", "wget", "widow", "winmht", "zeus"

My question remains.. which is faster: eregi [or] stristr?

coopster

12:48 pm on Jan 24, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Have you tested it [php.net]? You may also want to throw stripos() [php.net] into the race if you are running PHP5.

Mr_PHP

1:29 pm on Jan 24, 2005 (gmt 0)

10+ Year Member



Thanks coopster.

Yes, I'll test it myself. Thought maybe others had experience with this...
It's weird that Google does not return any useful results on this btw.

I can't test stripos, as I'm not using PHP5.

So, I'll test eregi and stristr and will let you know the results of it asap.

Mr_PHP

1:52 pm on Jan 24, 2005 (gmt 0)

10+ Year Member



As I'd expected stristr is faster than eregi.

It turned out on average around 7 times faster!

coopster

6:50 pm on Jan 24, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I figured as much and I'll bet stripos() might be faster yet. Glad you sorted it out.

jollymcfats

7:45 pm on Jan 24, 2005 (gmt 0)

10+ Year Member



An initial strtolower & then a case-sensitive strpos might be even faster still.

Mr_PHP

11:43 pm on Jan 24, 2005 (gmt 0)

10+ Year Member



Yeah, so stupid of me..

I should just do an initial strtolower indeed, then do the checks (with strstr)! DOH...

Is strpos really faster than strstr?

jollymcfats

11:55 pm on Jan 24, 2005 (gmt 0)

10+ Year Member



I don't know if strtolower would be a performance win with a single string compare, but with multiple strings like you've got there it probably is.

Also strpos is a bit faster. strstr has to do some memory allocation & string building to return its result; it is basically a combination of strpos and substr.


$text = 'blagga foo bar';
$part = [blue]strstr[/blue]($text, 'foo');
$part = substr($text, [blue]strpos[/blue]($text, 'foo'));

Mr_PHP

12:04 am on Jan 25, 2005 (gmt 0)

10+ Year Member



I just did two more tests...

1. using strstr (first do strtolower) instead of stristr in an iteration, is obviously faster

2. strstr is faster than strpos, although the average difference is very small

I am doing about 40 iterations max. on user agents (see above), so I'm now using:

$agent = strtolower($_SERVER['USER_AGENT']);
$banned_list = array('one','two','etc.');

for($i=0; $i<count($banned_list); $i++)
{
if( strstr($agent,$banned_list[$i]) ) { $banned=true; break; }
}

jollymcfats

12:59 am on Jan 25, 2005 (gmt 0)

10+ Year Member



2. strstr is faster than strpos, although the average difference is very small

That's surprising! I've benchmarked strpos as markedly faster in the past, though the strings in my test were substantially longer & needed larger memory allocation.

The implementation of the two functions is essentially identical, with strstr returning a freshly allocated string from a C-level substr().

Mr_PHP

1:27 am on Jan 25, 2005 (gmt 0)

10+ Year Member



Strange, yeah. But I don't know how it all works internally in PHP.

I tested again, and strstr is indeed faster than strpos, but on average only a few percent.