Overhead beim Aufruf einer Komponente Funktion vs Inline-Code - ColdFusion

9

Ich habe ein Leistungsproblem bei der Erstellung einer CSV-Datei mit etwa 50.000 Zeilen diagnostiziert und diese auf eine einzelne Funktion beschränkt, die einmal pro Zeile verwendet wird.

Nachdem ich viel herumgespielt habe, habe ich entdeckt, dass es einen Overhead bei der Verwendung der Funktion gibt, anstatt die Logik direkt in die Schleife zu bringen - meine Frage ist: Warum?!

Die fragliche Funktion ist sehr einfach, sie akzeptiert ein string-Argument und übergibt das an einen switch / case-Block, der ungefähr 15 Optionen enthält - die resultierende Zeichenfolge wird zurückgegeben. Ich habe eine Reihe von Timern überall platziert und festgestellt, dass eine Menge (nicht alle) der Zeit, die dieser Funktionsaufruf dauert zwischen 0 und 200 ms zu laufen ... aber wenn ich den exakt gleichen Code inline setze, sitzt es bei jeder Iteration auf 0 gesetzt.

All dies deutet auf ein grundlegendes Problem meines Verständnisses der Objekt-Instanziierung hin, und ich würde eine Klarstellung schätzen.

Ich hatte immer den Eindruck, dass wenn ich eine Komponente am Anfang einer Seite instanziiere, oder wenn ich sie in einem persistenten Bereich wie Application oder Session instanziiere, würde sie in den Speicher und nachfolgende Aufrufe von Funktionen innerhalb davon platziert werden Diese Komponente wäre blitzschnell. Es scheint jedoch, dass es einen Overhead zum Aufrufen dieser Funktionen gibt und während wir nur ein paar Millisekunden sprechen, wenn Sie das 50.000 Mal tun müssen, summiert sich das schnell.

Außerdem scheint es, dass dies Ressourcen verbraucht. Ich bin nicht besonders versiert darin, wie die JVM Speicher verwendet, ich habe es gelesen und mit Einstellungen und so gespielt, aber es ist ein überwältigendes Thema - besonders für diejenigen von uns ohne Java-Entwicklungserfahrung. Es scheint, dass beim Aufruf der Methode über Inline-Code der ColdFusion-Service manchmal zusammenbricht und die Anfrage nie endet. Zu anderen Zeiten ist es tatsächlich abgeschlossen, obwohl viel zu langsam. Dies deutet darauf hin, dass die Anfrage nur abgeschlossen werden kann, wenn der Server über die Ressourcen verfügt, um damit umzugehen - und dass der Methodenaufruf selbst Speicher verbraucht ... (?)

Wenn der Aufruf einer Methode tatsächlich einen Overhead hat, habe ich ein großes Problem. Es ist nicht wirklich machbar, all diesen Code inline zu verschieben (während die fragliche Funktion einfach ist, gibt es viele andere Funktionen, die ich benutzen muss), und dies läuft gegen alles, was ich als Entwickler glaube !!

Also, jede Hilfe wäre willkommen.

Nur aus Gründen der Klarheit und weil ich sicher bin, dass jemand danach fragen wird, hier ist der Code in Frage:

BEARBEITEN: Wie vorgeschlagen, habe ich den Code so geändert, dass er statt CFSwitch einen Struct-Lookup verwendet - unten wird der Code als Referenz geändert, es gibt aber auch eine Test-App in Pastebin-Links unten.

Innerhalb der init-Methode:

%Vor%

Funktion, die aufgerufen wird:

%Vor%

Wie gewünscht, habe ich eine Testanwendung erstellt, um dieses Problem zu replizieren:

Ссылка - Application.cfc

Ссылка - TestCom.cfc (Platzieren Sie den Ordner 'com' außerhalb von Webroot)

Ссылка - index.cfm

    
Gary Stanton 16.04.2014, 12:36
quelle

2 Antworten

2

Der Funktionsaufruf ist in jeder Sprache immer langsamer als der Inline-Code. Deshalb gibt es inline Schlüsselwort in C ++, und in JVM Land gibt es JIT Optimizer, der inline Funktionen für Sie, wenn es für notwendig hält.

Jetzt ist ColdFusion eine weitere Ebene über JVM. Daher ist eine Funktion in CF keine Funktion in JVM, daher werden Dinge nicht auf JIT-Optimizer-Basis 1: 1 übersetzt. Eine CFML-Funktion wird tatsächlich in eine Java-Klasse kompiliert. Außerdem werden Bereiche wie arguments , local (Java Hashtabellen) bei jedem Aufruf erstellt. Das braucht Zeit und Speicher und daher Overhead.

  

... wenn ich es in einem dauerhaften Bereich wie Application oder instanziiere   Session, dann würde es in den Speicher und nachfolgende Aufrufe an   Funktionen innerhalb dieser Komponente wären blitzschnell

Es wäre zwar schneller als eine neue Instanz zu instanziieren, aber es wird nicht "blitzschnell" sein, besonders wenn Sie es in einer engen Schleife aufrufen.

Zusammenfassend, inline die Funktion und wenn es immer noch nicht schnell genug ist, suchen Sie den langsamsten Teil des Codes und schreiben Sie es in Java.

    
Henry 16.04.2014, 18:12
quelle
0

Nur eine Randnotiz, da Railo innere Klassen anstelle von vollständigen unabhängigen Klassen verwendet, ist es schneller, wenn Sie so schreiben, dass Sie viele kleine Funktionen haben. In meinen Experimenten arbeiten beide Engines ähnlich mit Basic-Inline-Code. Adobe ColdFusion eignet sich für große God-Funktionen, wenn Sie die Leistung unter Last quietschen müssen. Da die JVM während der Kompilierung keine ColdFusion-Funktionen inte- grieren kann, werden Sie nie den Vorteil erhalten, dass der Compiler mit Ihrem Code intelligent ist.

Dies ist besonders wichtig, wenn Sie eine Anwendung erstellt haben, die eine Menge expliziter Getter / Setter verwendet und Sie feststellen, dass Ihr Datenverkehr von einem kleinen Volumen auf ein hohes Volumen ansteigt. All diese kleinen Funktionen werden Sie in die Knie zwingen gegen weniger große "Gott" -Funktionen.

Am langsamsten und schnellsten mit einem Basistest liefen 100.000 Iterationen:

Adobe ColdFusion (viele kleine Funktionen) (200X langsamer als Java) Railo (viele kleine Funktionen) (60X langsamer) ColdFusion / Railo (alle Code inline in einer riesigen Funktion) (10X langsamer) Native Java-Klasse (schnellste)

    
J.T. 20.08.2014 20:44
quelle