J'ai lu quelques articles sur le moment d'utiliser des symboles et le moment d'utiliser des chaînes. Mais pour que ce soit plus clair et plus simple, je voudrais demander: est-il vrai qu'il vaut mieux utiliser un symbole plutôt qu'une chaîne s'il y a au moins deux chaînes identiques dans mon application ou mon script?
Réponses
Trop de publicités?TL;DR
Une règle simple est d'utiliser des symboles à chaque fois que vous avez besoin interne identifiants. Pour ruby < 2.2 l'utilisation des symboles lorsqu'ils ne sont pas générés de manière dynamique, pour éviter les fuites de mémoire.
Solution complète
La seule raison de ne pas les utiliser pour des identifiants qui sont générées dynamiquement est à cause de soucis de mémoire, comme nous le verrons ci-dessous.
Ce doute est très fréquent, en raison de nombreux langages de programmation n'ont pas de symboles, seules des chaînes de caractères, et donc les cordes sont également utilisés comme identifiants dans votre logiciel. Vous devriez vous soucier de ce que les symboles sont destinés à être, non seulement lorsque vous devez utiliser des symboles. Les symboles sont destinés à être des identifiants. Si vous suivez cette philosophie, les chances sont que vous allez faire les choses.
Il existe plusieurs différences entre la mise en œuvre de symboles et de cordes. La chose la plus importante sur les symboles, c'est qu'ils sont immuables. Cela signifie qu'ils n'auront jamais leur valeur a changé. De ce fait, les symboles sont instanciés plus vite que les chaînes et de certaines activités comme la comparaison de deux symboles est également plus rapide.
Le fait qu'un symbole est immuable permet ruby utiliser le même objet chaque fois que vous faites référence au symbole, d'économiser la mémoire. Donc, à chaque seconde fois l'interpréteur lit :my_key
il peut prendre à partir de la mémoire au lieu d'instancier à nouveau. C'est moins large que l'initialisation d'une nouvelle chaîne de tous les temps.
Vous pouvez obtenir une liste de tous les symboles qui sont déjà instancié avec la commande. Permet de voir ce sur cisr:
symbols_count = Symbol.all_symbols.count # all_symbols is an array with all
# instantiated symbols.
a = :one
puts a.object_id
# prints 167778
a = :two
puts a.object_id
# prints 167858
a = :one
puts a.object_id
# prints 167778 again - the same object_id from the first time!
puts Symbol.all_symbols.count - symbols_count
# prints 2, the two objects we created.
Pour ruby versions avant la version 2.2, la fois un symbole est instancié, ce souvenir restera à jamais être à nouveau libre. La seule façon de libérer la mémoire est de redémarrer l'application. Si les symboles sont une des principales causes de fuites de mémoire lorsque utilisé à tort. La façon la plus simple de générer une fuite de mémoire est à l'aide de la méthode de to_sym
sur la saisie de l'utilisateur des données depuis ces données sera toujours en changement, une nouvelle portion de la mémoire sera utilisée pour toujours dans le logiciel de l'instance. Ruby 2.2 introduit le symbole du garbage collector, ce qui libère les symboles générés de manière dynamique, de sorte que les fuites de mémoire générée par la création de symboles de manière dynamique, il n'est pas un problème plus.
Pour répondre à votre question:
Est-il vrai que je dois utiliser un symbole plutôt qu'une chaîne s'il y a au moins deux les mêmes chaînes dans mon application ou un script?
Si ce que vous cherchez est un identifiant à être utilisés en interne à votre code, vous devriez être en utilisant des symboles. Si vous avez l'impression de sortie, vous devriez aller avec les cordes, même si elle apparaît plus d'une fois, même l'allocation de deux objets différents dans la mémoire. Raisonnement:
- L'impression des symboles sera beaucoup plus lente que l'impression des chaînes car elles sont projetées à cordes.
- Avoir beaucoup de symboles différents augmenter l'ensemble l'utilisation de la mémoire de votre application, car ils ne sont jamais libéré. Et vous n'êtes jamais à l'aide de toutes les chaînes de votre logiciel en même temps.
Cas d'utilisation par @AlanDert
@AlanDert: si j'utilise plusieurs fois quelque chose comme %input{type: :case} en haml code, que dois-je utiliser comme case? Moi: Oui. @AlanDert: Mais pour imprimer un symbole sur la page html, il doit être converti en chaîne de caractères, n'est-ce pas? quel est le point de l'utiliser alors?
Quel est le type de l'entrée? Un identifiant du type d'entrée que vous souhaitez utiliser, ou quelque chose que vous voulez montrer à l'utilisateur?
Il est vrai qu'il deviendra code HTML à un certain point, mais pour le moment, vous écrivez que la ligne de votre code, c'est à dire être un identificateur - il identifie le type de champ de saisie dont vous avez besoin. Ainsi, il est utilisé maintes et maintes fois dans votre code, et ont toujours la même "chaîne" des caractères de l'identifiant et de ne pas générer une fuite de mémoire.
Cela dit, pourquoi ne pas évaluer les données pour voir si les chaînes sont les plus rapides? après un simple test que j'ai créé pour cela:
require 'benchmark'
require 'haml'
str = Benchmark.measure do
10_000.times do
Haml::Engine.new('%input{type: "checkbox"}').render
end
end.total
sym = Benchmark.measure do
10_000.times do
Haml::Engine.new('%input{type: :checkbox}').render
end
end.total
puts "String: " + str.to_s
puts "Symbol: " + sym.to_s
Trois sorties:
# first time
String: 5.14
Symbol: 5.07
#second
String: 5.29
Symbol: 5.050000000000001
#third
String: 4.7700000000000005
Symbol: 4.68
Donc, en utilisant smbols est en fait un peu plus vite, puis à l'aide de cordes. Pourquoi est-ce? Cela dépend de la manière HAML est mis en œuvre. Il faudrait que je bidouille un peu sur HAML code pour voir. Mais si vous gardez à l'aide de symboles que le concept de l'identifiant, votre application sera plus rapide et fiable. Quand le doute grèves, de référence et d'obtenir des conclusions.