Which is faster: glob() or opendir()
Asked Answered
R

6

6

Which is faster between glob() and opendir(), for reading around 1-2K file(s)?

Reames answered 4/5, 2010 at 6:38 Comment(1)
They aren't really comparable, you should compare glob() to an alternative that does the same thing.Gasparo
D
11

http://code2design.com/forums/glob_vs_opendir

Obviously opendir() should be (and is) quicker as it opens the directory handler and lets you iterate. Because glob() has to parse the first argument it's going to take some more time (plus glob handles recursive directories so it'll scan subdirs, which will add to the execution time.

Dieback answered 4/5, 2010 at 6:43 Comment(0)
W
10

glob and opendir do different things. glob finds pathnames matching a pattern and returns these in an array, while opendir returns a directory handle only. To get the same results as with glob you have to call additional functions, which you have to take into account when benchmarking, especially if this includes pattern matching.

Bill Karwin has written an article about this recently. See:

Whoops answered 4/5, 2010 at 6:53 Comment(0)
S
2

Not sure whether that is perfect comparison but glob() allows you to incorporate the shell-like patterns as well where as opendir is directly there for the directories there by making it faster.

Samira answered 4/5, 2010 at 6:40 Comment(1)
glob() uses shell-like patterns, not regular expressionsGasparo
N
2

another question that can be answered with a bit of testing. i had a convenient folder with 412 things in it, but the results shouldn't vary much, i imagine:

igor47@whisker ~/test $ ls /media/music | wc -l
412
igor47@whisker ~/test $ time php opendir.php 
414 files total

real    0m0.023s
user    0m0.000s
sys 0m0.020s
igor47@whisker ~/test $ time php glob.php 
411 files total

real    0m0.023s
user    0m0.010s
sys 0m0.010s
Noria answered 4/5, 2010 at 6:51 Comment(0)
P
2

Which one is faster:

  • if you want full filenames+paths, sorted, glob is practically unbeatable.
  • if you want full filenames+paths unsorted, use glob with GLOB_NOSORT.
  • if you want only the names, and no sorting, use opendir + loop.

That's a TLDR.
If you're in a hurry, skip the boring part :)

The boring part

Before you choose, take a step back to understand. You can do tests to compose the exact same result with different methods only to find they have approximately the same time cost. Merely for fetching the information you'll have no real winner.

  1. Dealing with a huge file list, glob will sort faster - it uses the filesystem's sort method which will always be superior. (It knows what it sorts while PHP doesn't, PHP sorts a hashed array of arbitrary strings, it's simply not fair to compare them.)

  2. You'll probably want to filter your list by some extensions or filename masks for which glob is really efficient. You have fnmatch() of course, but calling it every time will never be faster than a system-level filter trained for this very job.

  3. On the other hand, glob returns a significantly bigger amount of text (each name with full path) so with a lot of files you may run into memory allocation limits. For a zillion files, glob is not your friend.

  4. Some mentioned recursion; careful with that. Yes you can do this: {,*/,*/*/,*/*/*/} with GLOB_BRACE, and it has the benefit of scanning only a finite depth (a blessing, if you ask me), but making glob do this scan for you will be less efficient than a well-written recursive function. (In real-life situations, avoiding huge and irrelevant folders like .git or .phpintel will make quite a difference, and you can't do that with glob; then again, what's best depends on your use case.)

Phlebotomy answered 17/4, 2017 at 21:44 Comment(0)
H
2

OpenDir is more Faster...

<?php
    
    
    $path = "/var/Upload/gallery/TEST/";
    $filenm = "IMG20200706075415";
    
    function microtime_float()
    {
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }

    
    echo "<br> <i>T1:</i>".$t1 = microtime_float();
    
    echo "<br><br> <b><i>Glob :</i></b>";
    foreach( glob($path.$filenm.".*") as $file )
    {
        echo "<br>".$file;
    }
    
    echo "<br> <i>T2:</i> ".$t2 = microtime_float();
    
    echo "<br><br> <b><i>OpenDir :</b></i>";
    function resolve($name)
    {
        // reads informations over the path
        $info = pathinfo($name);
        if (!empty($info['extension']))
        {
            // if the file already contains an extension returns it
            return $name;
        }
        
        $filename = $info['filename'];
        $len = strlen($filename);
        // open the folder
        $dh = opendir($info['dirname']);
        if (!$dh)
        {
            return false;
        }
        
        // scan each file in the folder
        while (($file = readdir($dh)) !== false)
        {
            if (strncmp($file, $filename, $len) === 0)
            {
                if (strlen($name) > $len)
                {
                    // if name contains a directory part
                    $name = substr($name, 0, strlen($name) - $len) . $file;
                }
                else
                {
                    // if the name is at the path root
                    $name = $file;
                }
                closedir($dh);
                return $name;
            }
        }
        // file not found
        closedir($dh);
        return false;
    }
    
    $file = resolve($path.$filenm);
    echo "<br>".$file;
    
    echo "<br> <i>T3:</i> ".$t3 = microtime_float();
    
    echo "<br><br>&emsp; <b>glob time:</b> ". $gt= ($t2 - $t1) ."<br><b>opendir time:</b>". $ot = ($t3 - $t2) ;
    
    echo "<u>". (( $ot < $gt ) ? "<br><br>OpenDir is ".($gt-$ot)." more Faster" : "<br><br>Glob is ".($ot-$gt)." moreFaster ") . "</u>";
?>

Output:

T1:1620133029.7558

Glob :
/var/Upload/gallery/TEST/IMG20200706075415.jpg
T2: 1620133029.7929

OpenDir :
/var/Upload/gallery/TEST/IMG20200706075415.jpg
T3: 1620133029.793

  glob time:0.037137985229492
opendir time:5.9843063354492E-5

OpenDir is 0.037078142166138 more Faster
Harrisharrisburg answered 4/5, 2021 at 13:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.