Verbessern Sie die Leistung eines ClojureScript-Programms

8

Ich habe ein ClojureScript-Programm, das hauptsächlich mathematische Berechnungen für Sammlungen durchführt. Es wurde in idiomatischen, Host-unabhängigen Clojure entwickelt, so dass es leicht ist, es zu benchmarken. Zu meiner Überraschung (und im Gegensatz zu dem, was die Antworten zu vorschlagen würden, was schneller ist , Clojure oder ClojureScript (und warum)? ), der gleiche Code in ClojureScript läuft 5-10 mal langsamer als sein Clojure-Äquivalent.

Hier ist was ich getan habe. Ich habe ein lein repl und einen Browser repl in Ссылка geöffnet. Dann habe ich diese Schnipsel in beiden REPLs ausprobiert.

%Vor%

Dann habe ich eine JavaScript-Konsole im Browser repl geöffnet und eine minimalistische Benchmark-Funktion geschrieben,

%Vor%

Zurück zum Browser REPL:

%Vor%

Dann versuche sowohl die native Javascript-Multiplikation als auch die Clojurescript-Variante in der JavaScript-Konsole.

%Vor%

Was ich gefunden habe

  • Native Javascript Mathe ist vergleichbar mit Mathe in Clojure
  • ClojureScript ist 5-10 mal langsamer als jeder von ihnen

Nun ist meine Frage, wie kann ich die Leistung meines ClojureScript-Programms verbessern?

Es gibt einige Ansätze, die ich bisher in Betracht gezogen habe

  • Verwenden Sie veränderbare Javascript-Arrays und Objekte hinter den Kulissen. (Ist das überhaupt möglich?)
  • Gehen Sie zurück zu nativen Javascript-Math-Operatoren. (Ist das überhaupt möglich?)
  • Verwenden Sie Javascript Arrays explizit mit (aget js/v 0)
  • Verwenden Sie eine weniger ehrgeizige Implementierung von clojure-for-javascript, wie Ссылка oder Ссылка Sie generieren ein mehr idiomatisches Javascript, aber sie unterstützen keine Namespaces, die ich oft verwende.
Adam Schmideg 14.05.2013, 16:19
quelle

2 Antworten

10

JavaScript hat explizite Rückgabe, also

%Vor%

tut nichts; Sie sollten einen Benchmark erstellen

%Vor%

stattdessen. Dies ist genau das, was die ClojureScript-Version kompiliert, so dass es keinen Unterschied gibt (in ClojureScript werden grundlegende arithmetische Funktionen bei der Verwendung nicht höherer Ordnung als reguläre operatorbasierte JavaScript-Ausdrücke eingezeichnet).

Jetzt ist Clojure definitiv schneller als ClojureScript. Ein Teil des Grundes ist, dass Clojure noch sorgfältiger abgestimmt ist als ClojureScript, obwohl sich ClojureScript in dieser Abteilung ziemlich schnell verbessert. Ein anderer Teil ist, dass Clojure ein reiferes JIT hat, um davon zu profitieren (die modernen JS-Engines, insbesondere V8, sind ziemlich gut, aber noch nicht ganz HotSpot-Klasse).

Die Größe des Unterschieds ist jedoch etwas schwierig zu messen; Die Tatsache, dass JITs involviert sind, bedeutet, dass eine Schleife mit einem Körper, der frei von irgendwelchen Nebenwirkungen ist, wie der in der Frage, wahrscheinlich weg optimiert wird, möglicherweise sogar beim ersten Durchlauf (durch den Einsatz eines On-Stack-Ersatzes) , benutzt von HotSpot und Ich denke auch V8 - ich müsste das allerdings überprüfen). Also besser, Benchmarks wie

%Vor%

( longs call, um Reflektionen in Clojure zu vermeiden; könnte auch ^longs thin verwenden).

Schließlich ist es in Clojure und ClojureScript sicher der Fall, dass es für bestimmte Arten von besonders leistungsempfindlichem Code am besten ist, native Arrays und dergleichen zu verwenden. Glücklicherweise gibt es dafür kein Problem: Auf der ClojureScript-Seite haben Sie array , js-obj , aget , aset , make-array , Sie können :mutable Metadaten für Felder in% co_de verwenden %, um deftype sie in Methodenkörpern usw. zu finden.

    
Michał Marczyk 14.05.2013, 19:59
quelle
7

ClojureScript math ist JavaScript-Mathematik. Ja, wenn die Leistung von entscheidender Bedeutung ist, verwenden Sie JavaScript-Arrays und die bereitgestellten Low-Level-Operatoren, diese garantieren, wo immer möglich, optimalen Code (d. H. Keine Verwendung höherer Ordnung). Die ClojureScript persistenten Datenstrukturen sind folgendermaßen geschrieben: Array-Mutation, Arithmetik, Bit-Twiddling.

Ich habe ein kleines Beispiel für effizientes ClojureScript - Ссылка die Sie als Leitfaden nützlich finden könnten.

    
dnolen 14.05.2013 20:35
quelle