如何优化这个PHP脚本?

如何优化这个PHP脚本?,php,mysql,mysqli,Php,Mysql,Mysqli,我将运行一个脚本来检查是否通过steam的web API接受了一些交易报价。我将使用cronjob每隔15秒运行一次。但我希望它能被优化并尽可能快地运行,我觉得我做得很差 正如您所看到的,我已经添加了一些注释,告诉您脚本正在做什么。但我也会在这里试试 它从数据库中收集所有新的交易报价 它检查交易要约是否已被取消 如果未取消,则aka接受。然后它收集有关报价的信息 如果机器人库存包含玩家存放的物品。数据库将设置status=1 然后,它将删除交易要约,因为交易要约已经完成 我觉得这个脚本运行得

我将运行一个脚本来检查是否通过steam的web API接受了一些交易报价。我将使用cronjob每隔15秒运行一次。但我希望它能被优化并尽可能快地运行,我觉得我做得很差

正如您所看到的,我已经添加了一些注释,告诉您脚本正在做什么。但我也会在这里试试

  • 它从数据库中收集所有新的交易报价
  • 它检查交易要约是否已被取消
  • 如果未取消,则aka接受。然后它收集有关报价的信息
  • 如果机器人库存包含玩家存放的物品。数据库将设置status=1
  • 然后,它将删除交易要约,因为交易要约已经完成
我觉得这个脚本运行得很慢,我应该改成mysqli吗?或者用assoc替换mysql\u fetch\u数组?我可以做些什么来优化这个。非常重要的是,它的运行速度要快于15秒

    <?php
require('xxxxxx/xx.php');

        //Getting bot-items
         $jsonInventory = file_get_contents('https://steamcommunity.com/profiles/76561xxxxx8959977/inventory/json/730/2');
         $data = json_decode($jsonInventory, true);

        //Getting tradeoffers
        $tradeoffers = mysql_query("SELECT * FROM tradeoffers");
        while($trade = mysql_fetch_array($tradeoffers)) {

        //Getting information about trade-offer
        $url = file_get_contents("https://api.steampowered.com/IEconService/GetTradeOffer/v1/?key=3593xxxxxB6FFB8594D8561374154F7&tradeofferid=".$trade['tradeofferid']."&language=en_us");
        $json = json_decode($url, true);

        //Checking if trade has been completed
        if (isset($json['response']) && isset($json['response']['offer'])) {


        if($json['response']['offer']['trade_offer_state'] == 1 || $json['response']['offer']['trade_offer_state'] == 5 || $json['response']['offer']['trade_offer_state'] == 6 || $json['response']['offer']['trade_offer_state'] == 7 || $json['response']['offer']['trade_offer_state'] == 8 || $json['response']['offer']['trade_offer_state'] == 10 || $json['response']['offer']['trade_offer_state'] == 11) {
            mysql_query("DELETE FROM tradeoffers WHERE tradeofferid = '".$trade['tradeofferid']."'");
            mysql_query("DELETE FROM items WHERE tradeofferid = '".$trade['tradeofferid']."'");
        } 

            if($json['response']['offer']['trade_offer_state'] == 3) {


            if(isset($data['rgDescriptions'])) {

                $itemsinfo = mysql_query("SELECT * FROM items WHERE tradeofferid = '".$trade['tradeofferid']."'");
                while($item = mysql_fetch_array($itemsinfo)) {

                foreach($data['rgInventory'] as $inv) {
                $desc = $data['rgDescriptions'][ $inv['classid'] .'_'. $inv['instanceid'] ]; 

            if($desc['icon_url'] == $item['iconurl']) {
                mysql_query("UPDATE items SET assetid = '".$inv['id']."' WHERE iconurl = '".$item['iconurl']."'");
                mysql_query("UPDATE items SET status = 1 WHERE iconurl = '".$item['iconurl']."'");

                   }
                }    
              }
            }
            //Deleting the trade-offer from the database.
            mysql_query("DELETE FROM tradeoffers WHERE tradeofferid = '".$trade['tradeofferid']."'");
        }
    } else {
        mysql_query("DELETE FROM tradeoffers WHERE tradeofferid = '".$trade['tradeofferid']."'");
        mysql_query("DELETE FROM items WHERE tradeofferid = '".$trade['tradeofferid']."'");
    }
 }
 echo 'Finished';
?>

首先,我建议您远离
mysql*
函数,使用
PDO
mysqli

优化。我没有运行您的代码,但运行了一些指针:

“从”
中选择*可能比较慢。尽量只使用您需要的字段

您正在更新
“其中iconurl=”。$item['iconurl']。“”。
此字段是否已编制索引


有必要删除这些记录吗?这是一个缓慢的操作。如果您标记它们,例如
complete=1会发生什么情况?
(如果您的表太拥挤,您可能会一次删除它们)

首先,我建议您远离
mysql.*
函数,使用
PDO
mysqli

优化。我没有运行您的代码,但运行了一些指针:

“从”
中选择*可能比较慢。请尝试仅使用所需的字段

您正在更新
“其中iconurl=”。$item['iconurl']。“”。
此字段是否已编制索引


是否有必要删除这些记录?这是一个缓慢的操作。如果标记它们会发生什么情况,例如,
complete=1?
(如果您的表太拥挤,您以后仍可以一次性删除它们)

提高性能的一个级别是从
文件获取内容
切换到从API获取数据
curl
通常要快得多。此外,使用curl,您可以并行运行多个请求,这将带来另一个性能提升(如果您能够并行化您的请求)

另见此


另一个级别是并行化数据库调用,这是迁移到
mysqli
后可以执行的操作。有关详细信息,请参阅。(再次假设它是可能的并且逻辑上合理)

提高性能的一个级别是从
文件获取内容
切换到从API获取数据
curl
通常要快得多。此外,使用curl,您可以并行运行多个请求,这将带来另一个性能提升(如果您能够并行化您的请求)

另见此


另一个级别是并行化数据库调用,这是迁移到
mysqli
后可以执行的操作。有关详细信息,请参阅。(再次假设这是可能的,并且从逻辑上讲是有道理的)

这里有一些很好的答案,我将首先附议他们在简短摘要中所说的内容,然后再加上我的两分钱

(1) 您最大的性能提升将来自Erik关于cURL的两个建议。切换到cURL将略微提高性能(每次调用可能需要0.5到1秒或更长时间),但使用multi-cURL并行调用两个URL可能会提供这里所有建议中绝对最大的好处,没有问题(因为您在循环中进行这些网络获取)。下面是其他人编写的一个类,它稍微简化了多重旋度:

<?php
// LICENSE: PUBLIC DOMAIN
// The author disclaims copyright to this source code.
// AUTHOR: Shailesh N. Humbad
// SOURCE: https://www.somacon.com/p539.php
// DATE: 6/4/2008

// index.php
// Run the parallel get and print the total time
$s = microtime(true);
// Define the URLs
$urls = array(
  "http://localhost/r.php?echo=request1",
  "http://localhost/r.php?echo=request2",
  "http://localhost/r.php?echo=request3"
);
$pg = new ParallelGet($urls);
print "<br />total time: ".round(microtime(true) - $s, 4)." seconds";

// Class to run parallel GET requests and return the transfer
class ParallelGet
{
  function __construct($urls)
  {
    // Create get requests for each URL
    $mh = curl_multi_init();
    foreach($urls as $i => $url)
    {
      $ch[$i] = curl_init($url);
      curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, 1);
      curl_multi_add_handle($mh, $ch[$i]);
    }

    // Start performing the request
    do {
        $execReturnValue = curl_multi_exec($mh, $runningHandles);
    } while ($execReturnValue == CURLM_CALL_MULTI_PERFORM);
    // Loop and continue processing the request
    while ($runningHandles && $execReturnValue == CURLM_OK) {
      // Wait forever for network
      $numberReady = curl_multi_select($mh);
      if ($numberReady != -1) {
        // Pull in any new data, or at least handle timeouts
        do {
          $execReturnValue = curl_multi_exec($mh, $runningHandles);
        } while ($execReturnValue == CURLM_CALL_MULTI_PERFORM);
      }
    }

    // Check for any errors
    if ($execReturnValue != CURLM_OK) {
      trigger_error("Curl multi read error $execReturnValue\n", E_USER_WARNING);
    }

    // Extract the content
    foreach($urls as $i => $url)
    {
      // Check for errors
      $curlError = curl_error($ch[$i]);
      if($curlError == "") {
        $res[$i] = curl_multi_getcontent($ch[$i]);
      } else {
        print "Curl error on handle $i: $curlError\n";
      }
      // Remove and close the handle
      curl_multi_remove_handle($mh, $ch[$i]);
      curl_close($ch[$i]);
    }
    // Clean up the curl_multi handle
    curl_multi_close($mh);

    // Print the response data
    print_r($res);
  }

}

这里有一些很好的答案,我将首先附议他们在简短摘要中所说的内容,然后再加上我的两分钱

(1) 您最大的性能提升将来自Erik关于cURL的两个建议。切换到cURL将略微提高性能(每次调用可能需要0.5到1秒或更长时间),但使用multi-cURL并行调用两个URL可能会提供这里所有建议中绝对最大的好处,没有问题(因为您在循环中进行这些网络获取)。下面是其他人编写的一个类,它稍微简化了多重旋度:

<?php
// LICENSE: PUBLIC DOMAIN
// The author disclaims copyright to this source code.
// AUTHOR: Shailesh N. Humbad
// SOURCE: https://www.somacon.com/p539.php
// DATE: 6/4/2008

// index.php
// Run the parallel get and print the total time
$s = microtime(true);
// Define the URLs
$urls = array(
  "http://localhost/r.php?echo=request1",
  "http://localhost/r.php?echo=request2",
  "http://localhost/r.php?echo=request3"
);
$pg = new ParallelGet($urls);
print "<br />total time: ".round(microtime(true) - $s, 4)." seconds";

// Class to run parallel GET requests and return the transfer
class ParallelGet
{
  function __construct($urls)
  {
    // Create get requests for each URL
    $mh = curl_multi_init();
    foreach($urls as $i => $url)
    {
      $ch[$i] = curl_init($url);
      curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, 1);
      curl_multi_add_handle($mh, $ch[$i]);
    }

    // Start performing the request
    do {
        $execReturnValue = curl_multi_exec($mh, $runningHandles);
    } while ($execReturnValue == CURLM_CALL_MULTI_PERFORM);
    // Loop and continue processing the request
    while ($runningHandles && $execReturnValue == CURLM_OK) {
      // Wait forever for network
      $numberReady = curl_multi_select($mh);
      if ($numberReady != -1) {
        // Pull in any new data, or at least handle timeouts
        do {
          $execReturnValue = curl_multi_exec($mh, $runningHandles);
        } while ($execReturnValue == CURLM_CALL_MULTI_PERFORM);
      }
    }

    // Check for any errors
    if ($execReturnValue != CURLM_OK) {
      trigger_error("Curl multi read error $execReturnValue\n", E_USER_WARNING);
    }

    // Extract the content
    foreach($urls as $i => $url)
    {
      // Check for errors
      $curlError = curl_error($ch[$i]);
      if($curlError == "") {
        $res[$i] = curl_multi_getcontent($ch[$i]);
      } else {
        print "Curl error on handle $i: $curlError\n";
      }
      // Remove and close the handle
      curl_multi_remove_handle($mh, $ch[$i]);
      curl_close($ch[$i]);
    }
    // Clean up the curl_multi handle
    curl_multi_close($mh);

    // Print the response data
    print_r($res);
  }

}

mysql已弃用,不应再使用。用户mysqli或PDO。是的,我知道如何使用mysqli,但是由于一位老开发人员的原因,站点的其余部分都在mysql上运行。但是我可以用mysqli运行这个脚本,对吗?在不干扰其余代码的情况下?从mysql更改为mysqli不太可能有助于提高性能。@Karldrakar如果这是孤立的,则是。此外,steam API似乎有一个
GetTradeOffers
路由,因此您可以批量获取它们,并批量从数据库中删除/更新内容(可能我不知道API是否会为您提供足够的信息,以便在批量请求中使用)。您的内部
文件\u get\u contents()
始终指向同一URL。没有必要重复这样做。在脚本开始时执行一次。mysql已弃用,不应再使用。用户mysqli或PDO。是的,我知道如何使用mysqli,但是由于一位老开发人员的原因,站点的其余部分都在mysql上运行。但是我可以用mysqli运行这个脚本,对吗?在不干扰其余代码的情况下?从mysql更改为mysqli不太可能有助于提高性能。@Karldrakar如果这是孤立的,则是。此外,steam API似乎有一个
GetTradeOffers
路径,因此您可以批量获取它们,并批量从数据库中删除/更新内容(可能我不知道API是否会为您提供足够的信息来处理批量请求)。您的内部
文件\u get\u contents()