7
votes

Sont des multimethods de clojure lent par la nature


2 commentaires

Vous semblez utiliser MultiMethods comme une sorte de construction de correspondance de modèle ici. C'est vraiment pas le but de MultiMethod, qui est (multi) expédition. Pensez-y comme un superset de ce qui est possible dans les langues orientées objet. Pour utiliser des protocoles d'utilisation unique (comme OO Stuff). Pour la correspondance de patterns, utilisez ceci: Github.com/swannodette/match


En outre, le code Clojure.core est la façon dont il s'agit précisément pour la raison de la performance. La plupart des autres implémentations seront plus lentes.


3 Réponses :


4
votes

MultiMethods de Clojure Autoriser le comportement polymorphe d'exécution basé sur des fonctions d'expédition arbitraires. Ceci est très puissant pour construire des hiérarchies et des abstractions ad-hoc, mais vous payez une performance frappée pour une telle flexibilité. Vous voudrez peut-être ré-implémenter votre solution avec un protocole. Utilisez uniquement des multimods lorsque vous avez besoin de flexibilité complète de type d'exécution.


1 commentaires

J'avais considéré un protocole mais du Documentation Les fonctions résultantes Expédition sur le type de leur premier argument, Et donc doit avoir au moins un argument et ce qui est nécessaire est une expédition sur la valeur de l'argument.



3
votes

En général Tout ce qui prendra plus de temps . Étant donné que les multimethods offrent une variété de moyens de dépêcher, ils prendront plus de temps que des protocoles que je dois répondre à votre question "Oui, par rapport aux protocoles".

En pratique, commencez avec les protocoles et accédez à des multimethodes lorsque vous devez (et cela ressemble à vous en avez besoin). Vous ne pouvez pas rendre l'ordinateur plus rapidement avec le code, mais vous pouvez le faire faire moins


0 commentaires

0
votes

Je pense que la raison pour laquelle votre implémentation multi-méthodes est plus lente peut également être dû au fait que vous utilisez de la suite sur une séquence paresseuse (fournie par plage) au lieu de la boucle / recurez sur un index d'incrémentation utilisé dans Clojure.core. Essayez de copier la partie de la boucle de la mise en œuvre de Clojure.core / Re-groupes dans votre deuxième défméthod et voyez si cela n'augmente pas la performance.

Il est difficile de dire sans voir votre cas de test, mais s'il y a beaucoup de groupes dans le matcheur, vous pouvez dépenser beaucoup plus de temps pour réduire les groupes dans un vecteur que dans l'expédition multi-méthodes. S'il y a peu de groupes cependant, l'expédition multi-méthodes sera une partie plus importante du temps passé. Dans les deux cas, avoir la même mise en œuvre éliminera un facteur contribuant potentiel à la différence de chronométrage et vous aidera à mieux vous sentir pour la surcharge réelle dans l'expédition multi-méthodes.

Une autre chose que vous pourriez envisager est la possibilité que le ralentissement soit dû à la réflexion. Essayez de régler * warn-on-réflexion * à vrai et voir s'il se plaint. Peut-être qu'un autre indice de type stratégique peut aider.


1 commentaires

J'ai utilisé cela pour obtenir les timings: (heure (Count (Map Recours (Cycle [# »[- +]? [0-9] + / ([0-9]) +" # "([ - +]? [0-9] +) / ([0-9]) + "#" [- +]? [0-9] + / [0-9] + "#" Hamster "]) (prendre 200000 (pour [x (plage) y (plage x)] (STR x "/" y))))))))