simplexml_load_file()的速度有多快?

时间:2009-09-26 12:30:27

标签: php xml api simplexml last.fm

我通过last.fm的API为我的mashup获取大量用户数据。我每周都这样做,因为我必须收集收听数据。

我通过REST API和XML获取数据:更具体地说是simplexml_load_file()

脚本花了很长时间。对于大约2 300个用户,该脚本需要30分钟才能获取艺术家的名字。我现在必须解决它,否则我的托管公司将关闭我。我已经抽出了所有其他选项,正是XML正在减慢脚本。

我现在必须弄清楚last.fm是否有一个缓慢的API(或者在没有他们告诉我们的情况下限制调用),或者PHP的simplexml是否实际上相当慢。

我意识到的一件事是XML请求比我需要的要多得多,但我无法通过API限制它(即只给我3个波段的信息,而不是70个)。但“大”XML文件只能达到大约20kb。可能是这样,这会减慢脚本的速度吗?必须为2300个用户中的每一个加载20kb的对象?

没有意义,它可能是......我只需要确认它可能是last.fm的慢API。或者是吗?

您可以提供其他任何帮助吗?

5 个答案:

答案 0 :(得分:1)

我不认为简单的xml是那么慢,它很慢,因为它是一个解析器,但我认为2300 curl / file_get_contents需要花费更多的时间。另外为什么不获取数据并只使用simplexml_load_string,你真的需要将这些文件放在服务器的磁盘上吗?

至少从内存加载应该加快一些事情,你还在加载的xmls上进行什么样的处理?你确定你的处理效率是多少吗?

答案 1 :(得分:1)

20kb * 2300用户约为45MB。如果你以~25kB /秒的速度下载,下载数据需要30分钟,更不用解析了。

答案 2 :(得分:0)

确保从last.fm下载的XML是gzip压缩的。您可能必须包含正确的HTTP标头以告知服务器您支持gzip。它会加快下载速度,但使用ungzipping部分会占用更多服务器资源。

还考虑使用异步下载来释放服务器资源。它不一定会加快进程,但它应该让服务器管理员满意。

如果XML本身很大,请使用SAX解析器,而不是DOM解析器。

答案 3 :(得分:0)

我认为每秒有一次API调用限制。我不确定这个策略是通过代码强制执行的,但它可能与它有关。如果您认为是这种情况,可以在irc.last.fm #audioscrobbler上询问IRC上的Last.fm工作人员。

答案 4 :(得分:0)

根据建议,使用simplexml_load_string获取数据并进行解析,而不是依赖simplexml_load_file - 它的速度大约是原来的两倍。这是一些代码:

function simplexml_load_file2($url, $timeout = 30) {


// parse domain etc from url
$url_parts = parse_url($url);
if(!$url_parts || !array_key_exists('host', $url_parts)) return false;

$fp = fsockopen($url_parts['host'], 80, $errno, $errstr, $timeout);
if($fp) 
{
    $path = array_key_exists('path', $url_parts) ? $url_parts['path'] : '/'; 
    if(array_key_exists('query', $url_parts)) 
    {
        $path .= '?' . $url_parts['query'];
    }

    // make request
    $out = "GET $path HTTP/1.1\r\n";
    $out .= "Host: " . $url_parts['host'] . "\r\n";
    $out .= "Connection: Close\r\n\r\n";

    fwrite($fp, $out);

    // get response
    $resp = "";
    while (!feof($fp))
    {
        $resp .= fgets($fp, 128);
    }
    fclose($fp);

    $parts = explode("\r\n\r\n", $resp);
    $headers = array_shift($parts);

    $status_regex = "/HTTP\/1\.\d\s(\d+)/";
    if(preg_match($status_regex, $headers, $matches) && $matches[1] == 200)
    {
        $xml = join("\r\n\r\n", $parts);    
        return @simplexml_load_string($xml);            
    }   

}
return false; }