Как я могу сделать эту программу PHP быстрее? - PullRequest
2 голосов
/ 19 июля 2011

Я создал программу для циклического просмотра слов и получения их синонимов от www.dicsin.com.br, но это займет целую вечность (буквально), потому что в моем testfile.txt есть 307 тыс. Слов, что я могу сделать? дайте мне советы, пожалуйста, могу ли я сделать его многопоточным или многопоточным, я не знаю, я новичок в PHP и программировании, спасибо, в любом случае, кстати, это мой полный рабочий код:

<?
//Pega palavras do site: www.dicsin.com.br
pegarSinonimos("http://www.dicsin.com.br/content/dicsin_lista.php");

function pegaPalavras()
{
return file('testfile.txt');
}

function pegarSinonimos($url)
{
        $dicionario = pegaPalavras();
        $array_palavras = array();
        $array_palavras2 = array();
        $con = mysql_connect("localhost","root","whatever");
        if (!$con)
         {
          die('Could not connect: ' . mysql_error());
         }
        mysql_select_db("palavras2", $con);
        foreach($dicionario as $palavra)
        {
            $url_final = $url . "?f_pesq=" . $palavra;// . "&pagina=" . $pagina;

            $html = file_get_contents($url_final);

            $dom = new DOMDocument();
            $dom->loadHTML($html);

            $xpath = new DOMXPath($dom);
            $tags = $xpath->query('//div[@class="palavras_encontradas"]/div[@class="box_palavras_encontradas"]');
            foreach ($tags as $tag) 
            {
                $bla = $tag->nodeValue;
                $bla = utf8_decode($bla);
                $bla = str_replace("visualizar palavras", "", $bla);
                $bla = str_replace("(Sinônimo) ", "", $bla);//echo $bla;//array_push($array_palavras,$tag->nodeValue);
                $sql = "CREATE TABLE $palavra(sinonimo varchar(29))";
                mysql_query($sql,$con);
                mysql_query("INSERT INTO $palavra (sinonimo) VALUES ('$bla')");
            }
        }
        mysql_close($con);
}   
?>

Ответы [ 4 ]

2 голосов
/ 19 июля 2011

Разработайте хеш-таблицу и посмотрите на нее. Это достигнет O (1) постоянного времени.

0 голосов
/ 19 июля 2011

Если вы используете последнюю библиотеку NaturePHP для PHP 5.3+ и у вас установлен cURL, это должно дать вам огромный импульс:

<?php
include('nphp/init.php');

function pegaPalavras()
{
return file('testfile.txt');
}

//Pega palavras do site: www.dicsin.com.br
pegarSinonimos("http://www.dicsin.com.br/content/dicsin_lista.php");

function pegarSinonimos($url)
{
$dictionary = pegaPalavras();
$files = array();

$con = mysql_connect("localhost","root","blablabla");   //omg! a root pwd :O
if (!$con)
{
    die('Could not connect: ' . mysql_error());
}
mysql_select_db("palavras2", $con);


foreach($dictionary as $palavra)
{
    $files[] = $url . "?f_pesq=" . $palavra;// . "&pagina=" . $pagina;
}

//Http::multi_getcontents on NaturePHP makes use of curl_multi for parallel processing  and 
//fires callbacks asap, first come first serve style
//it should, however, take a lot on CPU and bandwith while processing
Http::multi_getcontents(

//uris
$files,

//process callback
function($url, $content){

    list(, $word) = explode('=', $content);

    $dom = new DOMDocument();
    $dom->loadHTML($content);

    $xpath = new DOMXPath($dom);
    $tags = $xpath->query('//div[@class="palavras_encontradas"]/div[@class="box_palavras_encontradas"]');

    //you create one table per word
    $sql = "CREATE TABLE $palavra(sinonimo varchar(29))";
    mysql_query($sql,$con);

    //if something was found
    if(count($tags)>0){

        //get an array with synonyms
        $synonyms=array();
        foreach ($tags as $tag) 
        {
            $synonyms[] = utf8_decode($tag->nodeValue);
        }

        //you can use str_replace on arrays, it's faster
        $synonyms = str_replace("visualizar palavras", "", $synonyms);
        $synonyms = str_replace("(Sinônimo) ", "", $synonyms);

        //a single insert query with all values is much faster
        $values = "('" . implode("'), ('", $synonyms) . "')";
        mysql_query("INSERT INTO $palavra (sinonimo) VALUES $values");

    }


});

mysql_close($con);
}

?>

На самом деле код здесь не проверялся, так что могут быть ошибки mionor, но вы получите общую концепцию;)

Если у вас нет php 5.3+, вы можете взглянуть на исходный код на NaturePHP о том, как использовать curl_multi.

PS: возможно, вы захотите изменить свой корневой пароль: x

0 голосов
/ 19 июля 2011

1. Сложность

Как сказал FinalForm, сложность вашего алгоритма слишком высока (O (n ^ 2)). Вы должны избегать цикла внутри цикла (даже внутри другого цикла). Вы всегда должны вычислять сложность вашего алгоритма (это может быть сложно сделать математически)

Низко висящие фрукты

Чтобы помочь вам оптимизировать медленную партию, вы должны заниматься только низко висящими фруктами, используя такие инструменты, как xdebug / calgrind. Я советую вам посмотреть это видео " simple is hard " от создателя PHP Расмуса, чтобы изучить эту концепцию. Когда вы будете заниматься низко висящими фруктами, вы получите максимум денег за свои деньги

Curl_multi

Я думаю, что самая медленная часть в том, что вы делаете керлы по одному на время (не можете больше ничего делать в это время). Я не думаю, что другие циклы занимают так много времени (по сравнению с извлечением из удаленного хоста, который, я думаю, ваш низко висящий фрукт). Вы можете использовать multi_curl для мультиплексирования получения ваших URL => http://www.onlineaspect.com/2009/01/26/how-to-use-curl_multi-without-blocking/. Это должно быть намного быстрее, чем блокировка file_get_content

Очередь сообщений (MQ)

Хотя это не доступно на виртуальном хостинге (или не очень понравилось). Но чтобы сделать ваш сайт действительно быстрым, вам нужно обработать загрузку в автономном режиме, используя MQ, например, redis или beanstalkd . Затем вы должны обрабатывать каждую отдельную задачу в автономном режиме, используя очередь сообщений, и возвращать фрагменты обратно.

0 голосов
/ 19 июля 2011

Если вы хотите сделать его многопоточным, вы можете разветвлять процессы с помощью функций PCNTL , используя --enable-pcntl

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...