2009-09-26 53 views
2

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

我通过他们的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。或者是?

您可以提供其他帮助吗?

+0

Czn you post some code?你在做2300个API调用吗? – Eineki 2009-09-26 12:42:38

+0

是的,我正在做2 300个API调用。 – 2009-09-26 12:52:38

+0

是否与此类似? http://ws.audioscrobbler.com/2.0/?method=library。getartists&api_key = b25b959554ed76058ac220b7b2e0a026&user = joanofarctan – Eineki 2009-09-26 12:57:58

回答

1

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

至少从内存加载应该加快一点事情,你也在加载xml的进程是什么样的处理?你确定你的加工是有效的吗?

+0

这不是处理,我测试过了。这是使用“simplexml_load_file”的行为...所以你说我应该从last.fm得到xml,然后在本地加载它? – 2009-09-26 12:55:34

+0

从内存中加载至少会有少许io – RageZ 2009-09-26 13:04:44

1

20kb * 2300个用户是〜45MB。如果以25kB/sec的速度下载,只需要30分钟即可下载数据,更不用说解析它了。

+0

哇,可能是这个......但数据从服务器下载到服务器。它不能这么慢。 – 2009-09-26 13:09:06

0

确保您从last.fm下载的XML是经过压缩的。您可能需要包含正确的HTTP标头才能告诉服务器您支持gzip。它会加快下载速度,但会使用非缩放部分来占用更多的服务器资源。

也可以考虑使用异步下载来释放服务器资源。它不一定会加快这个过程,但它应该让服务器管理员感到高兴。

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

0

我认为每秒有1个API调用的限制。我不确定这个政策是通过代码实施的,但它可能与它有关。如果你认为这是事实,你可以询问IRC的Last.fm工作人员 #audioscrobbler。

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; }