Ankündigung

Einklappen
Keine Ankündigung bisher.

RAM Speicher einsparen/Performance erhöhen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • RAM Speicher einsparen/Performance erhöhen

    Hallo,

    vielleicht hat jemand Hinweise, wo ich weitere Informationen dazu finde oder sogar konkrete Tipps, wie derzeit so ein "Problem" gelöst wird.
    Wie die Überschrift verrät, geht es darum möglichst viel RAM Speicher einzusparen. Derzeit bewege ich mich mit knapp 120M noch nicht grundsätzlich am Limit, aber aus meiner Sicht kann das nicht gut sein und es muss einen Weg geben, das Ganze zu optimieren. Selbstverständlich rede ich hier nicht von der Dauerlast, sondern von klar auszumachenden "Prozessen", die entsprechend viel Speicher "fressen" und nur sehr selten ausgelöst werden.

    Um was geht es konkret? Derzeit beschäftigen mich zwei vorrangig zwei unterschiedliche "Prozesse".
    1) Import einer CSV Datei mit knapp 5000 Zeilen und jeweils 60 Spalten. Die "Rohdaten" haben schon ein Volumen von über 3M. Verarbeitet wird das Ganze derzeit über einen Upload im Browser, die Daten müssen aufbereitet werden (da geht es bespielsweise um Anpassung von Zeit-/Datumsstrukturen und ähnliches), so dass nach dem Speichern in der Datenbank knapp 120M RAM durch sind. Das kann auf lange Zeit nicht gut gehen, zumal ich nicht abschätzen kann, wie sich die Datenmenge aufgrund der Skalierung entwickelt. Eine Splittung der Datei in mehrere Teile soll möglichst vermieden werden, auch ist eine "Aufbereitung" vor dem Import weniger das Ziel.

    2) Die Daten sollen nach dem Import auf bestimmte Eigenschaften und Abhängigkeiten geprüft werden. Dazu hatte ich die glorreiche Idee einen Objektbaum mit den Daten nebst der zugehörigen Referenzdaten zu erstellen. Schon alleine die Datenbankabfrage braucht bei 5000 Datensätzen und jeweils 3-10 Referenzen pro Datensatz knapp über 72M Speicher. Bis dahin wurde noch kein Datensatz auf die entsprechenden Bedingungen geprüft. Auch das erscheint mir sehr viel.

    Gibt es eine Möglichkeit solche "Prozesse" in Teilen abzuarbeiten, so dass weniger Arbeitsspeicher verbraucht wird? Welche Möglichkeiten gibt es solche Abläufe zu splitten?
    Während eines kurzes Austausches mit einem Kollegen kam das Schlagwort Upload der Datei mithilfe von Ajax ins Spiel. Könnte das ein Ansatz sein?

    Viele Grüße
    ec

  • #2
    Eine Möglichkeit wäre das Importieren der CSV in eine (temporäre) Datenbank mit LOAD DATA ( http://dev.mysql.com/doc/refman/5.7/en/load-data.html ) und dann kannst Du die Daten Stück für Stück (Cronjob) abarbeiten.
    svenwegner.net

    Kommentar


    • #3
      Keiner zwingt dich die CSV komplett in den Speicher zu laden. Mit fopen und freadcsv kannst du eine CSV zeilenweise einlesen und verarbeiten.
      Für Punkt zwei gibt es keine allgemein gültige Lösung. Dort müsstest du ins Detail gehen.

      Kommentar


      • #4
        Die Idee mit einer temporären Tabelle finde ich grundsätzlich gut. Darüber muss ich nachdenken.

        freadcsv sagt mir nichts, meinst du fgetcsv? So lese ich die Datei ein. Es geht grundsätzlich weniger darum, dass ich die Datei in den Speicher lade (oder doch, ich bin mir gerade unsicher, wie du das genau meinst), sondern darum, dass die Rechen- und Speicheroperationen so umfangreich sind, dass der Arbeitsspeicher mächtig genutzt wird. Vielleicht habe ich auch etwas das verstanden, ich kenne nun nicht alle PHP Funktionen in Bezug auf die Bewertung aller internen Speicherroutinen.

        Kommentar


        • #5
          meinst du fgetcsv? So lese ich die Datei ein
          fgetcsv() liest aber nur eine Zeile. Ev. zeigst du mal genau her wie du aktuell deine Datei einliest, bzw. genau mit welchen Funktionen etc.. dann kann man ev. schon was dazu sagen.
          The string "()()" is not palindrom but the String "())(" is.

          Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
          PHP.de Wissenssammlung | Kein Support per PN

          Kommentar


          • #6
            Wenn die Rohdatei 3 MByte gross(was pro Spalte etwa 10 Byte entspicht) ist kann daraus eigentlich schwerlich ein Verbrauch von 120 MByte entstehen. Selbst wenn ich alles in ein assoziatives Array lade komme ich da nicht annähernd hin. Das Problem muss an anderer Stelle bestehen.

            Kommentar


            • #7
              Den genauen Ablauf darstellen wird vermutlich schwierig, dafür ist das Framework aus meiner Sicht zu verschachtelt.

              PHP-Code:
              protected function handleFile()
                  {
                      
              $database Factory::getDatabase();
                      
              $file $this->getFile();

                      if (
              file_exists($file))
                      {
                          if (
              $import $this->insertImport())
                          {   
                              
              $max     5000//
                              
              $max    $max 5000 5000 $max;
                              
                              
              $handle fopen($file'r');
                              while ((
              $data fgetcsv($handle0';')) !== false)
                              {
                                  
              $count count($data);
                                  
              $row++;
                                  
                                  if (
              $row == 1)
                                  {
                                      
              // handle the first row
                                      
              for ($i 0$i $count$i++)
                                      {
                                          
              $columns[$i] = trim(str_replace(
                                                  array(
              ' ''ä''ü''ö''ß'),
                                                  array(
              '_''ae''ue''oe''ss'),
                                                  
              mb_strtolower($data[$i], 'UTF-8')));
                                      }
                                      continue;
                                  }
                                  else
                                  {
                                      
              $obj = new Object();
                                      for (
              $i 0$i $count$i++)
                                      {
                                          
              $obj->set($columns[$i], $this->transform($columns[$i], $data[$i]));
                                      }
                                  }

                                  
              $table Table::getInstance('data');
                                  
              $table->bind($obj);
                                  
                                  if (!
              $table->store())
                                  {
                                         
              // error
                                  
              }
                              }
                              
              fclose ($handle);
                          }
                      }
                      return 
              true;
                  } 

              Kommentar


              • #8
                Schau dir mit einem Profiler an, wo der Speicher verbraucht wird.

                Kommentar


                • #9
                  Vermeide grosse Array-in-Array Konstrukte (Arrays sind von Natur aus ungemein speicherfressend in PHP).
                  Falls die Daten zu Vergleichszwecken doch vorgehalten werden müssen: Versuche leere Inhalte zu vermeiden (bzw. zu entfernen). Selbst wenn ein Wert im CSV "leer" ist, belegt er Speicherplatz im Array. Hast du viele solcher Lücken, kann das den Speicher extrem belasten. Problem/Nachteil: Wenn du die Lücken entfernst, müssen die Indizes beibehalten werden (um einen Vergleich konsistent möglich zu machen).
                  Ich hab mir eine kleine Helferklasse geschrieben, um CSV Daten RAM-schonend im Speicher zu halten. Dabei lege ich einen CSV Datensatz im Stringformat ab, beim Lesen-Zugriff wird der Datensatz ent- und beim Schreiben-Zugriff gepackt (die Klasse implementiert Iterator und ArrayAccess und lässt sich so wie ein Array behandeln). Hat mir sehr geholfen, sehr große CSV Dateien zu verarbeiten, ich muss mehrere davon gleichzeitigt geöffnet haben.

                  Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                  Kommentar

                  Lädt...
                  X