Подтвердить что ты не робот

Неустранимая ошибка: нехватка памяти, но у меня много памяти (PHP)

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

Я запускаю свой сайт на выделенном сервере с 8 ГБ памяти. Я полностью осознаю, что мне нужно увеличить лимит памяти на настройке php.ini. Я установил его с 128M до 256M и до -1. Тем не менее проблема заключается в настойчивости.

Неустранимая ошибка: Недостаточно памяти (выделено 786432) (попытался выделить 24576 байт) в D:\www\football\views\main.php в строке 81

Из памяти не имеет смысла, потому что сказано, что выделено только 786432 байта, и ему нужно еще 24576 байт.

786432 байта составляет всего 768 килобайт и довольно мало.

Советы

  • Ошибка происходит на очень случайной строке. Это не всегда ошибка на строке номер 81.
  • В пиковое время Apache занимает всего 500 мб памяти. У меня все еще есть 6 ГБ.
  • Нет бесконечного цикла.
  • script занимает 1,042,424 байт. Получение этого номера из echo memory_get_peak_usage();
  • Набор результатов из MySQL мал (не более 12 строк, чисто текст, без данных BLOB)
  • (Важная) Если я перезапускаю Apache один раз в два дня, ошибка исчезнет. Обычно это происходит, когда Apache работает более 2 дней.
  • Я включил профилирование script, и вы можете получить его здесь.
  • Этот выделенный сервер используется исключительно для запуска только одного веб-сайта. Этот веб-сайт является веб-сайтом с высоким трафиком со скоростью в среднем 1000 посетителей каждую минуту. В пиковое время одновременно будет доступно от 1 700 до 2000 посетителей.

Спецификация сервера

ОС: 64-разрядная версия Windows 2008 R2 Процессор: Intel Core i5 - 4 ядра
ОЗУ: 8 ГБ
Apache 2.2
PHP 5.3.1
Хранение: жесткие диски 2 x 1 ТБ
Полоса пропускания: 10 ТБ в месяц

Решение

Я наконец-то настроил и исправил проблему, и я хотел бы поделиться ею здесь, что я сделал, чтобы улучшить:

  • favicon.ico отсутствовал, что испортило мой механизм маршрута. Хотя мой механизм маршрутов очень мал, но включив favicon.ico, он помогает сократить использование памяти, не запуская мой механизм маршрута. У большей части моего веб-сайта есть это, и я забыл поместить его в этот новый раздел.
  • Лимит MaxRequestPerChild помогает. На моем другом выделенном сервере у меня ограниченный MaxRequestPerChild. Для этого сервера я установил его равным 0. Я всегда думал, что каждый script изолирован. Допустим, если мой script занимает 800kb для запуска. По завершении Apache или PHP должны освободить память 800 КБ. Похоже, что так не получается. Ограниченный MaxRequestPerChild помогает предотвратить утечку памяти, создавая новый процесс после ограниченного MaxRequestPerChild, и старый процесс умирает. Это моя новая настройка.

    ThreadsPerChild      1500
    MaxRequestsPerChild  10000 
    
  • ob_flush(); уменьшает немного больше памяти. Это не помогает, но каждый бит оптимизации помогает.

  • Я использовал xdebug, который я никогда раньше не использовал, как предполагают люди, которые пытаются ответить на этот вопрос. Я должен сказать, что это отличный инструмент, и я оптимизировал несколько продуктов, чтобы заставить его работать немного быстрее.
  • Я отключил несколько ненужных модулей Apache. Я пытаюсь отключить его один за другим и оставьте его на несколько дней, чтобы убедиться, что он работает отлично, прежде чем отключить другой. У меня теперь все ненужное расширение PHP.
  • Большинство моих script на этом сервере использовали традиционный способ (без шаблона, без уровня базы данных, чистого PHP, HTML и устаревшей функции mysql_ *). Честно говоря, он работает очень быстро и использует чрезвычайно маленькую память. Тем не менее, обслуживание script не очень просто, так как веб-сайт становится дольше. Я попытался преобразовать некоторые части веб-сайта в правильную структуру (моя собственная крошечная структура). Причина, по которой я использовал свою собственную структуру, потому что она крошечная (3kb для всей структуры и включает только то, что мне нужно).
  • Переключение на IIS7.5 полностью решение этой проблемы.
4b9b3361

Ответ 1

Я столкнулся с той же проблемой, когда сервер умирал при попытке использовать своп. Это связано с тем, что mod_php не освобождает память. Таким образом, процессы Apache продолжают расти либо до предела apache, либо из-за ограничения памяти PHP, или, если нет ограничений, сбой сервера.

Перезапуск apache заставляет его создавать новые свежие тонкие процессы, но по мере запуска скриптов PHP с течением времени они растут до тех пор, пока не возникнут проблемы.

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

Конечно, это может снизить производительность сервера, поскольку он требует ресурсов, чтобы убивать и создавать новые процессы, но по крайней мере он поддерживает работу сайта. У вас может возникнуть соблазн повысить количество запущенных процессов, чтобы поддерживать высокие показатели, убедитесь, что ограничение памяти для PHP (или apache) x максимальное количество процессов не распространяется на ваш физический RAM сервера.

Вот мой опыт, надеюсь, что это поможет.

Ответ 2

Для начала memory_get_peak_usage() здесь не будет полезно. Он вернет только объем памяти, который был выделен, и это тот же номер, который вызвал ошибку.

memory_get_usage вернет активный объем памяти, который выделяется при его вызове.

ini_set('memory_limit', '256M'); установит максимальный учет влияния PHP на ваши системы. Если вы получаете OOM на 768K, то это не устранит проблему.

Нет никаких указаний относительно того, какую версию PHP вы используете, но я бы предложил обновление сразу. Существует несколько ошибок, из-за которых Zend Memory Manager не может освободить память, что приведет вас к одной и той же проблеме.

Являются ли ваш локальный сервер и ваш производственный сервер той же версией ОС, такой же длинный бит и одна и та же версия PHP? Ответ будет отрицательным.

Если он не связан с проблемой windows malloc(), поскольку он является поддоменом и, вероятно, внутри VirtualHost и выделяет только 768k, это почти похоже на проблему с ОС.

Запустите tasklist из командной строки при доступе к вашему script. Вы видите дополнительный поток Apache или использование памяти во всплывающих окнах процессов?

Одна из последних идей - запустить flush() и/или ob_flush(); после каждого цикла для строки/столбца таблицы. Это должно очистить ваш буфер и сохранить вам некоторую память в случае, когда это происходит.

Ответ 3

Я бы начал с обновления PHP до 5.4+, так как это на 50% быстрее для некоторых приложений. Они зафиксировали большое количество утечек памяти. Пожалуйста, см. Becnhamrks: http://news.php.net/php.internals/57760

Ответ 4

Установите xdebug и включите триггер профайлера. Создайте файл профилировщика, а затем опубликуйте файл cachegrind, если вы все еще не сможете указать источник проблемы.

EDIT: файл профилирования страницы, где происходит утечка памяти!

Ответ 5

Обратите внимание, что ошибка Out of memory и не Allowed memory size [..] exhausted.

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

Это должно объяснять ошибку всегда в одной строке (и/или в том же script).

Ответ 6

Я бы предположил, что вы либо не отредактировали правильный php.ini, либо не перезапустили PHP и/или веб-сервер.

Создайте страницу phpinfo.php в своем docroot с содержимым <?php phpinfo();, чтобы убедиться, что вы меняете правильный php.ini. В дополнение к местоположению файла php.ini, который использует веб-сервер, он также укажет максимально допустимую память script.

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

register_shutdown_function(function()
{
    if($error = error_get_last())
    {
        // Should actually log this instead of printing out...
        var_dump($error);
        var_dump(debug_backtrace());
    }
});

Лично, Nginx + PHP-FPM - это то, что я использовал в течение многих лет с тех пор, как оставил медленный Ap 'Apache.

Ответ 7

Эй, у меня тоже такая же проблема на моем сервере. Я просто изменил следующие вещи:

измените php.ini на...

memory_limit = 128M

и добавьте к httpd.conf

RLimitMEM 1073741824 2147483648

и перезапустите apache, и я удалил ошибку:

Ответ 8

Может возникнуть проблема с MySQL и количеством открытых подключений, поэтому он сортируется при перезагрузке каждые несколько дней. Закрыты ли они при закрытии script?

Ответ 9

Просто чтобы ответить (я добавляю этот ответ на большое расстояние от исходного вопроса):

  • PHP не может выделить то, что кажется небольшим объемом памяти
  • текущее использование памяти в то время, когда ошибка occrs + запрошенная сумма меньше, чем действующий в настоящее время лимит памяти
  • система имеет 6Gb, доступную для использования PHP, когда это происходит
  • так как проблема решена путем перезапуска apache - это apache, которая препятствует доступности памяти из PHP для

Если все они действительны, единственное возможное объяснение состоит в том, что 6Gb очень фрагментирован, что, я думаю, маловероятно. Вы не сказали, как PHP вызывается из Apache - mod_php? FPM? FCGI?

Я бы начал с изучения каждого из вышеуказанных предикатов, в частности, свободной памяти. Откуда вы знаете, что там 6Gb бесплатно при возникновении ошибки? Более вероятная причина заключается в том, что происходит утечка памяти, которую вы не заметили.

Вы не указали какие-либо сведения о настройке apache; Я бы также посмотрел на сокращение MaxRequestsPerChild и MaxMemFree. (Я не очень хорошо знаком с рабочим apache, где это применимо для каждого потока - вам действительно нужно ограничение на процесс). Если вы предоставили базовую настройку из конфигурации apache, возможно, мы сможем сделать дополнительные предложения.

Если вы не используете Ajax широко, убедитесь, что ваше время ожидания составляет 2 или менее.

Ответ 10

Следующие два факта определенно указывают на утечки памяти:

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

Сначала я бы выделил PDO, отключив все остальные расширения и позвонил ему за одну ночь, используя что-то вроде Siege/Apache Bench (ab). Вы также можете попробовать запустить его с помощью интерфейса cli (просто убедитесь, что вы сохраняете одинаковые пределы памяти).

Вы можете использовать функцию memory_get_peak_usage() в конце вашего script, чтобы узнать, сколько памяти PHP думает, что она использует.

Из вашего комментария, что 800 kB, что хорошо; определенно не гигантский объем памяти, из-за которого будет отсутствовать память; -)

Наконец, хотя я бы не рекомендовал обновление до 5.4 на данный момент, обновление до последнего 5.3.x, вероятно, стоит того, что связано с несколькими уязвимостями и утечками, которые были устранены с 5.3.1.

Ответ 11

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

скажет, когда вы получаете доступ к этому URL http://localhost/mysite/page_with_multiple_requests

Проверьте свой журнал доступа к Apache, если он получает несколько запросов. проследите этот запрос и проверьте код, который может вызвать "узкое место" для системы (my exec() при использовании sendmail). Узкое место, о котором он говорит, не обязательно должен быть "бесконечным циклом". Это может быть функция, которая требуется для завершения. или, возможно, некоторые из функций php 'для выполнения программ

Вам может потребоваться также проверить запросы ajax (те, которые выполняются при загрузке страницы). если этот запрос ajax перенаправляется на тот же URL

например. httpx://локальный/MySite/page_with_multiple_requests

он снова "повторит" запросы

это поможет, если вы разместите случайные строки или сам код, где заканчивается script, возможно, там есть код цикла. imho php не просто вызовет случайные строки ни для чего.

http://blog.piratelufi.com/2012/08/browser-sending-multiple-requests-at-once/

Ответ 12

В большинстве случаев вы получаете такую ​​ошибку, проблема в коде. Я не пытаюсь сказать, что вы плохо пишете код, я пытаюсь сказать, что вам нужно внимательно наблюдать, что там, в котором используется этот объем памяти.

Всегда помните, что " сбор мусора на PHP довольно плохой", это не похоже на Java, любой другой такой язык. существует способ принудительного сбора мусора через gc_collect_cycle, но, по моему личному мнению, это не решит вашу проблему. PHP освобождает всю память, используемую для выполнения страницы, как только цикл запроса-ответа завершен, поэтому вы можете столкнуться с проблемами памяти, если ваш script работает долго, как фон script (Gearman и т.д.), Потому что память не является освобожден до script.

Если выше, это не так с вашим scr, pt, и, как вы сказали, нет кода, который требует такого огромного объема памяти, тогда проблема наиболее определенно в коде сама, а обновление до любой версии PHP выиграло Решить проблему. Однажды я столкнулся с одним из моих сценариев Gearman, и возникла проблема с одним из моих циклов, где я добавлял одну переменную в один из моих массивов, сама переменная была очень тяжелой (около 110 Кбайт данных). Поэтому я бы посоветовал сделать тщательный осмотр вашего кода.

Равиш

Ответ 13

У меня была аналогичная проблема с PHP:

1) Проверьте журналы ошибок. Перед продолжением устраните КАЖДУЮ ошибку. 2) Рассмотрите возможность изменения конфигурации apache для устранения неиспользуемых модулей - это уменьшит объем, необходимый PHP, - здесь отличная ссылка для этого - она ​​специфична для Wordpress, но должна по-прежнему быть очень полезной http://thethemefoundry.com/blog/optimize-apache-wordpress/

Чтобы дать вам представление о том, какую ошибку я обнаружил, у меня был код, который пытался отправить контент в Facebook, Facebook затем изменил их API, так что это сломалось, я также использовал "expirator контента", который в основном означал, что он продолжал повторять попытку опубликовать этот контент в Facebook и оставить массу объектов, лежащих в памяти.

Ответ 14

Из выходного файла профайлера я заметил пару вещей, которые мне не нравились/не доверяли много и смотрели на них:

Помимо незнания смысла выходных чисел для обнаружения аномалии или того, как работают скрипты PHP..., это не проблема? Включить в тот же файл main.ph, который выглядит как рекурсивная вещь?

2121 fl=D:\www\football\views\main.php
2122 fn=include::D:\www\football\views\main.php

Заметил, что файл D:\www\football\views\main.php несколько раз использует некоторые строковые функции, я думаю, он вызывает эти функции на данных, возвращаемых вашим запросом:

strlen
substr
strtotime

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

Можете ли вы разместить URL-адрес своего веб-сайта?

Ответ 15

Это известная ошибка в PHP v 5.2 для Windows, она присутствует по крайней мере до версии 5.2.3: https://bugs.php.net/bug.php?id=41615

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

Ответ 16

Попробуйте запустить php через fcgid, это может помочь:

Это классические ошибки, которые вы увидите при запуске PHP в качестве Модуль Apache. Мы много месяцев боролись с этими ошибками. Переход на используя PHP через mod_fcgid (как рекомендует Джеймс), исправит все эти проблемы. Убедитесь, что у вас есть последний распространяемый на Visual С++ установленный пакет:

http://support.microsoft.com/kb/2019667

Кроме того, я рекомендую перейти на 64-битную версию MySQL. Не реально причина для запуска 32-разрядной версии.

Источник: Ошибка Apache 2.4.6.0 из-за проблемы в php5ts.dll 5.5.1.0

Ответ 17

Неустранимая ошибка: Недостаточно памяти (выделено SOLVED
У меня была схожая проблема, в течение нескольких месяцев нет решения. наконец, я проверял одну из папок apache i.e(\ apache\conf\extra), я наткнулся на этот файл, который управляет распределением памяти apache. имя файла httpd-mpm в этом файле, вы должны увеличить MaxMemFree, который установлен на 2048 на что-то более высокое, я взял мой до 10000 для первого MaxMemFree (IfModule! mpm_netware_module), затем сделал второй MaxMemFree до 5000 IfModule mpm_netware_module.

Они решили мою проблему. надеюсь, что это поможет

Ответ 18

Я бы сказал, что на сервере заканчивается физическая/своп-память, поэтому PHP не может выделить достаточно памяти.

Можете ли вы вставить вывод free здесь?

Ответ 19

В моем случае эта ошибка была вызвана из-за огромного запроса выбора (сотни тысяч возвращенных результатов).

Он возник сразу после добавления в мою базу данных миллионов записей для проверки масштабируемости WordPress, поэтому это была единственная вероятная причина для меня.