1] Какая из функций быстрее?
2] каковы различия?
Differences
1] readdir возвращает имя следующей записи в каталоге. Scandir возвращает массив файлов и каталогов из каталога.
2] readdir должен иметь дескриптор ресурса, пока все записи не будут прочитаны. scandir, возможно, создает массив всех записей и закрывает ручку resouce?
Только получение результатов (без каких-либо действий), readdir – это минимум быстрее:
<?php $count = 10000; $dir = '/home/brati'; $startScan = microtime(true); for ($i=0;$i<$count;$i++) { $array = scandir($dir); } $endScan = microtime(true); $startRead = microtime(true); for ($i=0;$i<$count;$i++) { $handle = opendir($dir); while (false !== ($entry = readdir($handle))) { // We do not know what to do } } $endRead = microtime(true); echo "scandir: " . ($endScan-$startScan) . "\n"; echo "readdir: " . ($endRead-$startRead) . "\n";
дает:
== RUN 1 == scandir: 5.3707950115204 readdir: 5.006147146225 == RUN 2 == scandir: 5.4619920253754 readdir: 4.9940950870514 == RUN 3 == scandir: 5.5265231132507 readdir: 5.1714680194855
Тогда, конечно, это зависит от того, что вы намереваетесь сделать. Если вам нужно написать еще один цикл с помощью scandir (), он будет медленнее.
Это зависит от того, что вы делаете с данными.
Если вы проходите через запись, вы должны использовать readdir
, если вам действительно нужен список записей в памяти, вы должны использовать scandir
.
Нет смысла копировать информацию в память, когда вы собираетесь использовать ее в любом случае. Ленькая оценка, безусловно, способ пойти в этом случае.
Я бы предположил, что scandir
– это всего лишь обертка вокруг того же самого, что и readdir
, и поэтому будет медленнее.
Еще несколько сравнений времени для чтения всего дерева каталогов с большим количеством файлов и каталогов:
тип файла вызова () == "dir" явно быстрее, чем вызов is_dir ()
вызовы opendir / readdir намного быстрее, чем RecursiveDirectoryIterator
создание дерева каталогов с использованием рекурсивных вызовов глубины первого или линейного значения не имеет значения
Вышеприведенные тесты, которые выполняются в Windows на локальном SSD, локальном USB и сетевом диске с постоянными результатами. Работа на сетевом диске была в 180 раз медленнее, чем локальные диски – несмотря на гигабитный и быстродействующий блок ReadyNAS!
Количество записей, обрабатываемых в секунду, варьировалось от 115 с самым медленным кодом до сетевого диска почти до 65 000 для самого быстрого кода на USB 3.0 накопитель – из-за кэширования, конечно.
Но огромная разница для сетевого диска заставляет вас задаться вопросом, что происходит внутри PHP, поскольку простая команда dir и ls в Linux по тем же файлам намного быстрее.
Продолжение следует…
Я сделал несколько тестов. (Благодаря Aufziehvogel для строительства)
$count = 100000; $dir = dirname(__FILE__); $startScan = microtime(true); for ($i=0;$i<$count;$i++) { $array = scandir($dir); } $endScan = microtime(true); $startRead = microtime(true); for ($i=0;$i<$count;$i++) { $handle = opendir($dir); while (false !== ($entry = readdir($handle))) { // We do not know what to do } } $endRead = microtime(true); $startGlob = microtime(true); for ($i=0;$i<$count;$i++) { $array3 = glob('*'); } $endGlob = microtime(true); echo "scandir: " . ($endScan-$startScan) . "\n"; echo "readdir: " . ($endRead-$startRead) . "\n"; echo "glob : " . ($endGlob-$startGlob) . "\n";
Результаты Linux Server:
scandir: 0.82553291320801 readdir: 0.91677618026733 glob : 0.76309990882874
Это результаты с 4 ядер (8 потоков) Intel E3-1240 Cpu linux + сервер Apache.
Но результаты Windows Servers противоположны. Сервер Windows + Apache – Intel Q8400 4 Core (4 Темы)
Результаты Windows Server:
$count = 10000; // it was on linux 100000 :) scandir: 0.61557507515 readdir: 0.614650011063 glob : 1.92112612724
(Папка содержит 13 файлов. Если файлы увеличиваются, результаты могут быть разными)
Я знаю, что этот вопрос может быть не актуальным сейчас, но добавить, что я провел несколько тестов (например, Aufziehvogel и Sayahan) с небольшой разницей – в каталоге с 1 000 000 маленьких (несколько байтов) файлов.
$dir = dirname(__FILE__) . '/dir'; $startScan = microtime(true); $array = scandir($dir); for ($i = 0, $j = count($array); $i < $j; $i++) { // Code } $endScan = microtime(true); unset($array); $startRead = microtime(true); $handle = opendir($dir); while (false !== ($entry = readdir($handle))) { // Code } $endRead = microtime(true); unset($handle); unset($entry); $startDir = microtime(true); $files = new DirectoryIterator($dir); foreach ($files as $file) { // Code } $endDir = microtime(true); unset($files); echo 'scandir: ', ($endScan - $startScan), PHP_EOL; echo 'readdir: ', ($endRead - $startRead), PHP_EOL; echo 'DirectoryIterator: ', ($endDir - $startDir), PHP_EOL;
с$dir = dirname(__FILE__) . '/dir'; $startScan = microtime(true); $array = scandir($dir); for ($i = 0, $j = count($array); $i < $j; $i++) { // Code } $endScan = microtime(true); unset($array); $startRead = microtime(true); $handle = opendir($dir); while (false !== ($entry = readdir($handle))) { // Code } $endRead = microtime(true); unset($handle); unset($entry); $startDir = microtime(true); $files = new DirectoryIterator($dir); foreach ($files as $file) { // Code } $endDir = microtime(true); unset($files); echo 'scandir: ', ($endScan - $startScan), PHP_EOL; echo 'readdir: ', ($endRead - $startRead), PHP_EOL; echo 'DirectoryIterator: ', ($endDir - $startDir), PHP_EOL;
с$dir = dirname(__FILE__) . '/dir'; $startScan = microtime(true); $array = scandir($dir); for ($i = 0, $j = count($array); $i < $j; $i++) { // Code } $endScan = microtime(true); unset($array); $startRead = microtime(true); $handle = opendir($dir); while (false !== ($entry = readdir($handle))) { // Code } $endRead = microtime(true); unset($handle); unset($entry); $startDir = microtime(true); $files = new DirectoryIterator($dir); foreach ($files as $file) { // Code } $endDir = microtime(true); unset($files); echo 'scandir: ', ($endScan - $startScan), PHP_EOL; echo 'readdir: ', ($endRead - $startRead), PHP_EOL; echo 'DirectoryIterator: ', ($endDir - $startDir), PHP_EOL;
с$dir = dirname(__FILE__) . '/dir'; $startScan = microtime(true); $array = scandir($dir); for ($i = 0, $j = count($array); $i < $j; $i++) { // Code } $endScan = microtime(true); unset($array); $startRead = microtime(true); $handle = opendir($dir); while (false !== ($entry = readdir($handle))) { // Code } $endRead = microtime(true); unset($handle); unset($entry); $startDir = microtime(true); $files = new DirectoryIterator($dir); foreach ($files as $file) { // Code } $endDir = microtime(true); unset($files); echo 'scandir: ', ($endScan - $startScan), PHP_EOL; echo 'readdir: ', ($endRead - $startRead), PHP_EOL; echo 'DirectoryIterator: ', ($endDir - $startDir), PHP_EOL;
этот$dir = dirname(__FILE__) . '/dir'; $startScan = microtime(true); $array = scandir($dir); for ($i = 0, $j = count($array); $i < $j; $i++) { // Code } $endScan = microtime(true); unset($array); $startRead = microtime(true); $handle = opendir($dir); while (false !== ($entry = readdir($handle))) { // Code } $endRead = microtime(true); unset($handle); unset($entry); $startDir = microtime(true); $files = new DirectoryIterator($dir); foreach ($files as $file) { // Code } $endDir = microtime(true); unset($files); echo 'scandir: ', ($endScan - $startScan), PHP_EOL; echo 'readdir: ', ($endRead - $startRead), PHP_EOL; echo 'DirectoryIterator: ', ($endDir - $startDir), PHP_EOL;
не$dir = dirname(__FILE__) . '/dir'; $startScan = microtime(true); $array = scandir($dir); for ($i = 0, $j = count($array); $i < $j; $i++) { // Code } $endScan = microtime(true); unset($array); $startRead = microtime(true); $handle = opendir($dir); while (false !== ($entry = readdir($handle))) { // Code } $endRead = microtime(true); unset($handle); unset($entry); $startDir = microtime(true); $files = new DirectoryIterator($dir); foreach ($files as $file) { // Code } $endDir = microtime(true); unset($files); echo 'scandir: ', ($endScan - $startScan), PHP_EOL; echo 'readdir: ', ($endRead - $startRead), PHP_EOL; echo 'DirectoryIterator: ', ($endDir - $startDir), PHP_EOL;
Результаты (HDD):
scandir: 1.9403479099274 readdir: 0.79462885856628 DirectoryIterator: 0.5853099822998
Результаты (SSD):
scandir: 0.83593201637268 readdir: 0.35835003852844 DirectoryIterator: 0.28022909164429
Процессор: AMD A10-4600M APU с графикой Radeon ™ HD (4 ядра)
MEM: 8G
PHP: 5.6.29