Search code examples
phpstrpos

Most performant way to check if strpos() returned a non-false value


I've only ever seen developers use strict comparisons when they use strpos to check for the existence of a substring:

if (strpos($haystack,$needle) !== false) {

}

It occurred to me today that one could use is_numeric ins

if (is_numeric(strpos($haystack,$needle))) {

}

Is there a reason one would use one over the other (specifically in this use case)?

If you think about it, the purpose of strpos is to return the position of the substring. Only if it doesn't exist, will it return false. The position is a number. Thus, is_numeric is pretty qualified to be considered semantically.


Solution

  • I found this question searching for almost the same question, except my thought was to use is_int( ) not is_numeric( ). I couldn't really understand the benchmark that was posted so I made my own. In short, is_numeric( ) is a hair slower than !== false, and is_int( ) is a hair faster. Personally, I find it more readable than !== false not less, so I'll probably switch to it.

    This was done under php v7.1.23

    Results:

    0.7900s for '!== false' with hits
    4.5137s for '!== false' with misses
    
    0.9297s for 'is_numeric' with hits
    4.7509s for 'is_numeric' with misses
    
    0.6391s for 'is_int' with hits
    4.4862s for 'is_int' with misses
    

    From the code:

    $n_times = 10000000;
    $haystack_hit = "  Certificate Name: example.com";
    $heystack_miss = "Found the following certs:";
    $needle = "Certificate Name:";
    
    $start = microtime(true);
    for($i = 0; $i < $n_times; $i++)
        {
        if (strpos($haystack_hit,$needle) !== false)
            { }
        }
    $end = microtime(true) - $start;
    echo "\n" . round($end,4) . "s for '!== false' with hits\n";
    
    $start = microtime(true);
    for($i = 0; $i < $n_times; $i++)
        {
        if (strpos($haystack_miss,$needle) !== false)
            { }
        }
    $end = microtime(true) - $start;
    echo round($end,4) . "s for '!== false' with misses\n\n";
    
    // -----
    
    $start = microtime(true);
    for($i = 0; $i < $n_times; $i++)
        {
        if ( is_numeric(strpos($haystack_hit,$needle)) )
            { }
        }
    $end = microtime(true) - $start;
    echo round($end,4) . "s for 'is_numeric' with hits\n";
    
    $start = microtime(true);
    for($i = 0; $i < $n_times; $i++)
        {
        if ( is_numeric(strpos($haystack_miss,$needle)) )
            { }
        }
    $end = microtime(true) - $start;
    echo round($end,4) . "s for 'is_numeric' with misses\n\n";
    
    // -----
    
    $start = microtime(true);
    for($i = 0; $i < $n_times; $i++)
        {
        if ( is_int(strpos($haystack_hit,$needle)) )
            { }
        }
    $end = microtime(true) - $start;
    echo round($end,4) . "s for 'is_int' with hits\n";
    
    $start = microtime(true);
    for($i = 0; $i < $n_times; $i++)
        {
        if ( is_int(strpos($haystack_miss,$needle)) )
            { }
        }
    $end = microtime(true) - $start;
    echo round($end,4) . "s for 'is_int' with misses\n";