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

12 3
C
На сайте с 15.01.2007
Offline
100
1171

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

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

Sly32
На сайте с 29.03.2012
Offline
303
#1

а что с интернетом у вас, может скорость соединения лагает?

пинги сервера ок?

S
На сайте с 30.09.2016
Offline
469
#2
Corvus:
Прошу помощи, в какую сторону копать и как оптимизировать работу скрипта, добиться устойчивого времени его работы?

Расставьте в программе отладочные маркеры и логируйте их прохождение. Выявляйте узкое место программы.

Отпилю лишнее, прикручу нужное, выправлю кривое. Вытравлю вредителей.
SocFishing
На сайте с 26.09.2013
Offline
118
#3

Ну смотрите.

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

2. очень много открытий файлов, дисковых операций, когда один процесс открывает файл, он блокируется на время открытия для других процессов скорее всего

3. нужно перенастроить максимальное число возможных открытый файлов на VDS, вероятно бъет в лимит и больше не может открыть. Возможно в этом и причина. В SSH введите sudo ulimit -n 32768 и и повысить /proc/sys/fs/file-max в текстовике. Посмотреть другие лимиты ulimit -a

★Сервис идентифицирует (https://socfishing.com/?utm_source=searchengines) посетителей вашего сайта и предоставляет их профили ВКонтакте, Телефон, Почта! Цены копеечные, работаем 8 лет.
C
На сайте с 15.01.2007
Offline
100
#4
Sly32:
а что с интернетом у вас, может скорость соединения лагает?
пинги сервера ок?

Пинги нормальные, интернет тоже. Время выполнения скрипта я подсчитываю в самом скрипте, то есть без учёта затрат на передачу данных по сети. Если скрипт вызывать не через веб, а из командной строки через шелл, работает он так же неустойчиво.

---------- Добавлено 10.01.2020 в 16:25 ----------

Sitealert:
Расставьте в программе отладочные маркеры и логируйте их прохождение. Выявляйте узкое место программы.

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

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

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

---------- Добавлено 10.01.2020 в 16:29 ----------

SocFishing:
Ну смотрите.

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

2. очень много открытий файлов, дисковых операций, когда один процесс открывает файл, он блокируется на время открытия для других процессов скорее всего

3. нужно перенастроить максимальное число возможных открытый файлов на VDS, вероятно бъет в лимит и больше не может открыть. Возможно в этом и причина. В SSH введите sudo ulimit -n 32768 и и повысить /proc/sys/fs/file-max в текстовике. Посмотреть другие лимиты ulimit -a

Спасибо! Попробую то, что Вы сказали.

Как думаете, есть ли смысл помещатьисходные данные в БД? Их общий размер около 9 Гб, обновляются они несколько раз в сутки. Будет ли выигрыш по времени чтения, и стоит ли игра свеч, ведь залив в БД такого объёма будет идти, вероятно, весьма долго.

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

---------- Добавлено 10.01.2020 в 16:32 ----------

SocFishing:
Ну смотрите.

Посмотреть другие лимиты ulimit -a

core file size (blocks, -c) 0

data seg size (kbytes, -d) unlimited

scheduling priority (-e) 0

file size (blocks, -f) unlimited

pending signals (-i) 125436

max locked memory (kbytes, -l) 64

max memory size (kbytes, -m) unlimited

open files (-n) 500000

pipe size (512 bytes, -p) 8

POSIX message queues (bytes, -q) 819200

real-time priority (-r) 0

stack size (kbytes, -s) 10240

cpu time (seconds, -t) unlimited

max user processes (-u) 50000

virtual memory (kbytes, -v) unlimited

file locks (-x) unlimited

По идее этого должно быть достаточно?

SocFishing
На сайте с 26.09.2013
Offline
118
#5

А использовать сервисы по определению геоположения не то, на javascript, тот же яндекс? 9 гигабайт не мало для реалтайма, я думаю будет лучше, чем последовательно читать. Через БД можно оптимальнее обойти, если еще построить логику с лимитированием и индексами. Плюс можно выставить кеш на БД.

У вас последовательно с файлов читает кусками или построчно? если построчно, это очень медленные операции.

К примеру, скорость выборки 10000 случайных записей 1 - 150 млн занимает на обычно дохлой VPS при использовании MongoDB 0.1 сек и размер >9 gb с индексами.

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

_
На сайте с 24.03.2008
Offline
381
#6

Реально количество файлов какое ? Всего их сколько ? Объем какой ?

Вторичный вызов того-же запроса приводит к тому-же времени выполнения ?

Вызов быстрого всегда быстр ?

Скорее всего надо как-то в сторону файлового кеша и файловой системы смотреть.

Но вообще "профилируйте", наставляйте логов и смотрите где время уходит.

В ntfs например (не к ночи) короткие файлы прям в mft пишутся, а она может быть и сильно фрагментирована.

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

Под "линуксы" я помнится читал что есть ФС заточенные под подобного рода работу, т.е. работу с большим количеством файлов.

БД с индексами, скорее всего не даст вам никакого буста, если вам реально нужно содержимое этих файлов.

SocFishing
На сайте с 26.09.2013
Offline
118
#7

еще выполнить

sudo sysctl -w fs.nr_open=500000

sudo sysctl -p

забыл упомянуть, что ulimit -n 32768 && ulimit -a нужно применить на том пользователе, под которым у вас запускается процесс. Например пользователь вебсервера www-data

перейти под пользователя sudo -u www-data sh

дальше ulimit -n 32768 && ulimit -a

exit

БД с индексами, скорее всего не даст вам никакого буста, если вам реально нужно содержимое этих файлов.

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

_
На сайте с 24.03.2008
Offline
381
#8
SocFishing:

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

Правильно. Слушать не надо - думайте.

А файловая система по вашему мнению что, для чтения файла по пути последовательно весь диск читает :) ?

Врубите мозг наконец.

ФС - это такая СУБД для управления файлами.

И надеяться, что любая другая СУБД будет выдавать по одному индексу (пути) данные быстее, чем ФС - это очень-очень странно.

Уж не говоря о том, что ФС кешируется "на все деньги", что есть... при правильных настройках.

А SQL сервера, как правило нет.

SocFishing
На сайте с 26.09.2013
Offline
118
#9

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

В случае же базы данных мы можем побить множество нужных кусков данных под индексы и обращаться к этим кускам быстро отталкиваясь от своих задач. Аналогия, равносильно предположим создать 1000000 файлов и название указать широту, внутри файла же будет вся информация по городам с этой широты. так мы можем быстро открыть файл имея значение широты. Потому как файловая система строит индекс по названию файла. Но кто в здравом уме будет создавать столько файлов и гемороится, когда можно намного быстрее и проще сделать это с базой данных. Это вам любой практикующий разработчик скажет, что вы плывёте в другое русло.

Автор написал про 9 гб данных и 4000 файлов. несложно посчитать размер каждого файла и потом с этого размера последовательное чтение да еще и с поиском нужного значения.

_
На сайте с 24.03.2008
Offline
381
#10
SocFishing:
_SP_, мы за файл говорим или за файловую систему. Файл читается последовательно, в индекс файловой системы попадает например название этого файла, содержимое файла не разбивается по индексам.

В случае же базы данных мы можем побить множество нужных кусков данных под индексы и обращаться к этим кускам быстро отталкиваясь от своих задач.

Не можете.

Если ТСу нужно содержимое файла, то вы не можете ничего побить.

Если он обращается к содержимому по пути, то это будет не медленнее, чем обратиться по индексу, а может быть быстрее.

Если файл невелик, то разницы "считать весь / считать часть" не будет (чтение всё-равно идет блоками).

Если файл невелик, то чтение из него не будет медленнее, чем "достать через индекс из БД только нужное", а может быть быстрее.

Разумеется, если ТС что-то там "перебирает и ищет", то делать так НЕ НАДО, надо строить индексы итп.

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

12 3

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий