Tengo un montón de sistemas de punto de venta (POS) de clientes que periódicamente envían nuevos datos de ventas a una base de datos centralizada, que almacena los datos en una gran base de datos para la generación de informes.
El POS del cliente se basa en PHPPOS, y he implementado un módulo que utiliza la biblioteca estándar XML-RPC para enviar datos de ventas al servicio. El sistema del servidor se basa en CodeIgniter y utiliza las bibliotecas XML-RPC y XML-RPCS para el componente de servicio web. Cada vez que envío una gran cantidad de datos de ventas (tan solo 50 filas de la tabla de ventas y filas individuales de artículos de ventas pertenecientes a cada artículo dentro de la venta) aparece el siguiente error:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes)
128M es el valor predeterminado en php.ini
, pero supongo que es un gran número para romper. De hecho, incluso he intentado establecer este valor en 1024M, y todo lo que hace es tomar más tiempo para error.
En cuanto a los pasos que he tomado, he intentado deshabilitar todo el procesamiento en el lado del servidor, y lo he manipulado para que devuelva una respuesta fija independientemente de la entrada. Sin embargo, creo que el problema radica en el envío real de los datos. Incluso he intentado deshabilitar el tiempo máximo de ejecución de script para PHP, y todavía se produce un error.
fuente
ini_set('memory_limit', '256M');
Respuestas:
Cambiar el
memory_limit
by noini_set('memory_limit', '-1');
es una solución adecuada. Por favor no hagas eso.Su código PHP puede tener una pérdida de memoria en algún lugar y le está diciendo al servidor que use toda la memoria que quiera. No habrías solucionado el problema en absoluto. Si monitorea su servidor, verá que ahora probablemente está utilizando la mayor parte de la RAM e incluso está cambiando al disco.
Probablemente debería intentar localizar el código ofensivo en su código y corregirlo.
fuente
-1
podría ser útil solo en entornos de desarrollo para fines de prueba.ini_set('memory_limit', '-1');
anula el límite de memoria PHP predeterminado .fuente
-1
es un valor que PHP entiende como ilimitado en este contexto.La forma correcta es editar su
php.ini
archivo. Editememory_limit
a su valor deseado.A partir de su pregunta,
128M
(que es el límite predeterminado) se ha excedido, por lo que hay algo muy mal con su código, ya que no debería tomar tanto.Si sabe por qué se necesita tanto y desea permitir que se establezca
memory_limit = 512M
o más, debería ser bueno.fuente
La asignación de memoria para PHP se puede ajustar de forma permanente o temporal.
Permanentemente
Puede cambiar permanentemente la asignación de memoria PHP de dos maneras.
Si tiene acceso a su
php.ini
archivo, puede editar el valormemory_limit
a su valor deseado.Si no tiene acceso a su
php.ini
archivo (y su webhost lo permite), puede anular la asignación de memoria a través de su.htaccess
archivo. Agregarphp_value memory_limit 128M
(o lo que sea su asignación deseada).Temporal
Puede ajustar la asignación de memoria sobre la marcha desde un archivo PHP. Simplemente tiene el código
ini_set('memory_limit', '128M');
(o la asignación que desee). Puede eliminar el límite de memoria (aunque todavía pueden aplicarse límites de máquina o instancia) estableciendo el valor en "-1".fuente
Es muy fácil obtener pérdidas de memoria en un script PHP, especialmente si usa abstracción, como un ORM. Intente usar Xdebug para perfilar su secuencia de comandos y averiguar dónde se fue toda esa memoria.
fuente
Cuando agregué 22.5 millones de registros en una matriz con array_push, seguía recibiendo errores fatales de "memoria agotada" en alrededor de 20 millones de registros usando
4G
como límite de memoria en el archivo php.ini. Para solucionar esto, agregué la declaraciónen la parte superior del archivo. Ahora todo está funcionando bien. No sé si PHP tiene una pérdida de memoria. Ese no es mi trabajo, ni me importa. Solo tengo que hacer mi trabajo, y esto funcionó.
El programa es muy simple:
El error fatal apunta a la línea 3 hasta que aumenté el límite de memoria, lo que eliminó el error.
fuente
ini_set('memory_limit', '8192M');
?Seguí recibiendo este error, incluso con
memory_limit
set inphp.ini
, y el valor se lee correctamente conphpinfo()
.Al cambiarlo de esto:
A esto:
Esto rectificó el problema en PHP 7.
fuente
Cuando vea el error anterior, especialmente si
(tried to allocate __ bytes)
es un valor bajo, eso podría ser un indicador de un bucle infinito, como una función que se llama a sí misma sin salida:fuente
Después de habilitar estas dos líneas, comenzó a funcionar:
fuente
Puede corregir esto correctamente cambiando
memory_limit
fastcgi / fpm:Cambiar la memoria, como de 128 a 512, ver abajo
a
fuente
El directorio raíz de su sitio:
fuente
Cambie el límite de memoria en el archivo php.ini y reinicie Apache. Después del reinicio, ejecute phpinfo (); funcionar desde cualquier archivo PHP para una
memory_limit
confirmación de cambio.El límite de memoria -1 significa que no hay un límite de memoria establecido. Ahora está al máximo.
fuente
Para los usuarios de Drupal, la respuesta de Chris Lane de:
funciona pero necesitamos ponerlo justo después de la apertura
etiqueta en el archivo index.php en el directorio raíz de tu sitio.
fuente
En Drupal 7, puede modificar el límite de memoria en el archivo settings.php ubicado en su sitio / carpeta predeterminada. Alrededor de la línea 260, verá esto:
Incluso si su configuración de php.ini es lo suficientemente alta, no podrá consumir más de 128 MB si no está configurada en su archivo Drupal settings.php.
fuente
En lugar de cambiar el
memory_limit
valor en suphp.ini
archivo, si hay una parte de su código que podría usar mucha memoria, podría eliminar elmemory_limit
antes de que se ejecute esa sección y luego reemplazarlo después.fuente
PHP 5.3+ le permite cambiar el límite de memoria colocando un
.user.ini
archivo en lapublic_html
carpeta. Simplemente cree el archivo anterior y escriba la siguiente línea:Algunos hosts cPanel solo aceptan este método.
fuente
¿Página de bloqueo?
(Ocurre cuando MySQL tiene que consultar filas grandes. De manera predeterminada,
memory_limit
está configurado en pequeño, lo que era más seguro para el hardware).Puede verificar el estado de la memoria existente de su sistema, antes de aumentar
php.ini
:Aquí lo he aumentado como en el siguiente y luego hago
service httpd restart
para solucionar el problema de la página de bloqueo.fuente
free -m
comando para decidir sobre un nuevo memory_limit?Simplemente agregue una
ini_set('memory_limit', '-1');
línea en la parte superior de su página web.Y puede configurar su memoria según sus necesidades en lugar de -1, a
16M
, etc.fuente
Para aquellos que se rascan la cabeza para descubrir por qué demonios esta pequeña función debería causar una pérdida de memoria, a veces por un pequeño error, una función comienza a llamarse recursivamente para siempre.
Por ejemplo, una clase proxy que tiene el mismo nombre para una función del objeto que lo va a proxy.
A veces puede olvidarse de traer ese pequeño miembro actual de Objec y debido a que el proxy realmente tiene ese
doSomething
método, PHP no le daría ningún error y, para una clase grande, podría ocultarse de los ojos durante un par de minutos para descubrir por qué está goteando el recuerdo.fuente
die('here')
su código y mover esa declaración para ver dónde comienza la recursividad.Tuve el siguiente error al ejecutar un conjunto de datos más pequeño que el que había trabajado anteriormente.
Como la búsqueda de la falla me trajo aquí, pensé en mencionar que no siempre son las soluciones técnicas en las respuestas anteriores, sino algo más simple. En mi caso fue Firefox. Antes de ejecutar el programa, ya estaba usando 1,157 MB.
Resulta que había estado viendo un video de 50 minutos un poco a la vez durante un período de días y eso arruinó las cosas. Es el tipo de solución que los expertos corrigen sin siquiera pensarlo, pero vale la pena tenerlo en cuenta para mí.
fuente
Ejecutar el script de esta manera (caso cron, por ejemplo):
php5 /pathToScript/info.php
produce el mismo error.La forma correcta:
php5 -cli /pathToScript/info.php
fuente
Si está ejecutando un VPS (servidor privado virtual) con WHM, es posible que no tenga permisos para editar PHP.INI directamente; El sistema debe hacerlo. En el panel de control del host WHM, vaya a Configuración de servicio → Editor de configuración PHP y modifique
memory_limit
:fuente
Me resulta útil al incluir o requerir
_dbconnection.php_
y_functions.php
en archivos que realmente se procesan, en lugar de incluir en el encabezado. Que está incluido en sí mismo.Entonces, si su encabezado y pie de página están incluidos, simplemente incluya todos sus archivos funcionales antes de incluir el encabezado.
fuente
Usar también
yield
podría ser una solución. Ver sintaxis del generador .En lugar de cambiar el
PHP.ini
archivo por un almacenamiento de memoria más grande, a veces implementaryield
un bucle interno puede solucionar el problema. Lo que hace el rendimiento es que, en lugar de descargar todos los datos a la vez, los lee uno por uno, ahorrando mucho uso de memoria.fuente
PHP.ini
? ¿No es asíphp.ini
?Este error a veces es causado por un error en el código PHP que causa recurrencias que involucran manejo de excepciones y posiblemente otras operaciones. Desafortunadamente, no he podido crear un pequeño ejemplo.
En estos casos, que me han sucedido varias veces,
set_time_limit
falla y el navegador sigue intentando cargar la salida de PHP, ya sea con un bucle infinito o con el mensaje de error fatal que es el tema de esta pregunta.Al reducir el tamaño de asignación permitido agregando
cerca del comienzo de su código, debería poder evitar el error fatal.
Entonces es posible que se quede con un programa que finaliza, pero aún es difícil de depurar.
En este punto, inserte
BreakLoop()
llamadas dentro de su programa para obtener el control y averiguar qué bucle o recursión en su programa está causando el problema.La definición de BreakLoop es la siguiente:
El argumento $ LoopSite puede ser el nombre de una función en su código. No es realmente necesario, ya que el mensaje de error que recibirá lo dirigirá a la línea que contiene la llamada BreakLoop ().
fuente
En mi caso, fue un breve problema con la forma en que se escribió una función. Se puede causar una pérdida de memoria al asignar un nuevo valor a la variable de entrada de una función, por ejemplo:
fuente
Cuando eliminé las siguientes líneas de mi código, ¡todo funcionó bien!
Estas líneas se incluyeron en cada archivo que estaba ejecutando. Cuando ejecuté los archivos uno por uno, todo funcionó bien, pero cuando ejecuté todos los archivos juntos tuve el problema de pérdida de memoria. De alguna manera, "include_once" no incluye cosas una vez, o estoy haciendo algo mal ...
fuente
set_include_path(get_include_path() . get_include_path().'/phpseclib');
Esto agregará la ruta '/ phpseclib' una vez para cada archivo que tenga la línea ... ¡para que pueda agregarla muchas veces! Sugeriría ponerlo en un archivo de configuración yinclude_once
el archivo de configuración.