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

时间:2011-05-02 09:49:01

标签: php algorithm io

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

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

文件名的格式如下: Y-M-D-title.ext(其中Y为年,M为月,D为日)

我实际上使用glob来列出所有文件并创建我的数组: 以下是创建数组"年份"的代码示例。或"月" (它只用于只有一个参数的函数 - > $ 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 正在&#34;年&#34;,&#34;月&#34;等等..)

它返回一个填充了我需要的信息的数组,然后我可以循环创建我的统计文件。 每次启动PHP脚本时都会执行此过程。


我的问题是:这段代码是最优的(当然不是),我可以做些什么来从我的代码中挤出一些果汁? 我不知道如何缓存它(即使它可能),因为涉及很多I / O.

如果树形结构与平面结构相比可以改变,我可以改变树形结构,但是从我的测试中发现它看起来平坦是最好的。

我已经考虑过制作一个小小的&#34;助推器&#34;在C中只进行运算,但是由于它的I / O限制,我不认为它会产生巨大的差异,并且应用程序与共享主机用户的兼容性会低很多。

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

1 个答案:

答案 0 :(得分:0)

首先,您应该使用DirectoryIterator而不是glob函数。当涉及到scandir vs opendir vs glob时,glob就像它一样慢。

另外,当你处理大量文件时,你应该尝试在一个循环中进行所有处理,php函数调用相当慢。

我看到你正在使用未设置($ info);但是在你制作的每个循环中,$ info都会获得新的价值。 Php会自己进行垃圾收集,如果你担心的话。 Unset是一个语言结构而不是一个函数,应该非常快,但是当不需要使用时,它仍然会使整个事情变得有点慢。

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

最后你的脚本似乎处理了很多字符串处理。您可能想要考虑一些“序列化数据和base64编码/解码”解决方案,但您应该专门进行基准测试,可能更快,可能会更慢,取决于您的整个代码。 (我的想法是,序列化/反序列化MIGHT运行速度更快,因为这些是本机php函数,而字符串处理的自定义函数更慢)。

我的答案与I / O无关,但我希望它有所帮助。