it-swarm.com.de

Schwerwiegender Fehler: Nicht genügend Speicher, aber ich habe viel Speicher (PHP)

Da meine Frage immer länger wird, entscheide ich mich, die ganze Frage neu zu schreiben, um sie besser und kürzer zu gestalten.

Ich betreibe meine Website auf einem dedizierten Server mit 8 GB Speicher. Ich bin mir bewusst, dass ich die Speichergrenze für die php.ini-Einstellung erhöhen muss. Ich habe es von 128M auf 256M und auf -1 eingestellt. Das Problem ist immer noch Beharrlichkeit.

Schwerwiegender Fehler: Nicht genügend Speicher (zugewiesen 786432) (versucht, 24576 Bytes zuzuordnen) in Zeile D:\www\football\views\main.php

Der nicht genügend Arbeitsspeicher ist nicht sinnvoll, da nur 786432 Bytes zugewiesen wurden und es 24576 Bytes mehr benötigte.

786432 Bytes sind nur 768 Kilobytes und sind ziemlich klein.

Hinweise

  • Der Fehler tritt in einer sehr zufälligen Zeile auf. Es ist nicht immer ein Fehler in Zeile 81.
  • In Spitzenzeiten benötigt Apache nur etwa 500 MB Speicher. Ich habe noch 6 GB übrig.
  • Es gibt keine Endlosschleife.
  • Das Skript benötigt 1.042.424 Bytes. Diese Nummer von echo memory_get_peak_usage(); erhalten
  • Das Ergebnis von MySQL ist klein (höchstens 12 Zeilen, reiner Text, keine Blob-Daten).
  • (Important) Wenn ich Apache alle zwei Tage neu starte, ist der Fehler verschwunden. Dies geschieht normalerweise, wenn Apache länger als 2 Tage läuft.
  • Ich habe das Profiling des Skripts hinzugefügt und Sie können es hier erhalten.
  • Dieser dedizierte Server wird ausschließlich dazu verwendet, nur eine Website zu betreiben. Diese Website ist eine stark frequentierte Website mit durchschnittlich 1.000 Besuchern pro Minute. Zur Spitzenzeit werden 1.700 bis 2.000 Besucher gleichzeitig erreichbar sein.

Server Spec

Betriebssystem: Windows 2008 R2 64-Bit
CPU: Intel Core i5 - 4 Kerne
RAM: 8 GB
Apache 2.2
PHP 5.3.1
Speicher: 2 x 1 TB Festplatten
Bandbreite: 10 TB pro Monat

Lösung

Ich habe das Problem endlich behoben und behoben, und ich möchte hier mitteilen, was ich zur Verbesserung getan habe:

  1. favicon.ico fehlte, was mit meiner Routenmaschine durcheinander war. Meine Routen-Engine ist zwar sehr klein, aber durch die Verwendung von favicon.ico verringert sie den Speicherbedarf, indem sie meine Routen-Engine nicht ausführt. Der größte Teil meiner Website hat es und ich habe vergessen, es für diesen neuen Abschnitt hinzuzufügen.
  2. Begrenzung MaxRequestPerChild hilft. Auf meinem anderen dedizierten Server habe ich meine MaxRequestPerChild begrenzt. Für diesen Server habe ich ihn auf 0 gesetzt. Ich dachte immer, dass jedes Skript isoliert ist. Lass uns sagen, ob mein Skript 800kb benötigt. Nach dem Abschluss sollte Apache oder PHP 800 KB Speicher freigeben. Es scheint, als würde es so nicht funktionieren. Die begrenzte Variable MaxRequestPerChild verhindert den Speicherverlust, indem ein neuer Prozess erstellt wird, nachdem die Variable MaxRequestPerChild eingenommen wurde und der alte Prozess ausfällt. Dies ist meine neue Einstellung.

    ThreadsPerChild      1500
    MaxRequestsPerChild  10000 
    
  3. ob_flush(); reduziert etwas mehr Speicherplatz. Es hilft nicht viel, aber jede Optimierung hilft.

  4. Ich habe xdebug verwendet, das ich noch nie verwendet habe, wie von Leuten vorgeschlagen, die versuchen, diese Frage zu beantworten. Ich muss sagen, es ist ein großartiges Werkzeug und ich habe ein paar Sachen optimiert, damit es etwas schneller läuft.
  5. Ich habe ein paar unnötige Apache-Module deaktiviert. Ich versuche, es nacheinander zu deaktivieren und einige Tage zu testen, um sicherzustellen, dass es einwandfrei funktioniert, bevor ich einen anderen deaktiviere. Ich habe jetzt alle unnötigen PHP Erweiterungen deaktiviert.
  6. Die meisten meiner Skripte auf diesem Server verwendeten traditionelle Methoden (keine Vorlage, keine Datenbankschicht, reines PHP, HTML und die ältere mysql_ * -Funktion). Um ehrlich zu sein, läuft es sehr schnell und verwendet extrem kleinen Speicher. Die Pflege des Skripts ist jedoch nicht sehr einfach, da die Website länger wird. Ich habe versucht, einige Teile der Website in ein richtiges Framework (mein eigenes kleines Framework) umzuwandeln. Der Grund, warum ich mein eigenes Framework verwendet habe, weil es winzig ist (3kb für das gesamte Framework und nur das, was ich brauche).
  7. Umstellung auf IIS 7.5, um dieses Problem vollständig zu lösen.
58
invisal

Ich bin über das gleiche Problem gestolpert, dass der Server beim Versuch, den Swap zu verwenden, tot ist. Dies liegt daran, dass mod_php niemals Speicher freigibt. Daher steigen die Apache-Prozesse immer weiter an, indem sie entweder die Speichergrenze von Apache oder PHP erreichen oder, wenn es keine Begrenzung gibt, der Server abstürzt. 

Durch den Neustart von Apache können neue, schlanke Prozesse erzeugt werden. Wenn sie jedoch mit der Zeit PHP Skripts ausgeführt werden, wachsen sie, bis Probleme auftreten. 

Die Lösung besteht darin, Apache dazu zu veranlassen, Prozesse nach einer bestimmten Anzahl von Abfragen abzubrechen, sodass neue erstellt werden (es gibt einige Fragen dazu ), wobei die Konfigurationsoption MaxRequestsPerChild Sagen wir 100 (Standardeinstellung ist 1000). 

Natürlich kann dies die Serverleistung beeinträchtigen, da für das Beenden und Erzeugen neuer Prozesse Ressourcen erforderlich sind, aber zumindest die Website funktioniert. Sie könnten versucht sein, die Anzahl der laufenden Prozesse zu erhöhen, um die Leistung hoch zu halten. Stellen Sie sicher, dass PHP (oder Apache) Speicherbegrenzung x die maximale Anzahl von Prozessen nicht über den physischen RAM Ihres Servers geht.

Hier ist meine Erfahrung, hoffe es hilft.

25
greg

Für den Anfang ist memory_get_peak_usage() hier nicht hilfreich. Es wird nur die Menge des zugewiesenen Speichers zurückgegeben. Dies ist die gleiche Anzahl, die den Fehler verursacht hat.

memory_get_usage gibt die aktive Speichermenge zurück, die beim Aufruf zugewiesen wird. 

ini_set('memory_limit', '256M'); legt den maximalen Wert für den Footprint von PHP im Arbeitsspeicher Ihres Systems fest. Wenn Sie OOM bei 768K erhalten, wird das Problem durch das Hochfahren nicht behoben. 

Es gibt keinen Hinweis darauf, welche Version von PHP Sie verwenden, aber ich würde sofort ein Upgrade vorschlagen. Es gibt mehrere Fehler, bei denen der Memory Manager von Zend die Zuordnung von Speicher nicht zulässt. Dies würde Sie genau zu demselben Problem führen.

Führen sowohl Ihr lokaler Server als auch Ihr Produktionsserver dieselbe Betriebssystemversion, dasselbe lange Bit und dieselbe PHP-Version aus? Die Antwort wird nein sein.

Wenn es sich nicht auf das Windows malloc()-Problem bezieht, da es sich um eine Unterdomäne und wahrscheinlich innerhalb eines VirtualHost-Systems handelt und nur 768 KB zugewiesen wird, klingt es fast wie ein Betriebssystemproblem.

Führen Sie tasklist über die Eingabeaufforderung aus, wenn Sie auf Ihr Skript zugreifen. Sehen Sie einen zusätzlichen Apache-Thread oder Speicherauslastung in den Prozessspitzen?

Eine letzte Idee ist, nach jeder Schleife flush() und/oder ob_flush(); für die Tabellenzeile/-spalte auszuführen. Dadurch sollten Sie den Puffer löschen und für den Fall, dass das Problem auftritt, etwas Speicherplatz sparen.

14
Mike Mackintosh

Ich würde zunächst ein Upgrade von PHP auf 5.4+ durchführen, da es für einige Anwendungen um bis zu 50% schneller ist .. _. Bitte siehe becnhamrks: http://news.php.net/php.internals/57760

8
maxwell2022

Installieren Sie xdebug und aktivieren Sie den Profiler-Trigger . Generieren Sie eine Profiler-Datei, und buchen Sie die Cachegrind-Datei, wenn Sie die Ursache des Problems immer noch nicht feststellen können.

BEARBEITEN: Profiler-Datei der Seite, auf der der Speicherverlust natürlich auftritt!

6
Carmageddon

Bitte beachten Sie, dass der Fehler Out of memory ist und nicht Allowed memory size [..] exhausted ist.

Der Speicherverlust befindet sich also an anderer Stelle im System. Es ist möglich, dass der mysql-Server nach dieser intensiven Abfrage viel Systemspeicher verwendet, sodass Apache/php nicht physisch und ohne Swap ausgeführt wird.

Dies sollte den Fehler immer in derselben Zeile (und/oder im gleichen Skript) erklären.

5
Luca Rainone

Ich vermute, dass Sie entweder den richtigen php.ini nicht bearbeitet haben oder PHP und/oder den Webserver nicht neu gestartet haben.

Erstellen Sie in Ihrem Docroot eine phpinfo.php-Seite mit dem Inhalt <?php phpinfo();, um sicherzustellen, dass Sie den richtigen php.ini ändern. Zusätzlich zum Speicherort der php.ini-Datei, die der Webserver verwendet, wird auch der maximal zulässige Skriptspeicher angegeben.

Als Nächstes füge ich Ihrer Seite einige Stack-Spuren hinzu, damit Sie die Kette der Ereignisse sehen können, die zu diesem Ereignis geführt haben. Die folgende Funktion fängt schwerwiegende Fehler ab und liefert weitere Informationen zu den Ereignissen.

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

Ich persönlich habe Nginx + PHP-FPM seit Jahren verwendet, seit ich langsam den alten Apache verlassen habe.

4
Xeoncross

Hey, ich habe das gleiche Problem auch auf meinem Server. Ich habe gerade folgende Dinge geändert:

php.ini ändern in ...

memory_limit = 128M

und zu httpd.conf hinzufügen

RLimitMEM 1073741824 2147483648

und starte Apache neu und ich habe den Fehler entfernt: 

3

Möglicherweise liegt ein Problem mit MySQL und der Anzahl der offenen Verbindungen vor, weshalb es sich beim Neustart alle paar Tage selbst aussortiert. Schließen sie sich beim Herunterfahren des Skripts automatisch?

3
Matt Humphrey

Um es kurz zu fassen (ich füge diese Antwort ziemlich weit von der ursprünglichen Frage entfernt hinzu):

  • PHP kann keinen scheinbar geringen Speicherplatz zuweisen
  • die aktuelle Speicherbelegung zu dem Zeitpunkt, zu dem der Fehler auftritt, + der angeforderte Betrag ist niedriger als die derzeit gültige Speichergrenze
  • in diesem Fall stehen dem System 6 GB für PHP zur Verfügung
  • da das Problem durch einen Neustart von Apache behoben wird, verhindert Apache, dass der für PHP verfügbare Speicher verhindert wird

Wenn alle diese Werte zutreffen, ist die einzige mögliche Erklärung, dass die 6 GB sehr fragmentiert sind, was meiner Meinung nach etwas unwahrscheinlich ist. Sie haben nicht gesagt, wie PHP von Apache - mod_php aufgerufen wird? fpm? Fcgi?

Ich würde zunächst jeden der oben genannten Prädikate untersuchen - insbesondere den freien Speicher. Woher wissen Sie, dass 6 GB frei sind wenn der Fehler auftritt ? Eine wahrscheinlichere Ursache ist, dass ein Speicherverlust auftritt, den Sie nicht erkennen.

Sie haben keine Details zur Konfiguration von Apache bereitgestellt. Ich würde auch einen Blick auf die Reduzierung von MaxRequestsPerChild und MaxMemFree werfen. (Ich bin mit Worker Apache nicht sehr vertraut, wo dies für jeden Thread gilt - wirklich benötigen Sie ein Limit pro Prozess). Wenn Sie die Kerneinstellung aus der Apache-Konfiguration bereitgestellt haben, könnten wir vielleicht weitere Vorschläge machen.

Stellen Sie sicher, dass Ihre Keepalive-Zeit 2 oder weniger beträgt, es sei denn, Sie verwenden Ajax ausgiebig.

2
symcbean

das ist mir vor ein paar Tagen passiert. Ich habe eine Neuinstallation gemacht und es ist immer noch passiert. soweit jeder sieht und basierend auf Ihren Server-Spezifikationen. höchstwahrscheinlich ist es eine Endlosschleife. Es könnte sich nicht um den PHP - Code selbst handeln, sondern um die Anforderungen, die an Apache gestellt werden.

sagen wir, wenn Sie auf diese URL http: // localhost/mysite/page_with_multiple_requests zugreifen.

Überprüfen Sie das Zugriffsprotokoll Ihres Apache, wenn er mehrere Anforderungen empfängt. Verfolgen Sie diese Anforderung und checken Sie den Code aus, der einen Engpass für das System verursachen kann (Mine's exec () bei Verwendung von sendmail). Der Engpass, über den ich spreche, muss keine "Endlosschleife" sein. Es könnte eine Funktion sein, deren Ausführung einige Zeit in Anspruch nimmt. oder vielleicht einige der ' Programmausführungsfunktionen von php '

Möglicherweise müssen Sie auch ajax-Anforderungen prüfen (diejenigen, die beim Laden der Seite ausgeführt werden). Wenn diese Ajax-Anfrage an dieselbe URL weiterleitet 

z.B. httpx: // localhost/mysite/page_with_multiple_requests

es würde die Anforderungen noch einmal "wiederholen"

es wäre hilfreich, wenn Sie die zufälligen Zeilen oder den Code selbst dort posten, wo das Skript endet. Möglicherweise gibt es irgendwo einen 'Loop'-Code. imho php wird nicht umsonst zufällige Zeilen anrufen.

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

1
kapitanluffy

Ich hatte ein ähnliches Problem mit PHP:

1) Überprüfen Sie Ihre Fehlerprotokolle. Beseitigen Sie JEDEN Fehler, bevor Sie fortfahren. 2) Ziehen Sie in Betracht, Ihre Apache-Konfiguration zu ändern, um nicht verwendete Module zu entfernen. Dadurch wird der von PHP benötigte Footprint verringert nützlich http://thethemefoundry.com/blog/optimize-Apache-wordpress/

Um Ihnen eine Vorstellung von der Art des Fehlers zu geben, den ich gefunden habe, hatte ich Code, der versuchte, Inhalte auf Facebook zu veröffentlichen. Facebook modifizierte dann ihre API. Dies brach, und ich benutzte einen 'Content-Expirator', der im Wesentlichen dazu führte, dass der Versuch wiederholt wurde um diesen Inhalt auf Facebook zu posten und Lasten von Objekten im Gedächtnis zu lassen.

1
Dave Hilditch

Versuchen Sie, PHP über fcgid auszuführen, dies kann helfen:

Dies sind die klassischen Fehler, die beim Ausführen von PHP als .__ angezeigt werden. Apache-Modul. Wir haben seit Monaten mit diesen Fehlern zu kämpfen. Wechseln zu Durch die Verwendung von PHP über mod_fcgid (wie von James empfohlen) werden alle diese Probleme behoben. Probleme. Stellen Sie sicher, dass Sie über die neueste Version von Visual C++ verfügen Paket installiert: 

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

Außerdem empfehle ich den Umstieg auf die 64-Bit-Version von MySQL. Nicht wirklich Grund, die 32-Bit-Version nicht mehr auszuführen.

Quelle: Apache 2.4.6.0 Absturz aufgrund eines Problems in php5ts.dll 5.5.1.0

1
Igory

Schwerwiegender Fehler: Nicht genügend Speicher (zugewiesen Gelöst
Ich hatte ein ähnliches Problem, seit Monaten keine Lösung. Schließlich habe ich in einem der Apache-Ordner nachgesehen, d. h. (\ Apache\conf\extra) bin ich auf diese Datei gestoßen, die die Speicherzuordnung von Apache steuert. Der Dateiname ist httpd-mpm In dieser Datei soll der MaxMemFree, der auf 2048 eingestellt ist, etwas erhöht werden. Ich habe meinen Wert auf 10000 für den ersten MaxMemFree (IfModule! mpm_netware_module) erhöht und den zweiten auf 5000 IfModule mpm_netware_module.

Diese haben mein Problem gelöst. ich hoffe es hilft 

1
Bilyaminu K

In der Ausgabedatei des Profilers habe ich ein paar Dinge bemerkt, die mir nicht besonders gefallen/vertrauen und die ich mir ansehen würde:

Abgesehen davon, dass Sie die Bedeutung der Ausgabezahlen nicht kennen, um eine Anomalie zu erkennen, oder wie PHP -Skripts funktionieren, ... Ist dies nicht ein Problem? Haben Sie ein Include für dieselbe main.ph-Datei, die wie eine rekursive Sache aussieht?

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

Die Datei D:\www\football\views\main.php verwendet einige Stringfunktionen mehrmals. Ich nehme an, dass diese Funktionen für die von Ihrer Abfrage zurückgegebenen Daten aufgerufen werden:

strlen
substr
strtotime

Wenn diese Funktionen, wie in der C-Sprache, erfordern, dass Zeichenfolgen null oder ein anderes Ende des Zeichenfolgenendes beendet werden, um Speicherprobleme zu vermeiden, würde ich die von Ihrer Abfrage zurückgegebenen Zeichenfolgen betrachten. 

Können Sie die URL Ihrer Website posten?

1
Only You

In den meisten Fällen erhalten Sie einen solchen Fehler. Das Problem liegt im Code. Ich versuche nicht zu sagen, dass Sie Code schreiben, der schlecht ist. Ich versuche zu sagen, dass Sie genau beobachten müssen, was darin steckt und dass so viel Speicher verwendet wird.

Denken Sie immer daran " Garbage Collection in PHP ist ziemlich schlecht ", es ist nicht wie Java oder eine andere solche Sprache. Es gibt eine Möglichkeit, die Garbage Collection durch gc_collect_cycle zu erzwingen, aber meiner Meinung nach wird das Ihr Problem nicht lösen. PHP gibt den gesamten zur Ausführung einer Seite verwendeten Speicher frei, sobald der Request-Response-Zyklus abgeschlossen ist Wenn Ihr Skript also lange läuft, wie ein Hintergrundskript (Gearman usw.), kann es zu Speicherproblemen kommen, da der Speicher erst freigegeben wird, wenn das Skript ausgeführt wird.

Wenn oben mit Ihrem scr, pt nicht der Fall ist, und wie Sie sagten, es gibt keinen Code, der eine so große Menge an Speicher erfordert, liegt das Problem definitiv im Code selbst und beim Upgrade auf eine beliebige Version von PHP. wird das Problem nicht lösen. Ich war einmal mit einem meiner Gearman-Skripts konfrontiert, und es gab ein Problem mit einer meiner Schleife, bei der ich eine Variable an ein Array anfügte. Die Variable selbst war sehr umfangreich (ca. 110 KB Daten). Ich würde also vorschlagen, Ihren Code sorgfältig zu prüfen.

Rauben 

1
Ravish

Dies ist ein bekannter Fehler in PHP v 5.2 für Windows. Er ist mindestens in Version 5.2.3 vorhanden: https://bugs.php.net/bug.php?id=41615

Keine der vorgeschlagenen Korrekturen hat uns geholfen, wir müssen PHP aktualisieren.

1
Anonymous User

Die folgenden zwei Fakten weisen eindeutig auf Speicherlecks hin:

  1. Der Fehler wird in verschiedenen Zeilen in Ihrem Code angezeigt.
  2. Der Fehler meldet eine relativ kleine Speicherzuordnung.

Ich würde zuerst PDO herausgreifen, alle anderen Erweiterungen deaktivieren und es über Nacht laufen lassen, indem Sie etwa Siege/Apache Bench (ab) verwenden. Sie können es auch mit der cli-Schnittstelle ausführen (stellen Sie einfach sicher, dass Sie die gleichen Speichergrenzen einhalten).

Sie können die Funktion memory_get_peak_usage() am Ende Ihres Skripts verwenden, um zu sehen, wie viel Speicher PHP seiner Meinung nach verwendet wird.

Aus Ihrem Kommentar sind das 800 kB, was in Ordnung ist. definitiv nicht die gigantische Menge an Speicher, die einen Out-of-Memory verursachen würde ;-)

Auch wenn ich an dieser Stelle kein Upgrade auf 5.4 empfehlen würde, lohnt sich das Upgrade auf die neueste Version 5.3.x wahrscheinlich aufgrund mehrerer Schwachstellen und Lecks, die seit 5.3.1 behoben wurden

1
Ja͢ck

Ich würde sagen, der Server hat keinen physischen Speicher/Auslagerungsspeicher, daher kann PHP nicht genügend Speicherplatz zuweisen.

Können Sie die Ausgabe von free hier einfügen?

0
Edson Medina

In meinem Fall wurde dieser Fehler aufgrund einer großen Auswahlabfrage (Hunderttausende der zurückgegebenen Ergebnisse) ausgelöst. 

Es entstand unmittelbar nach dem Hinzufügen von Millionen Datensätzen in meiner Datenbank, um die Skalierbarkeit von WordPress zu testen. Es war also der einzige wahrscheinliche Grund für mich.

0
AFA Med