» Benchmark: $gentime vs. filemtime (Filecache)

problem mit imagesetpixelNeuen Thread eröffnenNeue Antwort erstellenlocalhost kann nicht aufgerufen werden
AutorNachricht
Administrator 

Name: Marc
Geschlecht:
Anmeldedatum: 28.08.2004
Beiträge: 52423
Wohnort: Lohmar


Meine eBay-Auktionen:
13.10.2009, 12:20
zitieren

Hi,

wegen einem Blogartikel, habe ich mich dran gemacht und mal getestet, welche Art der Speicherung Prüfung von Filecaches am schnellsten ist (z.B. wenn man Datenbankabfragen zwischenspeichert, statt sie erneut auszuführen).

Bisher nutzte ich include() und wollte auf filemtime() / file_get_contents() wechseln, da es bei sehr häufigen include() und Dateiänderungen dazu führt, dass die Datei unfertig eingebunden wird. Und was passiert, wenn man eine unfertige php-Datei einbindet? Richtig es erscheint die allseits bekannt $end-Fehlermeldung. Das Benchmark bestätigt mich jetzt noch mal in meiner Entscheidung auf reine Textdateien zu wechseln.

Hier die getesteten Codes:
<?php
/*
// version 1
// run: 0.247105841635
// run: 0.261900234224 refresh set to 10 seconds
// run: 0.256287105084 refresh set to 10 seconds
// run: [b]0.249131891729[/b] refresh set to 30 seconds
// fastest run: 0.104637145996
// run: 0.234740469457 without refresh
// fastest run: 0.0934660434723
// run: 0.237568306923 without refresh / without clearstatcache()
// fastest run: 0.147907018661
$gentime = 0;
$data = array();
// cache file will be included if it exists
if (file_exists($filename)) {
include($filename);
}
// cache file will be created if didn't existed or refreshed all 2 seconds
if (!$data || $gentime + 86400 < $now) {
// read data (db query...)
$data = array(
'id' => 1111,
0 => 'long text',
1 => 'long text',
2 => 'long text with quotes',
);
// write cache file
// it is necessary to lock first and truncate afterwards to avoid including a
// partial php file (won't work in 100% of all cases as it is still possible
// to include it after truncating it!)
$h = @fopen($filename, 'a');
@flock($h, LOCK_EX);
@ftruncate($h, 0);
@fwrite($h, '<' . '?php $gentime = ' . $now . '; $data = unserialize(\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), serialize($data)) . '\'); ?' . '>');
@flock($h, LOCK_UN);
@fclose($h);
@umask(0000);
@chmod($filename, 0644);
}
// only for the benchmark to avoid caching
clearstatcache();
*/
/*
// version 2
// run: 0.217099111083
// run: 0.222138965129
// run: 0.220421209337 refresh set to 10 seconds
// run: [b]0.222239365575[/b] refresh set to 30 seconds
// run: 0.219991838929 without refresh
// fastest run: 0.0898759365082
// run: 0.181516561508 without refresh / without clearstatcache()
// fastest run: 0.103751897812
$data = array();
// cache file will be included if it exists
if (file_exists($filename)) {
$data = @unserialize(file_get_contents($filename));
}
// cache file will be created if didn't existed or refreshed all 2 seconds
if (!$data || filemtime($filename) + 2 < $now) {
// read data (db query...)
$data = array(
'id' => 1111,
0 => 'long text',
1 => 'long text',
2 => 'long text with quotes',
);
// write cache file
// we do not need to lock, as unserialize results false if data set is corrupt
$h = @fopen($filename, 'w');
@fwrite($h, serialize($data));
@fclose($h);
@umask(0000);
@chmod($filename, 0644);
}
// only for the benchmark to avoid caching
clearstatcache();
*/
?>



Verfasst am: 14.10.2009, 00:45
zitieren

Mir sind noch drei Varianten eingefallen:
/*
// version 3
// run: [b]0.243602633478[/b]
// run: 0.245651497837 10 secs
// run: 0.233414025306 30 secs
// fastest run: 0.114813804626
$data = array();
$h = fopen($filename, 'a');
if (flock($h, LOCK_EX | LOCK_NB)) {
$data = @unserialize(file_get_contents($filename));
}
if (!$data || filemtime($filename) + 2 < $now) {
// read data (db query...)
$data = array(
'id' => 1111,
0 => 'long text',
1 => 'long text',
2 => 'long text with quotes',
  );
// write cache file
ftruncate($h, 0);
fwrite($h, serialize($data));
umask(0000);
chmod($filename, 0644);
}
flock($h, LOCK_UN);
fclose($h);
// only for the benchmark to avoid caching
clearstatcache();
*/
/*
// version 4
// [b]run: 0.188958084584[/b]
// run: 0.185067784788
// fastest run: 0.0628659725189
// cache file will be created if didn't existed or refreshed all 2 seconds
// we removed file_exists() as we expect in 99% of all cases that the file is
// existing and if not, file_get_contents() does the same for us
if (!($data = @file_get_contents($filename)) || ($data = @unserialize($data)) === false || filemtime($filename) + 2 < $now) {
// read data (db query...)
$data = array(
'id' => 1111,
0 => 'long text',
1 => 'long text',
2 => 'long text with quotes',
  );
// write cache file
// we do not need to lock, as unserialize results false if data set is corrupt
$h = @fopen($filename, 'w');
@fwrite($h, serialize($data));
@fclose($h);
@umask(0000);
@chmod($filename, 0644);
}
// only for the benchmark to avoid caching
clearstatcache();
*/
/*
// version 5
// [b]run: 0.0989973068235[/b]
// run: 0.0999602222446
// fastest run: 0.0978970527649
// our script results more than 100 hits per second, so we add a random
// switch to reduce usage of filemtime()
// if you run this script on a website, you have to count your daily impressions
// and decide how much filemtime() requests are needed to find the balance between
// cache actuality and interval. f.e.: you have a birthday data cache and you want
// to refresh it every 24 hours. your website results 100.000 impressions per day.
// i would choose 100 as a good random factor as there are 1.000 impressions left
// to refresh the cache. one of them should hit between 00:00 and 00:59 to result
// actual birthday data on the website (with factor 100 apprx. 42 impressions per
// hour can hit our random factor)
if (!($data = @file_get_contents($filename)) || ($data = @unserialize($data)) === false || (rand(0, 100) == 100 && filemtime($filename) + 2 < $now)) {
// read data (db query...)
$data = array(
'id' => 1111,
0 => 'long text',
1 => 'long text',
2 => 'long text with quotes',
  );
// write cache file
// we do not need to lock, as unserialize results false if data set is corrupt
$h = @fopen($filename, 'w');
@fwrite($h, serialize($data));
@fclose($h);
@umask(0000);
@chmod($filename, 0644);
}
if (isset($h)) {
// only for the benchmark to avoid caching
clearstatcache();
}
*/

 1x  bearbeitet

Verfasst am: 14.10.2009, 01:04
zitieren

15% konnte ich damit rausholen, dass ich auf file_exists() verzichtet habe und file_get_contents() und serialize() getrennt habe. Auf file_exists() können wir getrost verzichten, wenn wir unseren Cache immer nutzen. In dem Fall übernimmt file_get_contents() den Job.

Eigentlich ist file_get_contents() langsamer als file_exists(), aber das kommt nicht zum Tragen, da in 99,9% der Fälle ja eine Cache-Datei vorhanden sein wird und die Prüfung mit file_exists() damit überflüssig wird.

Danach habe ich eine weitere Idee ausprobiert, in der ich mir die Seitenaufrufe einer Website zu nutze mache. Da jede Cache-Datei durch den Besucher selbst ausgelöst wir, führt auch jeder Seitenaufruf zur entsprechenden Prüfung der Dateien mit filemtime(). Da diese Funktion aber bekanntlich zu viel Performance kostet und die Cache-Dateien nicht bei jedem Seitenaufruf erneuert werden müssen, machen wir uns einen Zufallsfaktor zu Nutze. Dieser hat die letzte Abfrage dann noch mal um 50% beschleunigt!

Geht man beispielsweise von 100.000 Seitenaufrufen pro Tag aus, so resultieren diese 100.000 Aufrufe von filemtime(). Das wollen wir nicht, weshalb wir einfach den Faktor 1:100 ins Spiel bringen. Schon reduzieren wir die Häufigkeit, mit der filemtime() aufgerufen wird auf 1.000. Damit haben wir noch ca. 42 Aufrufe pro Stunde. Haben wir nun einen Cache, der nur alle 24 Std. aktualisiert werden soll, wie z.B. die Geburtstagsliste aller Mitglieder, reicht das vollkommen für eine akzeptable Aktualität des Datensatzes.

Es kann zwar gut sein, dass die Geburtstage erst um 00:10 Uhr aktualisiert werden, aber im Regelfall sollte das reichen. Falls nicht, müsste man hier mit einem Zeitrahmen arbeiten, wo die Impressionen zwischen 00:00 und 00:10 Uhr z.B. alle zur Aktualisierung des Caches führen. Bei 100.000 Seitenaufrufen pro Tag fallen damit ca. 167 Aufrufe auf diese besagten 10 Minuten. Das wäre also sogar noch besser, da nur 167x, statt 1.000x die Funktion filemtime() aufgerufen wird.

Wie man sieht, kann man in diesem Punkt so einiges optimieren. Zumindest sollte man von dem flock-Konstrukt abkommen, dass weder performant, noch Sicherheit bietet, da man flock wiederrum beim Einlesen der Daten benötigt. Und ich glaube nicht, dass es so gut sein kann, wenn man bei mehreren Cache-Dateien in einem Seitenaufruf ständig sperrt und entsperrt.

Allerdings weiß ich noch nicht, ob der Wegfall von flock() Probleme machen könnte beim parallen Schreiben von identischen Cache-Datensätzen, was ja durchaus bei parallel laufenden Prozessen zum Tragen kommen könnte.

Da werde ich es aber einfach auf einen Test ankommen lassen und das Ergebnis hier noch mal in ein paar Monaten bereitstellen.
pn email
Gast 
14.10.2009, 01:04
zitieren

Mach mit!

Wenn Dir die Beiträge zum Thread "Benchmark: $gentime vs. filemtime (Filecache)" gefallen haben oder Du noch Fragen hast oder Ergänzungen machen möchtest, solltest Du Dich gleich bei uns anmelden:



Registrierte Mitglieder genießen die folgenden Vorteile:
✔ kostenlose Mitgliedschaft
keine Werbung
✔ direkter Austausch mit Gleichgesinnten
✔ neue Fragen stellen oder Diskussionen starten
✔ schnelle Hilfe bei Problemen
✔ Bilder und Videos hochladen
✔ und vieles mehr...


Neuen Thread eröffnenNeue Antwort erstellen
Ähnliche BeiträgeRe:
Letzter Beitrag
 Einfaches MySQL Benchmark PHP Skript (SELECT BENCHMARK)
Einfaches Skript um MySQl zu benchmarken: <?php $link = mysqli_connect&#40;"localhost", "root", ""&#41;; /&#x2A; check connection &#x2A;/ if &#40;mysqli_connect_errno&#40;&#41;&#41;...
[Allgemein]von mgutt
0
278
19.01.2017, 12:19
mgutt
3D Benchmark
Wollte mal gucken was eure PC´s so hergeben mein pc system: Asus Crosshair ATI 2900 GT Kingstone HyperX DDR1066 2GB standart SPD mit CL 5 xD und kleiner rein hier mal nen 3Dmark03 run mit meiner neuen CPU davor AMD X2 BE 2300 ca 21000...
von R3DEX
79
3.534
28.04.2011, 05:26
nfs_freak
Intel X25-M G2 160 GB Benchmark (SSDSA2M160G2GC)
Hi, von meiner neuen Platte hab ich mal ein Benchmark gemacht: HD Tune Pro: INTEL SSDSA2M160G2GC Benchmark Test capacity: full Read transfer rate Transfer Rate Minimum : 128.2 MB/s Transfer Rate Maximum : 198.2 MB/s Transfer Rate...
von mgutt
4
645
21.03.2011, 18:23
mgutt
JetFlash Transcend 16 GB Benchmark
Vielleicht kann ja jemand die Info gebrauchen. Hab den Stick...
von mgutt
0
156
09.05.2014, 07:22
mgutt
SanDisk Extreme 16 GB Benchmark
Vielleicht kann ja jemand die Info gebrauchen. Hab den Stick...
von mgutt
0
120
09.05.2014, 07:23
mgutt
SSD Benchmark: 4K Schreiben ist langsam?
Ich habe eine 850 Pro und nach einem Test mit AS SSD erscheint mir der 4K Schreibwert zu gering zu sein. Erst mal hier der Wert meiner alten 840...
von mgutt
5
1.478
08.12.2015, 17:52
Headshot91
preg_replace / preg_match Benchmark
Danach hatte ich eigentlich gesucht und bin auf etwas vergleichbares gestoßen: http://benchmark.nophia.de/benchmarks-textverarbeitung-k-2-texte-mit-mindestens-zwei-vokalen-b-21.html Dazu hätte ich direkt einen Verbesserungsvorschlag: <?PHP ...
[PHP]von mgutt
0
474
26.02.2009, 13:25
mgutt
Benchmark: Prepared Statements in Array
Hi, hier die Resultate: /* // version 1 // 1. run 0.14501937151 // 2. run 0.145541801453 // 3. run 0.141622686386 // fastest run 0.0934751033783 while ($field = $meta->fetch_field()) { $row[] =...
[PHP]von mgutt
0
527
09.10.2009, 18:39
mgutt
 ab.exe Apache Benchmark für Windows (Download)
Bitte...
[Allgemein]von Indianerjunge
0
0
19.01.2017, 11:27
Indianerjunge
strpos vs. in_array vs. isset - Performance-Benchmark
Ich wollte mal wissen was am schnellsten ist: <pre> <?php echo phpversion&#40;&#41; . PHP_EOL . PHP_EOL; $array = array_fill&#40;0, 10000, 16&#41;; $array = array_map&#40;'openssl_random_pseudo_bytes',...
[PHP]von mgutt
0
523
15.10.2017, 18:02
mgutt
© 2004 - 2025 www.programmierer-forum.de | Communities | Impressum |