9
votes

Compilation séparée pour les génériques de rouille

C ++ a été critiqué car il manque de compilation de modèles séparés. Les modèles C ++ sont compilés pour (virtuellement) chaque instanciation. Quel est l'état des choses pour la rouille concernant la compilation séparée des génériques? Je crois comprendre que cela se comporte comme C ++, sauf que les instanciations sont mises en cache lors de la compilation de chaque caisse. Est-ce correct?


2 commentaires

Je suis un peu floue sur l'endroit où les modèles s'intègrent en C ++, mais dans la rouille où les macros sont préoccupées, vous pouvez obtenir la forme expansée avec - assez développé . Mais pas des génériques.


En réalité, le problème réel en C ++ n'est pas que les modèles sont compilés pour chaque instanciation: les compilateurs intelligents effectuent une mémoire de mémoisation et disposent d'un cache d'un certain nombre d'instanciations "pré-compilées" d'un modèle pour quelques types de types / valeurs donnés. Le problème principal est compilation séparé combiné avec #include , le modèle doit être dans les en-têtes, il est donc inutilement analysé dans chaque unité de traduction, que cela l'utilise ou non. Ce problème disparaîtra avec des modules (C ++ 17 peut-être?).


3 Réponses :


2
votes

du Tutoriel Docs:

Le compilateur de rouille compile des fonctions génériques de manière très efficace en les monomorphisant. La monomorphisie est un nom de fantaisie pour une idée simple: générer une copie séparée de chaque fonction générique sur chaque site d'appel, une copie spécialisée dans les types d'arguments et peut ainsi être optimisée spécifiquement pour eux. À cet égard, les génériques de Rust ont des caractéristiques de performance similaires aux modèles C ++. http://doc.rust-lang.org/0.11.0/TUCTAL .html # génériques

edit: Cela n'a pas vraiment répondu à votre question, n'est-ce pas?


2 commentaires

Ce texte est exactement pourquoi j'ai conjecté que c'est la même chose qu'en C ++. Je voudrais entendre quelque chose de plus explicite, cependant.


Les "caractéristiques de performance similaires" désignent ici les performances d'exécution, ce qui signifie que la compilation est effectuée séparément pour chaque copie et donc aucune surcharge d'exécution. Cette phrase ne fait pas référence exactement à l'heure de la compilation.



1
votes

Les types génériques et les fonctions sont monomorphisés. Cependant, il est possible d'utiliser des traits sans génériques.

Ceci est une fonction générique. Il sera monomorphe. xxx

Il s'agit d'une fonction non générique équivalente. Une seule copie de cette fonction sera incluse dans le binaire. xxx

Notez que nous ne pouvions pas faire une fonction qui reçoit une collection par valeur , parce que collection est un trait, et il n'a donc pas de taille spécifique. Une fonction générique est requise dans ce cas.

Il y a des choses que vous ne pouvez pas faire avec des génériques et certaines choses que vous ne pouvez pas faire avec des références de trait. Avec des références de trait, vous avez besoin d'un trait, évidemment. Avec des génériques, vous ne pouvez pas avoir de vecteur de collections où les collections sont de types différents (par exemple, vous ne pouviez pas imposer de VEC et une chaîne dans ce Vecteur), mais vous pouvez avec des références de trait: Un VEC <& Collection> peut contenir un & VEC et un et de la chaîne


0 commentaires

7
votes

Autant que je sache, les génériques sont stockés sous une forme sérialisée dans la caisse où ils sont définis. Lorsqu'il est utilisé dans une autre caisse (bibliothèque ou binaire), ils sont instanciés de cette forme sérialisée. Ils sont donc monomorphisés de la même manière que les modèles C ++, mais les frais généraux de l'analyse répétée du code inutile sont évités.


0 commentaires