Warten in Warteschleife

Alice

Erfahrenes Mitglied
Hallo. :)

Ich hatte zwar schon einmal ein ganz ähnliches Thema, jedoch möchte ich die Diskussion neustarten aus diversen Gründen.

Ich habe meinen Verkehrzeichen Generator (Generiert Verkehrzeichen wie Straßenschilder) ausgibig getestet und habe festgestellt das wenn man den Generator mehrmals ausführt (in verschiedenen Tabs) sich die Ausführzeit immer um ca. 2-3 Sekunden erhöht.

1. Run - Straßenschild -> 4-5 Sekunden
2. Run - Stop-Shild -> 7-8 Sekunden
3. Run - Autobahnschild -> 9-10 Sekunden

Wenn ich jeweils nur ein Schild erstelle, braucht das Skript nie länger wie 4-5 Sekunden.

1. Frage:

Jetzt habe ich erst einmal zu der Ausführzeit eine Frage.
Ich weiss jetzt nicht genau warum sich die Ausführzeit immer um 2-3 Sekunden pro Schild erhöht? Liegt es am Server (Power) oder liegt es evtl. auch am Dateinamen?

Beispiel:
Server -> schilder-generator-deutschland.php
Server -> schilder-generator-schweiz.php

Sagen wir das Skript "schilder-generator-deutschland.php" wäre 5 mal gleichzeitig am laufen. Dann würde sich die Ausführzeit ja immer (im besten Fall) um 2-3 Sekunden verlängern.

schilder-generator-deutschland.php:
1. Run -> 4-5 Sekunden
2. Run -> 7-8 Sekunden
3. Run -> 9-10 Sekunden
4. Run -> 12-13 Sekunden
5. Run -> 15-16 Sekunden

Wie lange würde dann "schilder-generator-schweiz.php" laufen wenn ich es direkt nach dem 5. Run starten würde? Würde die Ausführungzeit wie bei "schilder-generator-deutschland.php" immer proportional ansteigen oder würde der Server den anderen Generator als "neuen Task" oder so bearbeiten und wäre in 4-5 Sekunden fertig? Oder würde das andere Skript (schweiz) 18-19 Sekunden laufen?

2. Frage:

Ich weiss nicht mehr genau ob ich diese Idee hatte, oder ob mir das jemand vorgeschlagen hat. Jedenfalls wäre es evtl. ganz Sinnvoll eine Warteschleife in das Skript einzubauen.

Die Idee:
Wenn der Generator gestartet wird, wird eine "1" in die DB geschrieben. Wenn das Skript fertig ist (ganz am Ende) wird die zuvor eingetragene "1" in "0" geändert. Solange eine "1" eingetragen ist, kann das selbe Skript nicht noch einmal ausgeführt werden.

Dieser Teil ist ja simpel zu programmieren aber wie mache ich das mit der Warteschleifen? Denn die Eingaben des User sollen ja nicht gelöscht werden und aus der "Run-Befehl" soll nicht gelöscht werden. Also Sachen wie "probieren sie es später" usw. sind nicht mein ding.

Hat hier jemand eine Idee wie ich das machen könnte?

Danke im Vorraus.
 
Zuletzt bearbeitet:
Hi

Ich habe meinen Verkehrzeichen Generator (Generiert Verkehrzeichen wie Straßenschilder) ausgibig getestet und habe festgestellt das wenn man den Generator mehrmals ausführt (in verschiedenen Tabs)...
Du meinst hoffentlich gleichzeitig?

Wenn ich jeweils nur ein Schild erstelle, braucht das Skript nie länger wie 4-5 Sekunden.
Weiss ja nicht, was du da machst, aber das ist nicht schnell.

1. Frage:

Jetzt habe ich erst einmal zu der Ausführzeit eine Frage.
Ich weiss jetzt nicht genau warum sich die Ausführzeit immer um 2-3 Sekunden pro Schild erhöht? Liegt es am Server (Power) oder liegt es evtl. auch am Dateinamen?
Der Dateiname hat damit gar nichts zu tun, aber eben die Leistung.

Ein Arbeiter mit Schaufel braucht für ein Loch eine Stunde.
Wie lange braucht er für 2 Löcher? ...

...
Wie lange würde dann "schilder-generator-schweiz.php" laufen wenn ich es direkt nach dem 5. Run starten würde? Würde die Ausführungzeit wie bei "schilder-generator-deutschland.php" immer proportional ansteigen oder würde der Server den anderen Generator als "neuen Task" oder so bearbeiten und wäre in 4-5 Sekunden fertig? Oder würde das andere Skript (schweiz) 18-19 Sekunden laufen?
Warum probierst du es nicht einfach?
Alle Scripts teilen sich den gleichen Computer.
Wenn Schweiz gleichzeitig mit 5 Deutschlands rennt ist Schweiz auch langsam.

2. Frage:

Die Idee:
Wenn der Generator gestartet wird, wird eine "1" in die DB geschrieben. Wenn das Skript fertig ist (ganz am Ende) wird die zuvor eingetragene "1" in "0" geändert. Solange eine "1" eingetragen ist, kann das selbe Skript nicht noch einmal ausgeführt werden.

Dieser Teil ist ja simpel zu programmieren aber wie mache ich das mit der Warteschleifen? Denn die Eingaben des User sollen ja nicht gelöscht werden und aus der "Run-Befehl" soll nicht gelöscht werden. Also Sachen wie "probieren sie es später" usw. sind nicht mein ding.

Hat hier jemand eine Idee wie ich das machen könnte?
Gar nicht.
PHP, Apache, der Browser etc. haben Timeouts.
Du kannst nicht beliebig lang warten, nach einigen Sekunden
sagt der Browser "schluss, will nicht mehr", Fehlermeldung.
 
Du meinst hoffentlich gleichzeitig?

Ja...

Weiss ja nicht, was du da machst, aber das ist nicht schnell.

Natürlich ist das nicht schnell. Wenn man aber berücksichtigt das im Hintergrund eine 8000x5000px große Grafik generiert wird (SVG -> PNG) und diese dann auch noch mit ImageMagick in die Richtige Ausgabegröße getrimmt wird, ist das nicht wirklich langsam.

Nebenbei wird auch ein etwas aufwändigeres Wasserzeichen generiert. Ein Text im Kreis mit ca. 100 Zeichen.

1. SVG erstellen
2. Wasserzeichen erstellen
3. SVG bearbeiten
4. SVG zu PNG konvertieren
5. PNG skallieren

Ohne den IMagick-Befehle zum konvertieren (SVG zu PNG) und zum Skalieren der PNG braucht das Skript lediglich nur noch 0,21007 Sekunden.

Bei dieser Zeit kann man nicht meckern und es zeigt auch, dass das Skript "sauber" programmiert ist.

Die längere Ausführungszeit liegt definitiv an der konvertierung von SVG nach PNG. Der Teil zum skallieren der Grafik wird schnell abgearbeitet.

Mit "exec" dauert es sogar noch länger. Mit Inkscape würde es sogar doppelt so lange wie mit "exec" dauern und "Batik" kann ich auf den Server nicht installieren, aber von "Batik" weiss ich das es auch länger braucht.

Es gibt also keine Alternative zu "Imagick".

Gar nicht.
PHP, Apache, der Browser etc. haben Timeouts.
Du kannst nicht beliebig lang warten, nach einigen Sekunden
sagt der Browser "schluss, will nicht mehr", Fehlermeldung.

Die Warteschleife soll ja nicht Minuten oder Stunden lang laufen. Vielleicht 60 oder 90 Sekunden als Maximum.

Wie machen das denn andere Dienste mit Serverlastigen Projekten? Es ist einfach ein aufwändiges Verfahren.

Edit:

Hallo noch einmal.

Ich habe mi folgendes überlegt.

Der User füllt das Formular aus und verschickt es. Es wird in der DB überprüft ob eine "1" eingetragen ist. Wenn ja, dann wird eine Schleife im Skript aktiviert, die solange in dieser Schleife bleibt, bis der Wert "0" ist. Wenn das ganze zu lange dauert, bekommt der User halt nach ca. 1 Minute einen Timeout.

Nur wie kann ich es regeln das der nächste User auch wirklich der nächste User ist?

Da muss es doch ne Lösung für geben?

Wie @Shell schon sagte sind 4-5 Sekunden nicht wenig und meine User benutzen den alten Generator (ganz einfach programmiert) manchmal 50 mal auf einmal. Das weiss ich weil ich unter anderem den Timestamp in der DB speichere.

Ich persöhnlich kenne jetzt auf Anhieb nur eine Webseite die auch Rechenintensive Skripte nutzt (auch Grafik verabeitung) und die setzen auch eine Warteschlage ein. Jedoch basiert die Seite komplett auf JS. Zumindest habe ich das so in deren Forum gelesen.

Edit:

Sorry für Doppelpost. Ich hätte schwören können, das ich auf Edit geklickt habe.
 
Der User füllt das Formular aus und verschickt es. Es wird in der DB überprüft ob eine "1" eingetragen ist. Wenn ja, dann wird eine Schleife im Skript aktiviert, die solange in dieser Schleife bleibt, bis der Wert "0" ist. Wenn das ganze zu lange dauert, bekommt der User halt nach ca. 1 Minute einen Timeout.
Wenn das Timeout also akzeptabel ist, ein Hinweis zum SQL:
Beim Warten und dann 1 setzen:

Nicht in der Schleife prüfen ob 1, ob 1...und dann
wenns 0 ist mit einer zweiten SQL-Anweisung auf 1 setzen.
Problem dabei: Zwei/mehrere merken, es ist gerade auf 0 gegangen.
Alle von denen beenden die Schleife.
Einer setzt sein 1 rein.
Der Nächste setzt auch 1 und denkt, er ist dran, weil er nicht gemerkt hat,
dass schon wieder 1 drin war.

Besser:
SQL:
update ... set x=1 where x=0
und dann affected_rows überprüfen (beides in der Schleife).
Wenn dieses 0 ergibt: Schleife weiter
1: Konvertierung beginnen.

Nur wie kann ich es regeln das der nächste User auch wirklich der nächste User ist?
Was bedeutet das?

Ich persöhnlich kenne jetzt auf Anhieb nur eine Webseite die auch Rechenintensive Skripte nutzt (auch Grafik verabeitung) und die setzen auch eine Warteschlage ein. Jedoch basiert die Seite komplett auf JS. Zumindest habe ich das so in deren Forum gelesen.
Wäre eine Möglichkeit.
PHP-Script erzeugt zeurst eine Bitte-warten-Seite
und speichert in der DB eine Liste von Bildern, die noch abgearbeitet werden müssen.
Die Bitte-warten-Seite fragt per Ajax alle 1-2 Sekunden ab, ob ihr Bild fertig ist,
und wechselt ggf. zur Ergebnisseite.

Sorry für Doppelpost. Ich hätte schwören können, das ich auf Edit geklickt habe
Das kann man doch auch nachträglich bearbeiten, ist hiermit geschehen.
 
Hallo. :)

Ich habe leider noch keine Idee wie ich das gut lösen kann.

Eine provisorische Idee wäre mittels JS z.B. 10 Sekunden nach Skript-Start einen Text einzublenden das der Vorganz sich verzögert.

Nur wie umsetzen?

Edit:

Ich weiss wie ich das mit JS lösen könnte. Jedoch soll die Funktion mit dem Submit-Button verbunden sein.
 
Zuletzt bearbeitet:
Wenn dein Edit eine Frage sein soll: Es gibt für alle möglichen Form-Elemente das Attribut "onclick", dem man eine JS-Funktion zuweisen kann.
 
Ich möchte mit der Funktion "timeout" nach 5 Sekunden ein DIV-Container einblenden.

Code:
function toogle (id) {
    var obj = document.getElementById(id);
    var defaultClassName = obj.className;
    return function () {
        obj.className = obj.className == "hidden" ? defaultClassName : defaultClassName + " hidden";
    }    
}
window.onload = function () {
    setTimeout(toogle("eine_id"), 1000);
    setTimeout(toogle("zwei_id"), 2000);
}

Die Zeit für den Timeout soll aber erst runtergezählt werden, wenn auf den Submit-Button geklickt wurde.

Kannst du mir dabei helfen?
 
Dann nimm die onload-Lambda raus und erstelle eine separate Funktion, die du im onclick-Attribut aufrufst. Z.B. so:

HTML:
<script type="text/javascript">
function toogle (id) {
    var obj = document.getElementById(id);
    var defaultClassName = obj.className;
    return function () {
        obj.className = obj.className == "hidden" ? defaultClassName : defaultClassName + " hidden";
    }    
}
timeout_handler() {
    setTimeout(toogle("eine_id"), 1000);
    setTimeout(toogle("zwei_id"), 2000);

    return true;
}
</script>

<form action....>
  ....
  <input type="submit" onclick="return timeout_handler();"/>
</form>

EDIT: Evtl verwendest du settimeout() nicht richtig. Hier ist ein Beispiel: http://de.selfhtml.org/javascript/objekte/window.htm#set_timeout

Das würde bedeuten, das man als ersten Parameter an settimeout() einen String übergeben muss. Ich bin mir nicht sicher, ob dass, wie du es machst, korrekt ist oder nicht - da ich kein JS-Experte bin :)
 
Zuletzt bearbeitet:
Hallo. :)

Mich würde es interessieren wie ImageMagick auf dem Server mit mehreren Aufgaben umgeht?

Ich kann ja in mehreren Tabs z.B. den Verkehrszeichen-Generator starten und es werden dann ja in wenigen Millisekunden mehrere SVG-Dateien erstellt. Nur wie geht ImageMagick beim konvertieren der SVG-Dateien zu PNG-Grafiken vor?

Werden die SVG-Dateien hintereinander konvertiert oder je nach Startzeit auch gleichzeitig?

Denn die Antwort auf diese Frage interessiert mich aus folgendem Grund sehr: Wenn die SVG-Grafiken je nach Startzeit NACHEINANDER abgearbeitet werden, befinden sich die anderen SVG-Dateien ja sowieso in einer Warteschlange oder sehe ich das falsch?
 
Zurück