首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >和高CPU负载

和高CPU负载
EN

Stack Overflow用户
提问于 2014-02-16 21:11:01
回答 3查看 4K关注 0票数 10

我正在使用Laravel 4开发一个简单的RESTful API。我已经设置了一个Route,它调用了我的Controller的一个函数,基本上是这样做的:

  • 如果数据库中有信息,请将其打包到JSON对象中,并返回响应
  • 否则,尝试下载它(html/xml解析),存储它,最后打包JSON响应并发送它。

我注意到,在执行总共1700个请求时,CPU负载(每次只有2个请求)会增加到70-90%。

我是一个完整的php和laravel初学者,我在本教程之后制作了API,也许我做错了什么,或者它只是一个缺乏优化的概念的证明。如何改进这段代码?(启动函数是getGames)您认为所有问题的根源是Laravel还是我应该获得相同的结果,甚至更改框架/使用原始PHP?

UPDATE1 I也设置了一个文件缓存,但是CPU负载仍然是50%左右。

UPDATE2 --我将查询速率设置为每500 is两次,CPU负载降低了12%,因此我猜这段代码缺少队列处理或类似的内容。

代码语言:javascript
复制
class GameController extends BaseController{
    private static $platforms=array(
        "Atari 2600",
        "Commodore 64",
        "Sega Dreamcast",
        "Sega Game Gear",
        "Nintendo Game Boy",
        "Nintendo Game Boy Color",
        "Nintendo Game Boy Advance",
        "Atari Lynx",
        "M.A.M.E.",
        "Sega Mega Drive",
        "Colecovision",
        "Nintendo 64",
        "Nintendo DS",
        "Nintendo Entertainment System (NES)",
        "Neo Geo Pocket",
        "Turbografx 16",
        "Sony PSP",
        "Sony PlayStation",
        "Sega Master System",
        "Super Nintendo (SNES)",
        "Nintendo Virtualboy",
        "Wonderswan");
    private function getDataTGDB($name,$platform){
        $url = 'http://thegamesdb.net/api/GetGame.php?';
        if(null==$name || null==$platform) return NULL;
        $url.='name='.urlencode($name);
        $xml = simplexml_load_file($url);
        $data=new Data;
        $data->query=$name;
        $resultPlatform = (string)$xml->Game->Platform;

        $data->platform=$platform;
        $data->save();
        foreach($xml->Game as $entry){
            $games = Game::where('gameid',(string)$entry->id)->get();
            if($games->count()==0){
                if(strcasecmp($platform , $entry->Platform)==0 || 
                (strcasecmp($platform ,"Sega Mega Drive")==0 && 
                ($entry->Platform=="Sega Genesis" || 
                $entry->Platform=="Sega 32X" || 
                $entry->Platform=="Sega CD"))){
                    $game = new Game;
                    $game->gameid = (string)$entry->id;
                    $game->title = (string)$entry->GameTitle;
                    $game->releasedate = (string)$entry->ReleaseDate;
                    $genres='';
                    if(NULL!=$entry->Genres->genre)
                    foreach($entry->Genres->genre as $genre){
                        $genres.=$genre.',';
                    }
                    $game->genres=$genres;
                    unset($genres);
                    $game->description = (string)$entry->Overview;
                    foreach($entry->Images->boxart as $boxart){
                        if($boxart["side"]=="front"){
                            $game->bigcoverurl = (string)$boxart;
                            $game->coverurl = (string) $boxart["thumb"];
                        } continue;
                    }
                    $game->save();
                    $data->games()->attach($game->id);
                } 
            }
            else foreach($games as $game){
                $data->games()->attach($game->id);
            }
        }
        unset($xml);
        unset($url);
        return $this->printJsonArray($data);
    }

    private function getArcadeHits($name){
        $url = "http://www.arcadehits.net/index.php?p=roms&jeu=";
        $url .=urlencode($name);

        $html = file_get_html($url);

        $data = new Data;
        $data->query=$name;
        $data->platform='M.A.M.E.';
        $data->save();
        $games = Game::where('title',$name)->get();
        if($games->count()==0){
            $game=new Game;
            $game->gameid = -1;
            $title = $html->find('h4',0)->plaintext;
            if("Derniers jeux commentés"==$title)
            { 
                unset($game);
                return Response::json(array('status'=>'404'),200);
            }
            else{
                $game->title=$title;
                $game->description="(No description.)";
                $game->releasedate=$html->find('a[href*=yearz]',0)->plaintext;
                $game->genres = $html->find('a[href*=genre]',0)->plaintext;
                $minithumb = $html->find('img.minithumb',0);
                $game->coverurl = $minithumb->src;
                $game->bigcoverurl = str_replace("/thumb/","/jpeg/",$minithumb->src);
                $game->save();
                $data->games()->attach($game->id);
            }
        }

        unset($html);
        unset($url);
        return $this->printJsonArray($data);
    }

    private function printJsonArray($data){
        $games = $data->games()->get();
        $array_games = array();
        foreach($games as $game){
            $array_games[]=array(
                'GameTitle'=>$game->title,
                'ReleaseDate'=>$game->releasedate,
                'Genres'=>$game->genres,
                'Overview'=>$game->description,
                'CoverURL'=>$game->coverurl,
                'BigCoverURL'=>$game->bigcoverurl
            );
        }
        $result = Response::json(array(
            'status'=>'200',
            'Game'=>$array_games
            ),200);
        $key = $data->query.$data->platform;
        if(!Cache::has($key))
            Cache::put($key,$result,1440);
        return $result;
    }

    private static $baseImgUrl = "";
    public function getGames($apikey,$title,$platform){
            $key = $title.$platform;
            if(Cache::has($key)) return Cache::get($key);
        if(!in_array($platform,GameController::$platforms)) return Response::json(array("status"=>"403","message"=>"non valid platform"));
        $datas = Data::where('query',$title)
                ->where('platform',$platform)
                ->get();
        //If this query has already been done we return data,otherwise according to $platform
        //we call the proper parser.
        if($datas->count()==0){
            if("M.A.M.E."==$platform){
                return $this->getArcadeHits($title);
            }
            else{
                return $this->getDataTGDB($title,$platform);
            }
        } else{
            else return $this->printJsonArray($datas->first());
        }
    }


}
?>
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-02-17 16:48:02

你想从别人的服务器上检索数据。这意味着将CPU“搁置”,直到数据被完全检索。这使得您的代码变得如此"CPU昂贵“(无法找到适合这里=/ )的,因为您的脚本正在等待数据被接收,然后释放脚本(CPU)工作。

I建议您进行异步调用。这将释放您的CPU工作的代码,而您的系统的其他部分是获取您需要的信息。

我希望这会有所帮助!

更新

要做例子,我必须重新考虑您的代码(而且我非常懒!)但是,我可以肯定地告诉您:如果将请求代码(调用其他站点的XML的人)放入队列中,您将获得大量的空闲CPU时间。每个请求都被重定向到一个队列。一旦他们准备好了,你就按你的意愿对待他们。拉勒维尔有一种处理排队问题的漂亮方法。

票数 3
EN

Stack Overflow用户

发布于 2014-02-17 07:44:26

我首先要做的是使用分析器来找出哪些部分需要优化。例如,您可以使用以下内容:

http://xdebug.org/docs/profiler

同样,您也没有指定它是哪种cpu,您使用了多少个核心?这是你的cpu使用率这么高的问题吗?

票数 2
EN

Stack Overflow用户

发布于 2014-05-15 17:10:48

例如,您应该使用Laravel的队列系统和beanstalkd,然后使用手工队列监视队列(worker):

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21816682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档