За последние 24 часа нас посетили 115886 программистов и 6569 роботов. Сейчас ищет 1561 программист ...

Нагрузка на процессор в конце долгого PHP-скрипта

Тема в разделе "PHP для новичков", создана пользователем doutaxe, 1 июл 2018.

Метки:
  1. doutaxe

    doutaxe Новичок

    С нами с:
    1 июл 2018
    Сообщения:
    2
    Симпатии:
    0
    Всем привет!
    Есть php-скрипт-парсер, который выполняется в среднем 4-5 часов. Запускается в Cron c интервалом в 5 мин, но т.к. стоит защита от повторного запуска - то по сути следующая итерация запускается только после конца предыдущей и с этим проблем нет. Условная структура скрипта выглядит так:

    PHP:
    1. <?php
    2. // Защита от двойного запуска
    3. $lock = fopen('/tmp/lock_file.lock', 'w');
    4. if ( !($lock && flock($lock, LOCK_EX | LOCK_NB)) ) {
    5.     exit( 'already running' );
    6. }
    7.  
    8. // Коннект к БД
    9. $sql = mysqli_connect('...', '...', '...', '...');
    10. if ( !$sql ) die ("Error");
    11.  
    12. // Парсинг
    13. foreach ($s1 as $k1)
    14. {
    15.     ...
    16. foreach ($s2 as $k2)
    17. {
    18.     ...
    19. foreach ($s3 as $k3)
    20. {
    21.     ...
    22. foreach ($s4 as $k4)
    23. {
    24.     ...
    25. }
    26. foreach ($s5 as $k5)
    27. {
    28.     ...
    29. foreach ($s6 as $k6)
    30. {
    31.     ...
    32. foreach ($s7 as $k7)
    33. {
    34.     ...
    35. }
    36. $query = "INSERT INTO tabl1 (r1, r2, r3, r4, r5, r6, r7, r8) VALUES ('$k1', '$k2', '$k3', '$k4', '$k5', '$k6', '$k7', '$k8') ON DUPLICATE KEY UPDATE r5='$k5', r6='$k6', r7 = '$k7', r8='$k8'";
    37. mysqli_query($sql, $query);
    38. }
    39. }
    40. }
    41. }
    42. }
    43. // Удаляем из БД все записи, которым больше 24 часов
    44. $now_delete = date("Y-m-d H:i:s", time() - 86400);
    45. $query_delete = "DELETE FROM tabl1 WHERE r8<'$now_delete'";
    46. if (  mysqli_query($sql, $query_delete)  ) echo "Старые записи подчищены.<br>";
    47. else echo "Старые записи не подчищены <br>";
    48.  
    49. mysqli_close( $sql );
    50. ?>
    Проблема в том, что именно в конце выполнения скрипта (по прошествии 4-5 часов) создается большая нагрузка на процессор сервера (порядка 30 cpu). То, что нагрузка создается именно на исходе скрипта видно по статистике нагрузки от хостера (она разделена по часам). Нагрузка на MySQL околонулевая. Узнать больше, чем то, что нагрузка создается именно этим скриптом - в логах сервера нельзя. Изначально я грешил на последнюю операцию очистки БД, но убрав ее - ничего не изменилось. Почему может так получаться, что скрипт выполняет по сути одно и то же в цикле 5 часов (запись в базу), а именно в конце создает такую нагрузку?
     
  2. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Экстрансы по прежнему в отпуске. Делайте профилироание с каким-нибудь xhprof и смотрите какая логика у вас сьедает процессорное время и в нем ли действительно проблема
     
    doutaxe нравится это.
  3. doutaxe

    doutaxe Новичок

    С нами с:
    1 июл 2018
    Сообщения:
    2
    Симпатии:
    0
    Проанализировал задержки по времени и использование памяти на протяжении всего действия скрипта - проблем ни с тем, ни с другим нет. Пришел к выводу, что нагрузка создается именно в конце 5-часового парсинга просто потому, что скрипт завершился - хостинг логирует нагрузку, которую скрипт создал. Почитал, оказывается такие долгие скрипты надолго полностью занимают процессор сервера - вот и фиксируется нагрузка. Еще почитал - есть решение со вставкой sleep() внутри циклов для периодического освобождения процессора и снижения нагрузки. Но мне принципиальна скорость выполнения скрипта, и увеличивать время выполнения до 10+ часов я не хочу. Вопрос: есть ли какой-нибудь способ снижения нагрузки в таком случае?
     
  4. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    ну перезапускайте его и все чтобы выгружал все из памяти. Однако, по хорошему, если у вас отрабатывает скрипт по N часов это уже некорректная реализация. Перепешите реализацию чтобы была возможность запускать несколько джобов которые бы работали со своим пулом задач и запускайте множество экземпляров, логируйте затраты ресурсов при выполнении и определяйте число допустимых параллельных выполнений если нет прямого доступа к конфигу php-fpm
     
    #4 Zuldek, 2 июл 2018
    Последнее редактирование: 2 июл 2018
  5. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.333
    Симпатии:
    1.753
    может сборщик мусора