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