Сильно варьируется время работы PHP-скрипта

  • Автор темы Автор темы Corvus
  • Дата начала Дата начала

Corvus

Новичок
Имеется PHP-скрипт (API для передачи геоданных в ответ на внешний запрос из сети интернет через веб-сервер Apache), суть которого состоит в открытии определённого числа файлов (около 4000), чтения из них данных по заданному смещению (в зависимости от широты и долготы пункта), закрытия файлов, некоторой математической обработки данных и возвращения в виде массива.

Проблема: штатно скрипт работает около 0.5 секунды, это оптимальное время. Но так работает он далеко не всегда. После 2-3 срабатываний с таким временем, он 2-3-4 раза срабатывает с гораздо более длительным временем, порядка 30-40 секунд, что совершенно неприемлемо. В общем, время работы скрипта варьируется почти в 100 раз и это совершенно непредсказуемо.

Памяти скрипт использует мало, порядка 1 Мб, ресурсов процессора берёт тоже очень мало, около 0.3%.

Всё это работает на выделенном сервере VDS, на котором кроме базового софта Linux, а также веб-софта типа Apapche, PHP, MySQL по сути ничего нет. Памяти 16 Гб, из них обычно занято (всеми процессами) не более 500-700 Мб.
То есть сервер свободный, кроме данного скрипта на нём извне ничего не запускается. И этот скрипт пока работает только в тестовых целях, то есть единичные последовательные запуски (без одновременных параллельных попыток).

Читал где-то, что такая проблема может наблюдаться при работе с большим числом файлов в одной директории (более 2000). Раскидал эти файлы по десятку директорий), но ничего не изменилось.

Попытки анализа вывода команд ps и top тоже пока ничего не дали. В логах апача тем более ничего интересного нет, т.к. нет там практически никаких других запросов, кроме (нечастых) вызовов данного скрипта.

Прошу помощи, в какую сторону копать и как оптимизировать работу скрипта, добиться устойчивого времени его работы?
 
VDS - это не выделенный сервер, а виртуалка с ограничениями по дисковым операциям

диск - самый медленный и ограниченный ресурс сервера,
первая фантазия, которая приходит в голову - провайдер замедляет операции с диском,
первые несколько раз в рамках лимита вы быстро считываете 10 тысяч файлов, потом скорость обработки обращений к диску ограничивают, чтобы вы не мешали другим виртуалкам

проверить тезис можно скриптом на 5 строк - читать в цикле из файлов и писать время исполнения функции, которая обращается к диску - вызов fgets/fread/etc, для контроля при втором запуске добавить в цикл usleep на долю секунды

оптимизировать можно редисом, он данные в оперативке держит, иммутабельным массивом на 7.3 с opcode cache,
и провайдером получше
 
Последнее редактирование:
погуглите по теме php profiling.
вам надо определить что именно тормозит. это может быть апач, если собирает полный пулл запросов. может сам php код, для этого надо расставить таймеры и главное таймеры на запросы к базе банных.


вангую, что проблема в апаче, раз скрипты выполняются дольше 30 секунд и не падают по таймлимиту.
 
а внешние вызовы тоже не учитываются в лимите
 
а еще блокировки по сессии, по файлам и по базе. Хотя база тут, похоже, ни при делах.
Для начала, поставить вывод в лог замеры времени выполнения скрипта и увидеть - тормозит ли скрипт при работе с файлами или при открытии сессии.
Если грусть печаль тоска и файловая система этого самого vds устраивает перекэширование внутреннее после 10к чтений - может можно перекинуть данные в базу ?
 
Мне кажется там апач говно =\
 
А мне сама идея чтения из 4000 файлов кажется дикой.
В том числе с т.з. производительности.
 
вангую, что проблема в апаче, раз скрипты выполняются дольше 30 секунд и не падают по таймлимиту.

Я тоже так думал сначала, но скрипт точно так же глючит (работает то 0.5 сек, то 40 сек) и при запуске из командной строки.
 
Для начала, поставить вывод в лог замеры времени выполнения скрипта и увидеть - тормозит ли скрипт при работе с файлами или при открытии сессии.

Да, я так делал. Отображал и время выполнения отдельных операций, и затраты памяти.

В том-то и проблема, что при одном запуске скрипта каждая операция чтения файла занимает, условно, 0.001 секунды и общее время работы скрипта 0.5 секунд, а в другом каждая операция чтения 0.1 секунды и общее время 40-50 секунд.

Вычисления в скрипте выполняются буквально за 0.2 секунды (если отключить в коде чтение данных из файлов). То есть именно чтение файлов занимает очень много времени. Может, диск на сервере не совсем исправен?
 
Если грусть печаль тоска и файловая система этого самого vds устраивает перекэширование внутреннее после 10к чтений - может можно перекинуть данные в базу ?

1. У меня поначалу память на сервере быстро заполнялась, из 16 Гб свободно было обычно в пределах 1 Гб.
Я стал по крону запускать каждые 10 минут /bin/sync && /bin/echo 1 > /proc/sys/vm/drop_caches
и память стала почти свободной.
Может, делать это каждые 1-2 минуты?
2. Вот я думаю, есть ли смысл помещать исходные данные в БД? Их общий размер около 9 Гб, обновляются они несколько раз в сутки. Будет ли выигрыш по времени чтения, и стоит ли игра свеч, ведь залив в БД такого объёма будет идти, вероятно, весьма долго.
Просто зная широту и долготу точки, я однозначно знаю, по какому смещению читать данные из файлов. Казалось бы, в таком случае чтение из файлов должно работать быстрее, чем чтение из БД? Попадались статьи на тему, что если индексы не нужны (априори известно местонахождение нужных данных - в каком файле и по какому смещению), то прямая работа с файлами априори быстрее, чем любая БД.
 
А мне сама идея чтения из 4000 файлов кажется дикой.
В том числе с т.з. производительности.

У меня подобный проект работает уже 8 лет на другом сервере, VPS, с гораздо более скромными системными параметрами.
Скрипты устойчиво выполняются пусть не за 0.5 с, так за 2-3 с.
На выделенном сервере, как я ожидал, всё будет летать. Но где там - ситуация совсем другая и грустная.
Такое впечатление, что что-то с настройками файловой системы.
 
Если подтверждается возникновение при секвентальных вызовах, то можно tmpfs попробовать. iostat смотреть опять же. 4к файлов будет дрючить систему полюбэ. Посмотрите как организованы директории в кеширующих проксях, в сквиде например. Если "от широты и долготы" значит будут хотспоты. Самое простое - добавить кеширование. Опять же широта + долгота -> связи простые -> смотреть в сторону nosql. А современные nosql все сами порешают, что я перечислил до этого.

PS. А еще проще - попробовать у другого провайдера.
 
А вот , случайно тормозить сайт начинает не раз в 10 минут ? Не связано ли 10-минутная очистка системного кэша с внезапными тормозами?
 
да что тут гадать, это проблема в архитектуре на высоком уровне, а не в сервере и не в коде
 
dd if=tempfile of=/dev/null bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 1.44716 s, 742 MB/s

hdparm выдаёт:
/dev/sda
Timing cached reads: 3590 MB in 2.00 seconds = 1795.36 MB/sec
Timing buffered disk reads: 290 MB in 3.02 seconds = 96.08 MB/sec

/dev/sdb:
Timing cached reads: 3580 MB in 2.00 seconds = 1789.78 MB/sec
Timing buffered disk reads: 474 MB in 3.00 seconds = 157.90 MB/sec

Это нормальная скорость чтения?
 
Я позапускал hdparm многократно, скорость чтения с диска обычно варьируется от 50 до 150 MB/sec. Уже одно это даёт колебание времени работы скрипта в разы.
 
А вот , случайно тормозить сайт начинает не раз в 10 минут ? Не связано ли 10-минутная очистка системного кэша с внезапными тормозами?

Я её не так давно сделал раз в 10 минут, пытаясь решить главную проблему.
Сейчас сделал раз в сутки, но глюки остались.
 
продолжай
giphy.gif
 
Сверху