API Allowed memory size exhausted

hi, ich importiere Artikel über die API in einer Schleife. Da es über 3000 Artikel mit unzähligen Varianten sind, lasse ich diese über eine Schleife laufen und Importiere imm chunks von 25 Artikel.

foreach ($customCategoryArticles->article as $article) {
   [...]
   $this->getShopwareArticleResource()->batch($articleData);
}

Das geht bis ca. 2500 Artikel gut und dann läuft mir der Speicher voll

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 72 bytes) in /vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php on line 372

Gib es die Möglichkeit zwischendurch den Speicher freizugeben?

Vielen Dank

 

Hi,

versuche Mal Shopware()->Models()->clear() nach jedem Aufruf von “batch”, damit werden die von der UnitOfWork vorgehalteten Entities gelöst. So wie ich das sehe, sollte das eigentlich bereits durch den Autoflush passieren. Aber das wäre mein erster Gedanke dazu. Ggf. kannst du die BatchSize auch noch erhöhen, hängt aber auch von der Anzahl der Varianten ab.

Weiterhin solltest du darauf achten, dass du für den Aufbau der Daten in deinem Code keine Entities vorhältst, die später nicht mehr freigegeben werden. 

Besten Gruß,

Daniel

@Daniel Nögel schrieb:

Hi,

versuche Mal Shopware()->Models()->clear() nach jedem Aufruf von „batch“, […] kannst du die BatchSize auch noch erhöhen, hängt aber auch von der Anzahl der Varianten ab.

Weiterhin solltest du darauf achten, dass du für den Aufbau der Daten in deinem Code keine Entities vorhältst, die später nicht mehr freigegeben werden. 

Besten Gruß,

Daniel

Hallo Daniel, vielen Dank für deine Antwort. Leider hat das nicht funktioniert.

Ich hole mir die Artikel-Informationen über ein externes XML und  speichere sie in ein simplexml-Objekt.  Ich rufe das ganze über die CLI auf. Ich rufe die Funktion so lange auf, bis das offset >= gesamtanzahl ist. Durch das erneute aufrufen der Funktion sollten die Variablen doch eigentlich destroyed werden sobald sie nicht mehr im scope sind oder?

Hast du noch einen Tipp? Das memory_limit auf dem Server liegt bei 1024M und das ganze läuft auf einem nginx.

Warum sollte ich die Batch-Size erhöhen? sollte ich die nicht eher verringern?

 hier mal ein schnipsel:

                    if(!empty($offset) && $offset !=0) {
                        $import = $max->importArticles(false, $offset, 20);
                    }else{
                        $import = $max->importArticles(false, null, 20);
                    }

                    if($import['offset'] && $import['offset'] != $import['count']) {
                        //import Articles
                        $arguments = array(
                            'command' => 'maxout:meinplugin:import',
                            'type' => 'articles',
                            'offset' => $import['offset'],
                        );
                        $importArticlesInput = new ArrayInput($arguments);
                        $output->writeln('' . sprintf("%s", $import['message']) . '');
                        $command->run($importArticlesInput, $output);
                    }else{
                        $output->writeln(''.strip_tags($import['message']).'');
                    }

 

hallo @hbee‍,

das Memory_limit existiert, um das lange Code zu anhalten, wenn es so lange dauert.

Die lösung ist , das Memory_limit zu erhöhen.

Oder Sie dürfen einen Workaround finden.

in Ihr Code können sie die Artikels , B.S jeden 100 Arikels in einem Batch, machen.

dann nach jeden call spieren wie viel Artikels hast du schon importeren in einem Datei.

in die nächste Code rufen , fang von last Arikel an.

VG,

Ahmad.

@ahmadsaad schrieb:

hallo @hbee‍,

das Memory_limit existiert, um das lange Code zu anhalten, wenn es so lange dauert.

Die lösung ist , das Memory_limit zu erhöhen.

Oder Sie dürfen einen Workaround finden.

in Ihr Code können sie die Artikels , B.S jeden 100 Arikels in einem Batch, machen.

dann nach jeden call spieren wie viel Artikels hast du schon importeren in einem Datei.

in die nächste Code rufen , fang von last Arikel an.

VG,

Ahmad.

Hallo Ahmad, ich binmir nciht sicher ob ich dich richtig verstanden habe. aber ich dneke du verwechselst memory_limit mit max_execution_time.

Ich lasse die Artikel ja schon in einem batch importieren und rufe die Funktion dann erneut auf.  irgendwann bricht die schleife aber ab. nicht wegen der Laufzeit, sondern wegen des memory_limits. Wie oben geschriben führe ich das script auf der console aus.

vielen Dank

Hallo,

du hast Richt, ich meine (wenn ein Code so lange dauert, benutzt es mehr und mehr memory). (ich bin nicht so gut auf Deutsch Undecided)

jeden array, varaibale, Entity , werden in die Memory gespeichert.

also Daniel Lösung Shopware()->Models()->clear()  zu beuntzen werde die Entities von die Memory gelöscht.

aber ich glaube , mit 3000 Artikel diese ist nicht genug.

was ich normaelweiße mache. speichen die letzte Artikel Array index nach jeden AnRuf in einem Datei (B.S .‘count’).

und raufe ich Das Code via Cronjob zwei drei mal jeden halb Stunde.

am Anfang prüfe ich ob die Datei .count existieren, dann nehme ich das index von die Datei and fang von diese index an.

ob nicht fang von vone (0) an.

ich hoffe dass ich habe jetzt besser erklärt.

VG

Ahmad.