serviceType SessionSingleton beim DIServiceManager

Im Entwickler-Forum können Implementierungsdetails sowie Alternativen der Umsetzung diskutiert werden. // Here, developers can discuss implementation details of features of their projects.
Antworten
dingsda
Beiträge: 49
Registriert: 03.02.2014, 04:00:36

serviceType SessionSingleton beim DIServiceManager

Beitrag von dingsda » 30.05.2014, 15:45:45

Hallo,
ich weiß nicht genau, ob das ein bug ist, ein fehler in der Docu oder ob ich es einfach nur missverstehe.

in abschnitt 4.4 Gültigkeitsbereiche steht zu sessionSingleton:
Ein weiterer Anwendungsfall ist die mehrfache Verwendung eines Service an unterschiedlichen Stellen innerhalb eines Besuchs, dessen Initialisierung aufwendig ist und daher nur einmal durchgeführt werden soll.
das verstehe ich so, dass der DIServiceManager auch nur beim ersten aufruf während einer Session das object initialisiert und konfiguriert. dies ist allerdings nicht der fall.
der DIServiceManager liest unabhängig vom ServiceType alle konfigurationen ein und injiziert sie in das object und erst vor aufruf der Setupmethod wird geprüft ob das object initialisiert ist. *


ich weiß nun nicht, ob das ein gewolltes verhalten ist und ich es einfach nur missverstanden habe jedenfall ist das gerade bei complexen konfigurationen wie z.b. beim GORM wenn man ihm noch einige extra mapping- und relations-definitionen mitgibt doch auch ein performance-faktor wenn alle konfigurationen nochmal übergeben werden, obwohl das object schon längst initialisiert ist.

an welcher stelle man nun am besten für die lösung (falls bug) ansetzt weiß ich grad nicht. vieleicht schon direkt nach lesen der konfiguration prüfen ob das object initialisiert ist?

lg
dingsda

* edit: lediglich bei singleton wird natürlich aus dem object cache des DIServiceManagers das object direkt zurückgegeben.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: serviceType SessionSingleton beim DIServiceManager

Beitrag von dr.e. » 08.06.2014, 12:09:03

Hi,
* edit: lediglich bei singleton wird natürlich aus dem object cache des DIServiceManagers das object direkt zurückgegeben.
Korrekt! Das ist eine Performance-Optimierung, da das initialisieren der Services einfach zu lange dauert und die Anwendung nachhaltig verlangsamt.
ich weiß nun nicht, ob das ein gewolltes verhalten ist und ich es einfach nur missverstanden habe jedenfall ist das gerade bei complexen konfigurationen wie z.b. beim GORM wenn man ihm noch einige extra mapping- und relations-definitionen mitgibt doch auch ein performance-faktor wenn alle konfigurationen nochmal übergeben werden, obwohl das object schon längst initialisiert ist.
Das ist ein zweischneidiges Schwert - ja. :D Sofern ich ein Objekt nach der ersten Initialisierung als "initialisiert" markiere - das kannst du mit der Methode isInitialized() in deinem Objekt ja tun - dann werden ggf. tiefere Abhängigkeiten nicht mehr aktualisiert. Sollte das eine Datenbank-Verbindung sein, wird das zu einem Fehler in der Applikation führen. Aus diesem Grund baue ich die Abhängigkeiten - nicht die Objekte - jeweils komplett zusammen. Zugegeben, mir ist bisher auch kein besserer Weg eingefallen um Initialisierungsfehler prinzipiell zu vermeiden.
an welcher stelle man nun am besten für die lösung (falls bug) ansetzt weiß ich grad nicht. vieleicht schon direkt nach lesen der konfiguration prüfen ob das object initialisiert ist?
Das könntest du tun, allerdings weißt du ja nicht, welches Objekt du hast, wenn du die Konfiguration noch nicht gelesen hast. Eine Optimierung hinsichtlich Performance ist natürlich immer möglich: die Konfiguration in (u)APC zu cachen. Dann liest du sie aus dem Hauptspeicher und produzierst damit weniger Latenzen beim Lesen.

Verbesserungsvorschläge sind daher herzlich willkommen! :)
Viele Grüße,
Christian

dingsda
Beiträge: 49
Registriert: 03.02.2014, 04:00:36

Re: serviceType SessionSingleton beim DIServiceManager

Beitrag von dingsda » 10.06.2014, 00:50:11

an sich ist ja das problem wie du schon sagst nur, dass man in php resourcen nicht serialisieren kann. deshalb haben klassen wie der gorm die eine verbindung zur datenbank aufbauen die sleep und wakeup methoden. allerdings hat der gorm ja nicht direkt die resource gespeichert sonder nur einen databaseHandler der erst die resource enthält.
man sollte also eher in dieser tieferen ebene ansetzen und die sleep und wakeup methode einbauen um sie aus dem gorm und anderen klassen, die nicht direkt mit ressourcen zu tun haben entfernen zu können. dann braucht man nicht erneut die objekte zu konfigurieren, weil die konfiguration erhalten bleibt.

ich hab vorhin kurz mal was dazu ausprobiert.

im diservicemanager gleich nach laden des objects hab ich das hier

Code: Alles auswählen

     if($serviceObject->isInitialized()){
         // add service object to cache and return it
         self::$SERVICE_OBJECT_CACHE[$cacheKey] = $serviceObject;
         $t->stop($benchId);
         return self::$SERVICE_OBJECT_CACHE[$cacheKey];
      }
sleep und wakeup beim mysqli-handler eingebaut und beim gorm, umgtmanager ect entfernt.

bei einem kurzen test kam auf jeden fall kein fehler obwohl die objecte aus der session geladen wurden. es scheint also zu funktionieren.

natürlich kann man auch durch cachen der konfiguration etwas performance rausholen aber das laden der konfiguration macht weniger aus als das erneute konfigurieren der eigentlich bereits fertig initialisierten objecte.

ein weiteres problem was ich hier aus dem forum mit der serialisierung der objekte rauslesen konnte war das der _incomplete_class_ fehler der auftrat, wenn objekte in der property eines serialisierten objektes gespeichert waren und vor dem deserialisieren nicht die klassendefinition importiert wurde.
das problem scheint mir aber nun mit autoloader kein problem mehr zu sein.

ich hab mal meine veränderungen in mein repository gepuscht
https://github.com/dingsda87/code/tree/ ... nSingleton
ist wie gesagt erstmal nur ein test und funktioniert auch nur mit dem mysqliHandler, weil ich nur dort jetzt die methoden wakeup und sleep schon eingebaut habe.

liebe grüße
dingsda

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: serviceType SessionSingleton beim DIServiceManager

Beitrag von dr.e. » 10.06.2014, 17:10:35

Hi,

danke für den POC. Lass uns das mal für 2.2 angehen. Einverstanden?
Viele Grüße,
Christian

dingsda
Beiträge: 49
Registriert: 03.02.2014, 04:00:36

Re: serviceType SessionSingleton beim DIServiceManager

Beitrag von dingsda » 10.06.2014, 22:06:30

können wir machen. muss sicherlich noch etwas genauer genauer geschaut werden, ob sich das wirklich so umsetzen lässt wie ich da vorschlage.

mir ist da nämlich tatsächlich schon ein problem aufgefallen, dass das ganze vielleicht unsinnig macht.
weiß nicht wie ich es beschreiben soll, daher mal als beispiel

Code: Alles auswählen

[gormA]

servicetype = "SESSIONSINGLETON"
class = "APF\modules\genericormapper\data\GenericORRelationMapper"

init.db.method=setDbDriver
init.db.namespace=myappgorm
init.db.name=MyDB

// weitere configurationen

[gormB]

servicetype = "SESSIONSINGLETON"
class = "APF\modules\genericormapper\data\GenericORRelationMapper"

init.db.method=setDbDriver
init.db.namespace=myappgorm
init.db.name=MyDB
// weitere configurationen

 
gorm A und B haben verschiedene configurationen aber nutzen das selbe databaseHandlerObject. So wie die DI aktuell arbeitet funktioniert das auch genau so wie gedacht. das databaseHandlerObject wird nur einmal pro request initialisiert selbst wenn beide gorms aufgebaut werden. bei meinem POC ist das ab dem zweiten request nicht mehr der fall. durch das serialisieren geht natürlich die referenz verloren.
das könnte wahrscheinlich schon zu problemen führen, wenn man wirklich das selbe object an zwei verschiedenen stellen braucht.
außerdem baut jedes databasehandlerobject wieder unnötig eine datenbankverbindung auf

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: serviceType SessionSingleton beim DIServiceManager

Beitrag von dr.e. » 11.06.2014, 13:00:00

Hi,
das könnte wahrscheinlich schon zu problemen führen, wenn man wirklich das selbe object an zwei verschiedenen stellen braucht.
Korrekt. Das war auch der Grund, warum ich in einer früheren Version die instanceId eingeführt habe um beim Erstellen per Singleton auch wirklich zwei Datenbankverbindungen der selben Klasse erzeugen zu können.

Lass uns mal die Optionen sammeln und dann die Anwendungsfälle dagegen validieren.
Viele Grüße,
Christian

dingsda
Beiträge: 49
Registriert: 03.02.2014, 04:00:36

Re: serviceType SessionSingleton beim DIServiceManager

Beitrag von dingsda » 14.06.2014, 01:04:23

entweder ich missverstehe dich oder du mich :D

das problem bei meinem poc ist nicht, dass man nicht zwei datenbankverbindung herstellen kann sondern dass man nach der serialisierung grundsätzlich nicht mehr eine einzige singleton datenbankverbindungen erstellen kann.

das problem ist die serialisierung und gilt für jedes object, nicht nur datenbankverbindungen.

Code: Alles auswählen

class foo {
   public function __wakeup() {
      var_dump('foo ist aufgewacht');
   }
}

class bar {
   protected $foo;

   public function setFoo(foo $foo) {
      $this->foo = $foo;
   }
   
   public function getFoo() {
      return $this->foo;
   }
}

$foo = new foo();

$a = new bar();
$a->setFoo($foo);

$b = new bar();
$b->setFoo($foo);

var_dump($a->getFoo() === $b->getFoo());

$a = unserialize(serialize($a));
$b = unserialize(serialize($b));

var_dump($a->getFoo() === $b->getFoo());
 
ausgabe

Code: Alles auswählen

boolean true
string 'foo ist aufgewacht' (length=18)
string 'foo ist aufgewacht' (length=18)
boolean false
insofern muss man also wirklich die objekte vor dem serialisieren mittels sleep von injizierten objekten bereinigen und sie nach dem deserialiesieren wieder injizieren, so wie das aktuell der DI auch macht. lediglich die gesamte conf-section könnte man wohl beim DI überspringen. denn damit werden ja keine objekte injiziert sondern nur attribute

edit: von der performance her ist mein poc daher auch nicht besser als der aktuelle DI. ich hatte überhaupt nur deshalb etwas performance-probleme mit dem DI gehabt, weil ich vergessen habe dass ich xdebug noch auf logging von funktionsaufrufen eingestellt hatte :oops: . da hat das schon nen großen unterschied gemacht, weil ja mit meinem poc weniger funktionen aufgerufen werden

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: serviceType SessionSingleton beim DIServiceManager

Beitrag von dr.e. » 15.06.2014, 22:16:28

Hallo,

dann habe ich dich tatsächlich zunächst falsch verstanden.
insofern muss man also wirklich die objekte vor dem serialisieren mittels sleep von injizierten objekten bereinigen und sie nach dem deserialiesieren wieder injizieren, so wie das aktuell der DI auch macht.
Schade, aber gut, dass du die Implementierung dadurch wenigstes bestätigen konntest.
lediglich die gesamte conf-section könnte man wohl beim DI überspringen. denn damit werden ja keine objekte injiziert sondern nur attribute
Das könnten wir in der Tat mal versuchen.
edit: von der performance her ist mein poc daher auch nicht besser als der aktuelle DI. ich hatte überhaupt nur deshalb etwas performance-probleme mit dem DI gehabt, weil ich vergessen habe dass ich xdebug noch auf logging von funktionsaufrufen eingestellt hatte :oops: . da hat das schon nen großen unterschied gemacht, weil ja mit meinem poc weniger funktionen aufgerufen werden
Gut, dass du's gefunden hast! ;) Grundsätzlich ist der DISM taträchlich nicht der schnellste und mir fehlt nach deinem POC auch tatsächlich eine sinnvolle Idee zur Verbesserung. Schade... :)
Viele Grüße,
Christian

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste