Quelqu'un connaît-il la réponse et / ou a-t-il une opinion à ce sujet?
Puisque les tuples ne seraient normalement pas très grands, je suppose qu'il serait plus logique d'utiliser des structures que des classes pour ces derniers. Ce que vous dites?
performance
class
struct
.net-4.0
Bent Rasmussen
la source
la source
ValueTuple<...>
. Voir la référence sur les types de tuple C #Réponses:
Microsoft a créé tous les types de références de types de tuple dans un souci de simplicité.
Je pense personnellement que c'était une erreur. Les tuples avec plus de 4 champs sont très inhabituels et devraient de toute façon être remplacés par une alternative plus typée (comme un type d'enregistrement en F #) donc seuls les petits tuples sont d'un intérêt pratique. Mes propres tests de performance ont montré que les tuples sans boîte jusqu'à 512 octets pouvaient toujours être plus rapides que les tuples en boîte.
Bien que l'efficacité de la mémoire soit une préoccupation, je pense que le problème dominant est la surcharge du garbage collector .NET. L'allocation et la collecte sont très coûteuses sur .NET car son garbage collector n'a pas été très fortement optimisé (par exemple par rapport à la JVM). De plus, le .NET GC (poste de travail) par défaut n'a pas encore été parallélisé. Par conséquent, les programmes parallèles qui utilisent des tuples s'arrêtent alors que tous les cœurs se disputent le garbage collector partagé, détruisant l'évolutivité. Ce n'est pas seulement la préoccupation dominante mais, AFAIK, a été complètement négligé par Microsoft quand ils ont examiné ce problème.
Une autre préoccupation est la répartition virtuelle. Les types de référence prennent en charge les sous-types et, par conséquent, leurs membres sont généralement appelés via une distribution virtuelle. En revanche, les types valeur ne peuvent pas prendre en charge les sous-types, de sorte que l'invocation de membre est sans ambiguïté et peut toujours être effectuée comme un appel de fonction direct. La distribution virtuelle est extrêmement coûteuse sur le matériel moderne car le processeur ne peut pas prédire où le compteur de programme se terminera. La JVM fait de grands efforts pour optimiser la répartition virtuelle, mais pas .NET. Cependant, .NET fournit une évasion de la distribution virtuelle sous la forme de types valeur. Donc, représenter les tuples comme des types valeur pourrait, encore une fois, avoir considérablement amélioré les performances ici. Par exemple, appeler
GetHashCode
sur un 2-tuple un million de fois prend 0,17 s, mais l'appeler sur une structure équivalente ne prend que 0,008 s, c'est-à-dire que le type valeur est 20 fois plus rapide que le type référence.Une situation réelle où ces problèmes de performances avec les tuples surviennent fréquemment est l'utilisation de tuples comme clés dans les dictionnaires. En fait, je suis tombé sur ce fil en suivant un lien de la question Stack Overflow F # exécute mon algorithme plus lentement que Python! où le programme F # de l'auteur s'est avéré être plus lent que son Python précisément parce qu'il utilisait des tuples encadrés. Le déballage manuel à l'aide d'un
struct
type écrit à la main rend son programme F # plusieurs fois plus rapide et plus rapide que Python. Ces problèmes ne se seraient jamais posés si les tuples étaient représentés par des types valeur et non par des types référence pour commencer ...la source
Tuple<_,...,_>
types auraient pu être scellés, auquel cas aucun envoi virtuel ne serait nécessaire bien qu'il s'agisse de types de référence. Je suis plus curieux de savoir pourquoi ils ne sont pas scellés que de savoir pourquoi ce sont des types de référence.La raison est très probablement parce que seuls les plus petits tuples auraient du sens en tant que types valeur car ils auraient une petite empreinte mémoire. Les plus gros tuples (c'est-à-dire ceux avec plus de propriétés) souffriraient en fait de la performance puisqu'ils seraient plus grands que 16 octets.
Plutôt que de faire en sorte que certains tuples soient des types valeur et que d'autres soient des types de référence et obligent les développeurs à savoir lesquels, j'imagine que les gens de Microsoft ont pensé que faire d'eux tous les types de référence était plus simple.
Ah, soupçons confirmés! S'il vous plaît voir Building Tuple :
la source
Si les types .NET System.Tuple <...> étaient définis comme des structures, ils ne seraient pas évolutifs. Par exemple, un tuple ternaire d'entiers longs est actuellement mis à l'échelle comme suit:
Si le tuple ternaire était défini en tant que struct, le résultat serait le suivant (basé sur un exemple de test que j'ai implémenté):
Comme les tuples ont un support de syntaxe intégré en F #, et qu'ils sont utilisés très souvent dans ce langage, les tuples "struct" exposeraient les programmeurs F # au risque d'écrire des programmes inefficaces sans même en être conscients. Cela arriverait si facilement:
À mon avis, les tuples «struct» entraîneraient une forte probabilité de créer des inefficacités significatives dans la programmation quotidienne. D'autre part, les tuples de "classe" actuellement existants provoquent également certaines inefficacités, comme mentionné par @Jon. Cependant, je pense que le produit de la "probabilité d'occurrence" par le "dommage potentiel" serait beaucoup plus élevé avec les structures qu'il ne l'est actuellement avec les classes. Par conséquent, la mise en œuvre actuelle est le moindre mal.
Idéalement, il y aurait à la fois des tuples "class" et des tuples "struct", tous deux avec support syntaxique en F #!
Modifier (2017-10-07)
Les tuples de structure sont désormais entièrement pris en charge comme suit:
la source
ref
, ou peut ne pas aimer le fait que les soi-disant «structures immuables» ne le sont pas, surtout lorsqu'elles sont encadrées. C'est dommage que .net n'ait jamais implémenté le concept de passage de paramètres par un exécutableconst ref
, car dans de nombreux cas, une telle sémantique est vraiment nécessaire.Dictionary
, par exemple ici: stackoverflow.com/questions/5850243 /…Pour 2-tuples, vous pouvez toujours utiliser le KeyValuePair <TKey, TValue> des versions antérieures du Common Type System. C'est un type de valeur.
Une clarification mineure à l'article de Matt Ellis serait que la différence de sémantique d'utilisation entre les types référence et valeur n'est "légère" que lorsque l'immuabilité est en vigueur (ce qui, bien sûr, serait le cas ici). Néanmoins, je pense qu'il aurait été préférable dans la conception BCL de ne pas introduire la confusion du passage de Tuple à un type de référence à un certain seuil.
la source
Je ne sais pas mais si vous avez déjà utilisé F # Les tuples font partie du langage. Si j'ai créé un .dll et renvoyé un type de tuples, ce serait bien d'avoir un type pour le mettre. Je soupçonne maintenant que F # fait partie du langage (.Net 4), des modifications ont été apportées à CLR pour accueillir certaines structures communes en fa #
Depuis http://en.wikibooks.org/wiki/F_Sharp_Programming/Tuples_and_Records
la source