Crunch много файлов для создания файла статистики - PullRequest
1 голос
/ 02 мая 2011

У меня есть куча файлов, которые мне нужно обработать, и я беспокоюсь о масштабируемости и скорости.

Имя файла и файловые данные (только первая строка) хранятся в массиве в ОЗУ для создания статических файлов позже в скрипте. Файлы должны оставаться файлами и не могут быть помещены в базы данных.

Имя файла отформатировано следующим образом: Y-M-D-title.ext (где Y - год, M - месяц, D - день)

Я на самом деле использую glob, чтобы вывести список всех файлов и создать свой массив: Вот пример кода, создающего массив «for year» или «month» (он используется в функции только с одним параметром -> $ period)

[...]
function create_data_info($period=NULL){
    $data = array();
    $files = glob(ROOT_DIR.'/'.'*.ext');
    $size = sizeOf($files);
    $existing_title = array(); //Used so we can handle having the same titles two times at different date.

    if (isSet($period)){
        if ( "year" === $period ){
            for ($i = 0; $i < $size; $i++) {
                $info = extract_info($files[$i], $existing_file);
                //Create the data array with all the data ordered by year/month/day
                $data[(int)$info[5]][] = $info;
                unset($info);
            }
        }elseif ( "month" === $period ){
            for ($i = 0; $i < $size; $i++) {
                $info = extract_info($files[$i], $existing_file);
                $key = $info[5].$info[6];
                //Create the data array with all the data ordered by year/month/day
                $data[(int)$key][] = $info;
                unset($info);
            }
        }
    }
    [...]
}

function extract_info($file, &$existing){
    $full_path_file = $file;
    $file = basename($file);

    $info_file = explode("-", $file, 4);

    $filetitle = explode(".", $info_file[3]);
    $info[0] = $filetitle[0];

    if (!isSet($existing[$info[0]]))
        $existing[$info[0]] = -1;
    $existing[$info[0]] += 1;
    if ($existing[$info[0]] > 0)
        //We have already found a post with this title
        //the creation of the cache is based on info[4] data for the filename
        //so we need to tune it
        $info[0] = $info[0]."-".$existing[$info[0]];

    $info[1] = $info_file[3];
    $info[2] = $full_path_file;
    $post_content = file(ROOT_DIR.'/'.$file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    $info[3] = $post_content[0]; //first line of the files
    unset($post_content);

    $info[4] = filemtime(ROOT_DIR.'/'.$file);

    $info[5] = $info_file[0]; //year
    $info[6] = $info_file[1]; //month
    $info[7] = $info_file[2]; //day
    return $info;
}

Так что в моем скрипте я вызываю только create_data_info ( PERIOD ) ( PERIOD - это "год", "месяц" и т. Д.)

Возвращает массив, заполненный необходимой мне информацией, и затем я могу циклически обработать ее для создания файлов статистики. Этот процесс выполняется каждый раз, когда запускается PHP-скрипт.


Мой вопрос: является ли этот код оптимальным (конечно, нет) и что я могу сделать, чтобы выжать немного сока из моего кода? Я не знаю, как я могу это кэшировать (даже если это возможно), так как в этом задействовано много операций ввода-вывода.

Я могу изменить древовидную структуру, если она может изменить вещи по сравнению с плоской структурой, но из того, что я обнаружил в своих тестах, она кажется плоской - лучше.

Я уже думал о создании небольшого «бустера» в C, выполняющего только сжатие, но я, поскольку он связан с вводом / выводом, не думаю, что это будет иметь огромное значение, и приложение будет гораздо менее совместимым для пользователи виртуального хостинга.

Большое спасибо за ваш вклад, я надеюсь, что я был достаточно ясен здесь. Дайте мне знать, если вам нужны разъяснения (и забудьте мои английские ошибки).

1 Ответ

0 голосов
/ 04 мая 2011

Для начала вы должны использовать DirectoryIterator вместо функции glob.Когда дело доходит до scandir vs opendir vs glob, glob работает настолько медленно, насколько это возможно.

Кроме того, когда вы работаете с большим количеством файлов, вы должны попытаться выполнить всю обработку внутри одного цикла, функция phpвызовы довольно медленные.

Я вижу, вы используете unset ($ info);тем не менее, в каждом цикле, который вы делаете, $ info получает новое значение.Php делает свою собственную сборку мусора, если это ваше беспокойство.Unset - это языковая конструкция, а не функция, которая должна быть довольно быстрой, но при ее использовании она не нужна, но все равно немного замедляется.

Вы передаете $ Существующий в качестве ссылки.Есть ли практический результат для этого?По моему опыту, ссылки делают вещи медленнее.

И, наконец, ваш скрипт, похоже, имеет дело с большой обработкой строк.Возможно, вы захотите рассмотреть какое-то решение «сериализации данных и кодирования / декодирования base64», но вам следует сравнить, что конкретно, может быть быстрее, может быть медленнее, в зависимости от всего вашего кода.(Моя идея заключается в том, что сериализация / десериализация МОЖЕТ выполняться быстрее, поскольку это собственные функции php, а пользовательские функции с обработкой строк медленнее).

Мой ответ не был связан с вводом / выводом, но я надеюсь, что он был полезен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...