#php #performance #codeigniter #codeigniter-2
#php #Производительность #codeigniter #codeigniter-2
Вопрос:
У меня есть скрипт, который выполняет следующие шаги
- Пользователь входит в систему, добавляет SMS-сообщение и указывает получателей. Эта информация добавляется в «таблицу сообщений в очереди»;
- Какой-то процесс отправляет сообщения с использованием API, и сообщения перемещаются в «таблицу отправленных сообщений»;
- Приходит отчет о доставке, и сообщения удаляются из «таблицы отправленных сообщений», а запись журнала, ссылающаяся на отправленные сообщения, добавляется в «таблицу журнала отправленных сообщений».
когда большое количество сообщений помещается в очередь в «таблице сообщений в очереди», шаги (2) и (3) занимают много времени,
Перед отправкой сообщения в API для каждого получателя генерируется случайный уникальный идентификатор для последующей ссылки при получении отчета, этот идентификатор используется в таблице «таблица журнала отправленных сообщений».
Ниже приведен пример сценария
<?php
class Message {
/*
* random unique id for mobile number
*/
protected $mobile_ids = array();
public function add_unique_id($id, $mobile)
{
$this->mobile_ids[] = array($id, $mobile);
}
public function get_unique_id()
{
return $this->mobile_ids;
}
// The method that generated the xml for API
public function makeXML($param,$multi_part=false)
{
$xmlString =
"<SMS>
<authentification>
<username>sss</username>
<password>sss</password>
</authentification>
<message>
<sender>sender</sender>";
if($multi_part == "longSMS") $xmlString .= "<type>longSMS</type>";
$xmlString .= "<text>{$param['text']}</text></message><recipients>";
// Array of mobile numbers came from $param
$phone_numbers = $param['numbers'];
// Loop through the array and generate <gsm messageId='0001'>mobile</gsm>
foreach($phone_numbers as $mobile) {
// Generate id for mobile
$msg_id = $this->make_random_int();
/**
* This is the slow part of the script,
* IDs are added to the array for logging into the database
* When message is sent, i looped through the id and created a log for this message
**/
$this->add_unique_id($msg_id, $mobile);
$xmlString .= "<gsm messageId="{$msg_id}">{$mobile}</gsm>";
}
$xmlString .= "</recipients></SMS>";
return $xmlString;
}
/**
* This is the method that created the log
* Log the sms
* You will need to call $msgid = $this->update_db('the sms')
* return value of $msgid is last_insert_id
*/
public function log_sms($msgid) {
// Log the currently sent message
$userData = array();
$now = date('Y-m-d H:i:s');
foreach ($this->mobile_ids as $data) {
$userData[] = "('{$msgid}', '{$data[0]}', '{$data[1]}', 'QUEUED', '0000-00-00', '0000-00-00', '{$now}')";
}
$query = 'INSERT INTO sent_sms_log (txtId,msgID,mobile,status,sentdate_time,deliver_date_time,sysdate_time) VALUES' . implode(',', $userData);
$this->ci->db->query($query);
$this->mobile_ids = array(); // reset the array
}
// Make random int
protected function make_random_int() {
$this->ci->load->helper('string');
$int = random_string('numeric', 12);
return $int;
}
/**
* Update database after sms sent
* @return int
*/
public function update_db($msg, $owner, $qid=0) {
$data = array('qid'=> $qid, 'sms' => $msg, 'date_time' => date('Y-m-d H:i:s'), 'owner' => $owner);
$this->ci->db->insert('f_sent_sms', $data);
return $this->ci->db->insert_id();
}
}
Ответ №1:
Я предполагаю, что это, вероятно, может быть api, с которым вы работаете. Мне приходилось работать с API для разных сервисов, которые были чрезвычайно медленными. Возможно, попробуйте профилировать разные части кода с помощью класса benchmark:
http://codeigniter.com/user_guide/libraries/benchmark.html
Это будет быстрый и простой способ найти самые медленные части кода.
Комментарии:
1. Передача сообщения в API прошла нормально, перебор идентификаторов и регистрация его в базе данных были медленной частью, мне интересно, смогу ли я найти лучший подход для генерации и регистрации идентификаторов
Ответ №2:
Я предполагаю, что это выполняется в каком-то цикле прямо сейчас? Вместо того, чтобы вставлять неизвестное количество записей по одной за раз, ознакомьтесь с методом insert_batch() для активной записи в руководстве пользователяhttp://codeigniter.com/user_guide/database/active_record.html Вы можете использовать один вызов базы данных, чтобы вставить все ваши записи. Вместо цикла вставки данных в базу данных, все, что нужно было бы сделать циклу, это создать массив всех данных, которые будут вставлены. После завершения цикла запустите insert_batch(‘f_sent_sms’, $my_data) для массива, который вы только что создали.
Было бы неплохо также протестировать все это (до и после), как уже сказал @Matthew.
Комментарии:
1. Если вы читали приведенный выше пример кода, проверьте этот метод log_sms(), это то, о чем вы говорите? я создаю один запрос из массива идентификаторов и запускаю запрос один раз, чтобы вставить данные