Собираю два массива А и Б по ~миллиону целых чисел из веб сервиса, чтобы затем сосчитать их пересечение. Сервис отдаёт за один запрос 1000 чисел, поэтому в цикле около 1000 раз для каждого приходится делать запрос через cURL. Коннекшн один, используется снова и снова: подставляются новые значения в CURLOPT_POSTFIELDS, и снова curl_exec()
Полученный json разбирается, и очередной массив с 1000 целых чисел merge'ится в А или Б.
Пока это всё работает в виде пруф-оф-концепт на shared хостинге руЦентра, где памяти выделено всего ничего. С партиями меньше миллиона скрипт справляется. Больше - вылетает с фатальной ошибкой об исчерпанной памяти. Иногда на этапе получения второго миллиона из сервиса, иногда уже после, на этапе сравнения.
Вместо ф-ий array_merge() и array_intersect() уже использую свои, менее ресурсоёмкие: мне не нужно сортировать и получать само пересечение, достаточно сосчитать кол-во общих.
Не может только массив целых с 2 млн. значений занимать десятки мегов памяти же! Как понять, раздувается ли это cURL при каждом новом обращении? Или, может, массивы хранят значения не как целые по 4 байта, а как строки например?
Сориентируйте, пожалуйста, с оптимизацией по памяти - куда копать?
Ответ
Имхо при ужатой памяти вам проще на БД переложить этот процесс. Работать будет дольше, но памяти есть меньше. Может быть, можно будет даже часть алгоритмов на базу переложить. Далее, в php с памятью такая анархия, что лучше даже не интересоваться. Достаточно сказать, что размер массива всегда степень двойки (в большую сторону), состоит он из указателей(4-8 байт) на int, а int - это структура(имя, тип, размер etc). И далее, если можно обрабатывать все в процессе - do it. Т.е. получили тысячу, обработали, выкинули, погнали дальше. Если нет - БД. Теоретически можно попробовать с временными файлами поколдовать, но вряд ли этот способ сильно выиграет у БД по удобству/скорости.
Комментариев нет:
Отправить комментарий