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

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 тоже пока ничего не дали. В логах апача тем более ничего интересного нет, т.к. нет там практически никаких других запросов, кроме (нечастых) вызовов данного скрипта.

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

grigori

( ͡° ͜ʖ ͡°)
Команда форума
VDS - это не выделенный сервер, а виртуалка с ограничениями по дисковым операциям

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

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

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

AmdY

Пью пиво
Команда форума
погуглите по теме php profiling.
вам надо определить что именно тормозит. это может быть апач, если собирает полный пулл запросов. может сам php код, для этого надо расставить таймеры и главное таймеры на запросы к базе банных.


вангую, что проблема в апаче, раз скрипты выполняются дольше 30 секунд и не падают по таймлимиту.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
а внешние вызовы тоже не учитываются в лимите
 

ksnk

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

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Мне кажется там апач говно =\
 

AnrDaemon

Продвинутый новичок
А мне сама идея чтения из 4000 файлов кажется дикой.
В том числе с т.з. производительности.
 

Corvus

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

Corvus

Новичок
Для начала, поставить вывод в лог замеры времени выполнения скрипта и увидеть - тормозит ли скрипт при работе с файлами или при открытии сессии.
Да, я так делал. Отображал и время выполнения отдельных операций, и затраты памяти.

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

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

Corvus

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

Corvus

Новичок
А мне сама идея чтения из 4000 файлов кажется дикой.
В том числе с т.з. производительности.
У меня подобный проект работает уже 8 лет на другом сервере, VPS, с гораздо более скромными системными параметрами.
Скрипты устойчиво выполняются пусть не за 0.5 с, так за 2-3 с.
На выделенном сервере, как я ожидал, всё будет летать. Но где там - ситуация совсем другая и грустная.
Такое впечатление, что что-то с настройками файловой системы.
 

whirlwind

TDD infected, paranoid
Если подтверждается возникновение при секвентальных вызовах, то можно tmpfs попробовать. iostat смотреть опять же. 4к файлов будет дрючить систему полюбэ. Посмотрите как организованы директории в кеширующих проксях, в сквиде например. Если "от широты и долготы" значит будут хотспоты. Самое простое - добавить кеширование. Опять же широта + долгота -> связи простые -> смотреть в сторону nosql. А современные nosql все сами порешают, что я перечислил до этого.

PS. А еще проще - попробовать у другого провайдера.
 

ksnk

прохожий
А вот , случайно тормозить сайт начинает не раз в 10 минут ? Не связано ли 10-минутная очистка системного кэша с внезапными тормозами?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
да что тут гадать, это проблема в архитектуре на высоком уровне, а не в сервере и не в коде
 

Corvus

Новичок
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

Это нормальная скорость чтения?
 

Corvus

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

Corvus

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