Memory Fehler beim Kopieren einer View

Hallo,

ich wollte jetzt eine View mit dem Tool von Andreas kopieren und bekomme die Meldung: Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 41 bytes).

Die View (IOS) selbst ist 2,6 MB groß, die Hintergrundbilder habe ich vorher entfernt.

Gruß
Hans

Bei mir genauso, wobei der Server noch ca. 6 GB RAM frei hat.

Hatte ich auch mal…aber zu lange her, kann mich nicht mehr genau dran erinnern :frowning:

Finde auch die passende EMail von Brownson leider nicht mehr…

-Chris-

Bei war es die Größe der Bilder. View kopieren, Bilder löschen, anpassen des Scripts das Kopie verwendet wird und gut ist - geht also nun weiter ;):

Hallo,

danke für die Hinweise. Wie erwähnt habe ich die HIntergrundbilder gelöscht. Die View ist ja auch nur 2,6 MB groß. Wenn ich anfange die Bilder der Button zu löschen, dann kann ich auch gleich die View unter einem anderen Namen speichern und manuell anpassen :smiley:

Beim Kopieren selbst habe ich die Skalierung auf 1.0 gelassen, um mögliche Skalierungsprobleme zu umgehen.

Die View hat allerdings recht viele Button und von daher vermute ich irgendeine Art von Speicherüberlauf. Aber vielleicht hat Andreas ja eine Idee, immerhin kann Bayaro sich erinnern, dass da mal was war :slight_smile:

Gruß
Hans

Das Laden, Kopieren und Auswerten der View in PHP ist relativ Speicher intensiv. Ich werde in den nächsten Tagen noch eine Version des Scriptes posten, das einen optimierten Speicherverbrauch hat.

Hier mal eine modifizierte Version des Scriptes:


<?
	/**
	 * @file          IPSView_ResizeView.php
	 * @author        brownson
	 * @version
	 *   Version 1.0, 2015-08-10 brownson: Initiale Version<br/>
	 *   Version 1.1, 2016-01-27 brownson: Reduced Memory Usage<br/>
	 *
	 * IPSView Skript um eine View auf eine andere View zu kopieren inklusive
	 * Umrechung der Skalierung von X und Y Achse.
	 *
	 * Konfiguration Einstellungen:
	 *   * $masterViewID     - ID der View von der kopiert werden soll
	 *   * $childViewID      - ID der View auf die kopiert werden soll
	 *   * $childViewFactorX - Umrechnungsfaktor für die X Achse
	 *   * $childViewFactorY - Umrechnungsfaktor für die Y Achse
	 *
	 */

	// Konfiguration
	$masterViewID        = 12345;
	$childViewID         = 67890;
	$childViewFactorX    = 2.5;
	$childViewFactorY    = 2.13;

	// -------------------------------------------------------------------------

	// Konfiguration überprüfen
	if ($masterViewID == '') {
		die('Bitte geben Sie eine MasterViewID in der Konfiguration an.');
	}

	// Konfiguration überprüfen
	if ($childViewID == '') {
		die('Bitte geben Sie eine ChildViewID in der Konfiguration an.');
	}

	echo "Convert View with FactorX=$childViewFactorX and FactorY=$childViewFactorY".PHP_EOL;
	echo "Available Memory: ".ini_get('memory_limit').' ';
echo "".PHP_EOL;

   showMemoryUsage('Startup: ');

	$viewProperties = getViewProperties ($childViewID);
	$masterObj      = getViewObject($masterViewID);

	// Build Result Object
	$resultObj                   = resizeView ($masterObj, $childViewFactorX, $childViewFactorY);
	$resultObj['ViewRatio12']    = $viewProperties['ViewRatio12'];
	$resultObj['Name']           = $viewProperties['Name'];
	$resultObj['ID']             = $childViewID;
	$resultObj['Width']          = $viewProperties['Width'];
	$resultObj['Height']         = $viewProperties['Height'];
	$resultObj['Client']         = $viewProperties['Client'];
	$resultObj['Hardware']       = $viewProperties['Hardware'];

   showMemoryUsage('Build Result:');
   $masterObj = null;
   
	// Write Data to View
	writeViewContent ($childViewID, $resultObj);
	$resultObj = null;
   showMemoryUsage('finished:');

	echo ' '.PHP_EOL;
	echo '============================================================='.PHP_EOL;
	echo 'Successfully finished synchronization                        '.PHP_EOL;
	echo '============================================================='.PHP_EOL;

	// ----------------------------------------------------------------------------------------------------
	function writeViewContent ($ID, $viewObj) {
	   $name    = IPS_GetName($ID);
		// Write Data to View

		$data        = json_encode($viewObj);
	   showMemoryUsage("json_encode '$name'");
		$viewObj = null;

		$content     = base64_encode($data);
	   showMemoryUsage("base64_encode '$name'");
		$data = null;

		IPS_SetMediaContent($ID, $content);
	   showMemoryUsage("IPS_SetMediaContent '$name'");
		$resultContent = null;
	}

	// ----------------------------------------------------------------------------------------------------
	function getViewProperties ($ID) {
	   $viewObj = getViewObject($ID);
	   $name    = IPS_GetName($ID);

		$result                   = array();
		$result['ViewRatio12']    = $viewObj['ViewRatio12'];
		$result['Name']           = $viewObj['Name'];
		$result['ID']             = $viewObj['ID'];
		$result['Width']          = $viewObj['Width'];
		$result['Height']         = $viewObj['Height'];
		$result['Client']         = $viewObj['Client'];
		$result['Hardware']       = $viewObj['Hardware'];
   	showMemoryUsage("getViewProperties '$name'");

	   return $result;
	}

	// ----------------------------------------------------------------------------------------------------
	function getViewObject($ID) {
	   $name = IPS_GetName($ID);
	
		// Read Content of View
		$content     = IPS_GetMediaContent($ID);
	   showMemoryUsage("IPS_GetMediaContent '$name'");
		if ($content===false) {
			die("Media Objekt von Master konnte NICHT gefunden werden");
		}

		$data         = base64_decode($content);
	   showMemoryUsage("base64_decode '$name'");
		$content      = null;

		$obj          = json_decode($data, true);
	   showMemoryUsage("json_decode '$name'");
		$data         = null;
	 	if ($obj===false) {
			die("JSON Objekt von View '$name' konnte NICHT dekodiert werden");
		}
		return $obj;
	}

	// ----------------------------------------------------------------------------------------------------
	function resizeView ($jsonObj, $factorX, $factorY) {
		$factor = $factorX > $factorY ? $factorY : $factorX;
		$pages  = array();
		foreach ($jsonObj['Pages'] as $page) {
		   //echo "Process Page=".$page['DisplayName'].PHP_EOL;
			$controls = array();
			foreach ($page['Controls'] as $control) {
				$control['Width']     = round($control['Width'] * $factorX);
				$control['Height']    = round($control['Height'] * $factorY);
				$control['LocationX'] = round($control['LocationX'] * $factorX);
				$control['LocationY'] = round($control['LocationY'] * $factorY);
				if (array_key_exists('Font', $control) && array_key_exists('Size', $control['Font'])) {
				   $control['Font']['Size'] = round($control['Font']['Size'] * $factor);
				}
				if (array_key_exists('CR1', $control)) $control['CR1'] = round($control['CR1'] * $factor);
				if (array_key_exists('CR2', $control)) $control['CR2'] = round($control['CR2'] * $factor);
				if (array_key_exists('CR3', $control)) $control['CR3'] = round($control['CR3'] * $factor);
				if (array_key_exists('CR4', $control)) $control['CR4'] = round($control['CR4'] * $factor);
				$controls[] = $control;
			}
			$page['Controls']    = $controls;
			$page['PopupWidth']  = round($page['PopupWidth'] * $factorX);
			$page['PopupHeight'] = round($page['PopupHeight'] * $factorY);
			$pages[] = $page;
		}
		$jsonObj['Pages'] = $pages;

		return $jsonObj;
	}

	// ----------------------------------------------------------------------------------------------------
	function showMemoryUsage($statusMessage) {
		$statusMessage = substr($statusMessage.'                                                            ', 0, 60);
		$memory = round(memory_get_usage() / 1024 / 1024, 2);
	   echo $statusMessage . ' UsedMemory='.$memory. " MB".PHP_EOL;
	}

?>

Konnte den Speicherverbrauch um über 50% senken (diese Version des Scriptes logged auch den Speicherverbrauch in den verschiedenen Phasen des Kopiervorgangs).

Hallo Andreas,

super, nun hat es geklappt :slight_smile: Ich habe einige Testdurchläufe gemacht. Wichtig scheint zu sein, dass man vorher die Hintergrundbilder löscht, da diese die View doch erheblich vergrößern. Der höchste Memory Wert befindet sich bei mir in den Zeilen base64_decode und json_encode (je ca. 23 MB).

Gruß
Hans

Ich versuche gerade mit der optimierten Version eine View zu kopieren, jedoch bekomme ich immer die Meldung:

Ich habe auch schon alle Hintergrundbilder entfernt - dennoch die selbe Meldung.

Was mache ich falsch?

Danke.

Prinzipiell nichts, Deine View hat allerdings noch immer 18 MB und das ist zu viel für die PHP Session in IP-Symcon.

Entweder versuchst Du die View kleiner zu bekommen (hast sicher noch einige riesige Images drinnen) oder versuchst über die php.ini mehr Speicher zu bekommen.

Prima, der Hinweis mit der php.ini war Gold wert, ich habe das Limit auf 64 MB angehoben (der Server hat noch 10 GB RAM frei - sollte also nicht das Problem sein ;)).

Nun laufen auch die Anpassungen durch und ich konnte meine beiden Views anpassen (iPad Pro und iPhone 6s Plus).

Nun läuft alles so wie es sein soll :).

Danke dir.