php - 压缩大量文件以生成统计文件

标签 php algorithm io

我有一堆文件需要处理,我担心可扩展性和速度。

文件名和文件数据(仅第一行)存储在 RAM 中的数组中,以便稍后在脚本中创建一些静态文件。 这些文件必须保留为文件,不能放入数据库。

文件名的格式如下: 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 脚本时都会完成此过程。


我的问题是:这段代码是否是最优的(当然不是),我该怎么做才能从我的代码中榨取一些汁液? 我不知道如何缓存它(即使可能),因为涉及很多 I/O。

如果与平面结构相比树结构可以改变一些东西,我可以更改树结构,但根据我的测试发现,平面结构似乎是最好的。

我已经考虑过在 C 中创建一个小的“助推器”,只做处理,但我认为它是 I/O 绑定(bind)的,我认为它不会产生巨大的差异,而且应用程序的兼容性会大大降低共享主机用户。

非常感谢您的输入,我希望我在这里足够清楚。如果您需要澄清,请告诉我(忘记我的英语错误)。

最佳答案

首先你应该使用DirectoryIterator而不是 glob 函数。当谈到 scandir vs opendir vs glob 时,glob 是最慢的。

此外,当您处理大量文件时,您应该尝试在一个循环内完成所有处理,php 函数调用相当慢。

我看到你正在使用 unset($info);然而,在您进行的每个循环中,$info 都会获得新的值(value)。如果您关心的话,Php 会进行自己的垃圾收集。 Unset 是一种语言构造而不是函数,应该非常快,但是当不需要使用时,它仍然会使整个过程变慢一些。

您正在传递 $existing 作为引用。这有实际的结果吗?根据我的经验,引用会使事情变慢。

最后,您的脚本似乎处理了大量的字符串处理。您可能想考虑某种“序列化数据和 base64 编码/解码”解决方案,但您应该具体地对它进行基准测试,可能更快,也可能更慢,具体取决于您的整个代码。 (我的想法是,序列化/反序列化可能运行得更快,因为这些是 native php 函数,而带有字符串处理的自定义函数更慢)。

我的回答与 I/O 不是很相关,但我希望它有帮助。

关于php - 压缩大量文件以生成统计文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5855686/

相关文章:

php - 从多个数组中删除公共(public)项

php - 显示MYSQL数据库中多个表的数据

php - 如何在 symfony 4 中创建自定义表单类型?

algorithm - MSD 与 LSD 基数排序

arrays - 在 ruby​​ 中实现的算法将 1 添加到表示为数组的数字

javascript - 从任意行 X 开始读取超长文件的最快方法

javascript - 在模态中传递一行的 id

linux - Linux 中的 fwrite()、write()、pwrite()、fread()、read()、pread()、fsync() 有什么区别?

java - 具有文件的对象的内存管理。

algorithm - 是否有确定最小可解线性方程组的算法