Чтение и скандир
1] Какая из функций быстрее?
2] какие отличия?
Differences
1] readdir возвращает имя следующей записи в каталоге. Scandir возвращает массив файлов и каталогов из каталога.
2] readdir должен иметь дескриптор ресурса, пока все записи не будут прочитаны. scandir, возможно, создает массив всех записей и закрывает ручку resouce?
Ответы
Ответ 1
Просто получая результаты (ничего не делая), 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(), он будет медленнее.
Ответ 2
На самом деле это зависит от того, что вы делаете с данными.
Если вы переходите через запись, вы должны использовать readdir
, если вам действительно нужен список записей в памяти, вы должны использовать scandir
.
В любом случае нет смысла копировать информацию в память, когда вы собираетесь использовать ее по очереди. Ленькая оценка - это, безусловно, способ пойти в этом случае.
Я бы предположил, что scandir
является всего лишь оберткой вокруг того же самого, что readdir
вызывает, и поэтому будет медленнее.
Ответ 3
Сделал еще несколько сравнений времени для чтения всего дерева каталогов с большим количеством файлов и каталогов:
-
вызов filetype() == "dir" явно быстрее, чем вызов is_dir()
-
вызовы opendir/readdir намного быстрее, чем RecursiveDirectoryIterator
-
построение дерева каталогов с использованием рекурсивных вызовов глубины первого или линейного значения не имеет значения
Вышеприведенные тесты, которые выполняются в Windows на локальном SSD, локальном USB и сетевом диске с постоянными результатами. Запуск на сетевом диске был в 180 раз медленнее, чем локальные диски - несмотря на гигабитный и быстрая система ReadyNAS!
Количество записей, обрабатываемых в секунду, варьировалось от 115 с самым медленным кодом до сетевого диска почти до 65 000 для самого быстрого кода на накопителе USB 3.0 - из-за кэширования, конечно.
Но огромная разница для сетевого диска заставляет вас задаться вопросом, что происходит внутри PHP, поскольку простая команда dir и ls в Linux по тем же файлам намного быстрее.
Продолжение следует...
Ответ 4
Я сделал несколько тестов. (Благодаря 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:
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 файлов. Если файлы увеличиваются, результаты могут быть разными)
Ответ 5
Я знаю, что этот вопрос может быть не актуальным сейчас, но добавить. Я сделал несколько тестов (например, 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;
Результаты (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 (tm) HD (4 ядра)
MEM: 8G
PHP: 5.6.29