PHP-скрипты: оптимизация копирования файлов
Октябрь 31, 2007
В прошлой статье мы убедились в том, что запуск бинарных файлов должен компенсироваться временем исполнения скриптов. Сегодня мы тестируем функцию копирования файлов из одной директории в другую.
На текущий момент я вижу много вариантов развития данного действия.
1. Использование стандартных функций:
— листинг директории и использования функции copy для каждого из файлов
— листинг директории и использования более низкоуровневых функций, реализующих копирование в следующих комбинациях
fopen ('File', 'r+b') — fput
fopen ('File', 'r+b') — fwrite
2. Использование бинарника cp из стандартной поставки Linux-системы
— для каждого из файлов
— сразу для всех файлов директории
Для теста я выбираю папку с различными типами файлов: текстовые, графические, бинарные, архивы, mp3 (всего — на 24.8mb)
На вскидку, предполагаю следующий вариант развития событий
Быстрее всех справится с задачей бинарник с копированием файлов по маске «*» из папки в папку.
После будет бинарник с пофайловым копированием.
Далее — стандартная функция copy
Далее — примерно одинаково fput/fwrite с 4Kb буфером.
Начнем, пожалуй ![]()
В качестве основы для копирования файлов я взял либу, которая широко распространена на просторах сети (дабы не давать читателю оснований для подозрений :)) и выдрал оттуда следующий код:
<?php
$d = @opendir („.“);
while (($e=readdir ($d)) !== false)
{
if ($e=='.' || $e=='...') continue;
if (!@is_dir ($e))
{ /* — COPY PROCESS — */ };
}?>
Для тестировния быстродействия мы используем скрипты из предыдущей статьи (стандартные функции).
Чуток поработав, мы получаем следующий код для стандартной функции copy
<?php
$from = '/home/jeurey/testdir';
$to = $from.'/dest';echo '
Тестировние стандартной функции copy на предмет целесообразности использования в копировании файлов
';
$av_time_arr = array ();
$tmp_arr = array ();$tmp_arr = explode (' ',microtime ());
$ex_start_mtime = $tmp_arr[0]+$tmp_arr[1];$d = @opendir („/home/jeurey/testdir“);
while (($e=readdir ($d)) !== false)
{
if ($e=='.' || $e=='...') continue;
if (!@is_dir ($e))
{ echo 'COPY PROCESS '.$e;
if (copy ($from.'/'.$e, $to.'/'.$e)) echo ' done';
echo '
'."\n";
}}
$tmp_arr = explode (' ', microtime ());
$ex_stop_mtime= $tmp_arr[0]+$tmp_arr[1];
$ex_mtime = ($ex_stop_mtime-$ex_start_mtime);echo 'Время старта скрипта: '.$ex_start_mtime.' cек
';
echo 'Время остановки скрипта: '.$ex_stop_mtime.' сек
';
echo 'Время работы скрипта: '.$ex_mtime.' секунд
';?>
Результат работы:
COPY PROCESS cron.log2.txt done
COPY PROCESS d done
COPY PROCESS pdt-all-in-one-incubation-S20070910_RC1-linux-gtk.tar.gz done
COPY PROCESS Firefox_wallpaper.png done
COPY PROCESS dest
COPY PROCESS nautilus-debug-log.txt done
COPY PROCESS pdt-all-in-one-1.0-R20070917-win32.zip done
COPY PROCESS templates.tar.gz done
Время старта скрипта: 1193827626.44 cек
Время остановки скрипта: 1193827658.82 сек
Время работы скрипта: 32.3768770695 секунд
Переходим к тестированию метода fread/fputs
<?php$from = '/home/jeurey/testdir';
$to = $from.'/dest';echo '<h2>Тестировние стандартной функций fopen_fput на предмет целесообразности использования в копировании файлов</h2>';
$av_time_arr = array ();
$tmp_arr = array ();$tmp_arr = explode (' ',microtime ());
$ex_start_mtime = $tmp_arr[0]+$tmp_arr[1];$d = @opendir ($from);
while (($e=readdir ($d)) !== false)
{
if ($e=='.' || $e=='...') continue;
if ($e != 'dest')
{ echo 'COPY PROCESS '.$e;$fR = fopen ($from.'/'.$e,'r+b');
$fW = fopen ($to.'/'.$e,'w+b');
while (!feof ($fR))
{ fputs ($fW,fread ($fR,4096)); //Буфер в 4кб
}
fclose ($fR);
fclose ($fW);
if (filesize ($to.'/'.$e)>0) echo ' done';
echo '<br />'."\n";
}}
$tmp_arr = explode (' ', microtime ());
$ex_stop_mtime= $tmp_arr[0]+$tmp_arr[1];
$ex_mtime = ($ex_stop_mtime-$ex_start_mtime);echo 'Время старта скрипта: '.$ex_start_mtime.' cек<br />';
echo 'Время остановки скрипта: '.$ex_stop_mtime.' сек<br />';
echo 'Время работы скрипта: '.$ex_mtime.' секунд<br />';?>
Результаты работы
не утешают: время выполнения скрипта больше 100 секунд. Сколько — не важно, главное, что копирование данным методом нам не подходит.
И, наконец, последний, заключительный тест. Используем бинарник /bin/cp для копирования файлов. На него я делаю ставку
<?php
echo '<h2>Тестировние стандартных функции на предмет скорости копирования</h2>';$from = '/home/jeurey/testdir';
$to = $from.'/dest';$av_time_arr = array ();
$tmp_arr = array ();$tmp_arr = explode (' ',microtime ());
$ex_start_mtime = $tmp_arr[0]+$tmp_arr[1];exec ('sudo cp '.$from.'/* '.$to);
$tmp_arr = explode (' ', microtime ());
$ex_stop_mtime= $tmp_arr[0]+$tmp_arr[1];
$ex_mtime = ($ex_stop_mtime-$ex_start_mtime);echo 'Время старта скрипта: '.$ex_start_mtime.' cек<br />';
echo 'Время остановки скрипта: '.$ex_stop_mtime.' сек<br />';
echo 'Время работы скрипта: '.$ex_mtime.' секунд<br />';
?>
Ну, и результат, конечно
Время старта скрипта: 1193829335.65 cек
Время остановки скрипта: 1193829337.82 сек
Время работы скрипта: 2.16994690895 секунд
Думаю, целесообразность использования бинаря Вам уже ясна.
Good Luck, как говорится