我基本上是从各种API中获取数据,并使用PHP将它们组合在一起-就像web mashup一样。我目前使用4个foreeach语句将收集到的数据插入到各自的数组中。我认为当前的代码效率很低,因为加载显示PHP数据的页面大约需要3秒。在过去,我只有一个大的foreach循环来一次遍历所有的数据并打印它们。但对我来说,这也是低效的。
那么,我如何才能让我的代码在处理速度方面更有效率呢?我见过一些混搭网站,比如Soundeer,它们的加载时间大约是一秒钟。这是因为他们的代码效率吗?
我使用的代码是:
$echonest_uri = simplexml_load_file("http://developer.echonest.com/api/v4/artist/search?api_key=$APIkey&style=rap&results=10&start=$element_num&bucket=id:deezer&bucket=images&sort=familiarity-desc&format=xml");
//Swap the comments for when in UWE or not
//$echonest_xml = new SimpleXMLElement($echonest_uri);
$echonest_xml = $echonest_uri;
$artist_name = array();
$artist_image = array();
$echonest_id = array();
$full_deezer_id = array();
$deezer_id = array();
$num_of_albums = array();
//Loop through each entries in the id_arr and make each image of the artist a link to the album page passing all the relevant information.
foreach($echonest_xml->artists->artist as $artist){
$artist_name[] = $artist->name;
$artist_image[] = $artist->images->image[0]->url;
$echonest_id[] = $artist->id;
$full_deezer_id[] = $artist->foreign_ids->foreign_id->foreign_id;
}
foreach($full_deezer_id as $key => $value){
preg_match('#deezer:artist:([A-Z,a-z,0-9]+)#', $value, $id);
$deezer_id[] = (string)$id[1];
}
foreach($deezer_id as $id_index => $id){
$deezer_xml = simplexml_load_file("http://api.deezer.com/2.0/artist/$id/albums&output=xml");
$num_of_albums[] = $deezer_xml->total;
}
//The variable which will contain the HTML code to display the artists.
$output = null;
foreach($deezer_id as $key => $value){
$fav_count_query = "SELECT COUNT(user_index) FROM fav_artist WHERE artist_deezer_id = '$value'";
$fav_count_resource = $mysqli->query($fav_count_query);
$fav_count = $fav_count_resource->fetch_assoc();
$output .= <<<HERE
<div class="artist-container">
<a href="albums.php?echonest_id={$echonest_id[$key]}&deezer_id={$deezer_id[$key]}&artist_name={$artist_name[$key]}&artist_image={$artist_image[$key]}&num_of_albums={$num_of_albums[$key]}" class="artist-image">
<img src="{$artist_image[$key]}" alt="{$artist_name[$key]}" title="{$artist_name[$key]}"/>
</a>
<a href="albums.php?echonest_id={$echonest_id[$key]}&deezer_id={$deezer_id[$key]}&artist_name={$artist_name[$key]}&artist_image={$artist_image[$key]}&num_of_albums={$num_of_albums[$key]}" class="artist-name">
{$artist_name[$key]}
</a>
<a href="albums.php?echonest_id={$echonest_id[$key]}&deezer_id={$deezer_id[$key]}&artist_name={$artist_name[$key]}&artist_image={$artist_image[$key]}" class="album-number">Albums:
{$num_of_albums[$key]}
</a>
</div>
HERE;
}发布于 2013-01-20 04:20:12
您的代码很可能不会因为多个foreach循环而变慢(老实说,在实际场景中您不会感觉到区别)。在这里让你痛苦的是从外部网站下载一些东西。
我的解决方案是每隔5分钟自动下载一次(通过cronjob,或者只是在用户访问页面时),如果不到5分钟,则在服务器上显示一个缓存版本。
也就是说,这似乎是一个搜索,所以结果很可能不会有太大变化。也许可以有一个1天的缓存呢?(每个新的搜索查询仍然需要3秒,但如果您希望许多用户进行相同的查询,那么这将使您的站点看起来快得多)。
测试的一个简单方法是在代码中出现错误的地方,使用microtime函数。我通常会这样做:
$beforeCall = microtime(true);
$echonest_uri = simplexml_load_file("http://developer.echonest.com/api/v4/artist/search?api_key=$APIkey&style=rap&results=10&start=$element_num&bucket=id:deezer&bucket=images&sort=familiarity-desc&format=xml");
echo "The call took " . number_format(microtime(true) - $beforeCall, 4) . " seconds";如果您正在使用XML (看起来很像),那么您可以使用启用了缓存的SimplePie。在SimplePie's own article on their cache system中有一篇很好的文章,您可以使用set_cache_duration调整缓存持续时间。
发布于 2013-01-20 04:27:29
缓存
最重要的是,您缺少的是缓存。缓存api调用结果的一个简单实现是:
$url = "http://developer.echonest.com/api/v4/artist/search?api_key=$APIkey&style=rap&results=10&start=$element_num&bucket=id:deezer&bucket=images&sort=familiarity-desc&format=xml";
$cacheFile = md5($url) . '.xml';
// If the cache file exists and is less than an hour old - use it.
if (file_exists($cacheFile) && filemtime($cacheFile) > (time() - 3600)) {
$xml = file_get_contents($cacheFile);
// else download it
} else {
$xml = file_get_contents($url);
file_put_contents($cacheFile, $xml);
}
$xml = simplexml_load_file($cacheFile);也就是说,不要在每个请求上都使用api --只与它交谈一次,只要你认为合适/安全,就使用响应(在上面的例子中,使用3600秒-或一个小时)。
这种逻辑最好封装在方法中。
干式代码执行
与缓存相比,不那么重要的是,问题中的代码是4个foreach循环,它们相互提供-这不是编写此类逻辑的有效方式。这是一个好主意,不要在执行代码时重复自己,比如:
foreach($echonest_xml->artists->artist as $artist){
...
$full_deezer_id[] = $artist->foreign_ids->foreign_id->foreign_id;
}
foreach($full_deezer_id as $key => $value){ // <--
...
$deezer_id[] = (string)$id[1];
}
foreach($deezer_id as $id_index => $id){ // <--
...
}
foreach($deezer_id as $key => $value){ // <--可以更好地写成
foreach($echonest_xml->artists->artist as $artist){
processArtist($artist);
}
foreach($buidThis as $row) {因此,编写代码最多循环两次(但最好只循环一次),而不是对同一数据循环四次。
只使用问题中的逻辑,例如,前两个循环可以很容易地组合在一起:
foreach($echonest_xml->artists->artist as $artist){
preg_match('#deezer:artist:([A-Z,a-z,0-9]+)#', $artist->foreign_ids->foreign_id->foreign_id, $id);
$deezer_id[] = (string)$id[1];
}同样的分析应该应用于所有代码:尝试限制迭代/递归逻辑的数量。
https://stackoverflow.com/questions/14418416
复制相似问题