Closed BugBuster1701 closed 11 years ago
Sowohl die Model-Relationen als (in Contao 3.1) auch die .xlf-Daten.
Also es geht allgemein um die Caching Mechanismen? Erstmal Grundlage, Caching sollte so laufen:
-> getIrgendwasCachefähiges()
? cache existiert
-> return cache
: erstelle Daten live
-> lege Daten in Cache
-> return Daten
Soweit sind wir uns denke ich einig?
Wenn ich mir die System::loadLanguageFile
anschaue, dann verhält die sich auch genau so:
https://github.com/contao/core/blob/master/system/modules/core/library/Contao/System.php#L371
Der Sprachencache ist also bereits so angelegt, das er nicht notwendig ist.
Sind die anderen Caches nicht auch schon so aufgebaut? Immerhin müssten die Caches doch die Option "internen Cache umgehen" berücksichtigen?
Wenn wir hier sind, wollen wir einen Schritt weiter gehen.
Um das Caching in einen Cron auszulagern ist eigentlich nicht sonderlich viel notwendig.
Eigentlich muss nur der Punkt -> lege Daten in Cache
optional gemacht werden.
Z.B. über eine Konstante/Parameter/whatever.
In der loadLanguageFile
könnte dass dann so aussehen:
...
if (!$GLOBALS['TL_CONFIG']['bypassCache'] && file_exists($strCacheFile))
{
include $strCacheFallback;
include $strCacheFile;
}
else if (CACHE_NOGENERATE)
{
// Parse all active modules
foreach (\Config::getInstance()->getActiveModules() as $strModule)
{
$strFallback = TL_ROOT . '/system/modules/' . $strModule . '/languages/en/' . $strName . '.php';
if (file_exists($strFallback))
{
include $strFallback;
}
if ($strLanguage == 'en')
{
continue;
}
$strFile = TL_ROOT . '/system/modules/' . $strModule . '/languages/' . $strLanguage . '/' . $strName . '.php';
if (file_exists($strFile))
{
include $strFile;
}
}
}
else
{
// Generate the cache files
$objCacheFallback = new \File('system/cache/language/en/' . $strName . '.php');
$objCacheFallback->write('<?php '); // add one space to prevent the "unexpected $end" error
$objCacheFile = new \File('system/cache/language/' . $strLanguage . '/' . $strName . '.php');
$objCacheFile->write('<?php '); // add one space to prevent the "unexpected $end" error
// Parse all active modules
foreach (\Config::getInstance()->getActiveModules() as $strModule)
{
$strFallback = TL_ROOT . '/system/modules/' . $strModule . '/languages/en/' . $strName . '.php';
if (file_exists($strFallback))
{
$objCacheFallback->append(static::readPhpFileWithoutTags($strFallback));
include $strFallback;
}
if ($strLanguage == 'en')
{
continue;
}
$strFile = TL_ROOT . '/system/modules/' . $strModule . '/languages/' . $strLanguage . '/' . $strName . '.php';
if (file_exists($strFile))
{
$objCacheFile->append(static::readPhpFileWithoutTags($strFile));
include $strFile;
}
}
$objCacheFallback->close();
$objCacheFile->close();
}
...
Das Cron Script / Wartungsmodul müsste dann nur noch alle Module durch laufen und alle Sprachdateien laden. Das ist zwar eine Ressourcenhungrige Operation, stört aber in einem Cron oder im Wartungsmodul nicht wirklich.
Das Cron Script müsste nur ein define('CACHE_NOGENERATE', false)
machen, während define('CACHE_NOGENERATE', true)
die Standardeinstellung für den Normalbetrieb wäre. Das würde im bypassCache
Modus sogar dafür sorgen, dass nicht ständig die Cache Dateien neu geschrieben werden.
Soweit sind wir uns denke ich einig?
Soweit sind wir uns einig und nach genau diesem Prinzip funktioniert der Cache in Contao auch. Aus Effizienzgründen werden aber nicht die ganzen Einzeldateien per include
aufgerufen, sondern nur die aggregierte temporäre Datei kurz bevor sie an ihre eigentliche Position verschoben wird. Wenn die Option "internen Cache umgehen" aktiviert ist, könnte man die Daten auch in einen String schreiben und ihn durch eval()
schicken, um sich das Erstellen der Dateien zu sparen.
Würden wir Leo Unglaub's Idee implementieren, wäre ich jedoch dafür, dass die Routine zur Erstellung der Cache-Dateien komplett in den Automator ausgelagert wird. Die loadLanguageFile()
sollte dann nur noch "Lade aus dem Cache" oder "Lade die Einzeldateien" machen.
Die Frage ist, ob das alles notwendig ist bzw. irgendwelche lohnenswerten Vorteil bringt.
Ich habe die Änderungen für Contao 3.1 in 5c7ac78013fcb30f72dc4c04cc26bc543d55bb50 vorgenommen.
Ja, das sieht sehr gut aus, werde ich im Rahmen meines nächsten Projektes auch mal testen ;-)
Mal angenommen der Cache ist leer. (cron, frische Installation, ...) Nun folgen 2 Zugriffe zu selben Zeit. Der erste bewirkt, dass z.b. die Cache Datei dca/tl_module.php geschrieben wird. Während der geschrieben wird, fängt der zweite schon an die zu lesen, da die Datei ja bereits existiert. Nun ist das lesen aber schneller als das schreiben und die Sache explodiert.
Ich habe mal mit 100 Requests, davon max 10 gleichzeitig, gestestet, davon sind 14 auf Fehler gelaufen.
Das ist keine Theorie. Getestet habe ich das, da es in der Praxis bereits aufgetreten ist und ich die Ursache, die als Theorie vorlag, prüfen wollte.