69 votes

Pourquoi n'est-ce pas une bonne idée de créer dynamiquement beaucoup de symboles dans ruby (pour les versions avant 2.2) ?

Quelle est la fonction d'un symbole en ruby ? Quelle est la différence entre une chaîne et un symbole ? Pourquoi n'est-ce pas une bonne idée de créer dynamiquement beaucoup de symboles ?

39 votes

Est-ce que vous travailliez à travers le EdgeCase Ruby koans aussi ?

1 votes

Quelqu'un pourrait-il mettre à jour cette question pour préciser Ruby 2.1 o Versions de Ruby antérieures à 2.2

0 votes

@dewet : pourriez-vous également mentionner pourquoi ?

96voto

david4dev Points 2578

Les symboles sont comme les chaînes de caractères mais ils sont immuables - ils ne peuvent pas être modifiés.

Ils ne sont mis en mémoire qu'une seule fois, ce qui les rend très efficaces pour des choses comme les clés dans les hachages, mais ils restent en mémoire jusqu'à la sortie du programme. Cela les rend gourmands en mémoire si vous les utilisez mal.

Si vous créez dynamiquement de nombreux symboles, vous allouez beaucoup de mémoire qui ne pourra être libérée qu'à la fin de votre programme. Vous ne devriez créer des symboles de façon dynamique (en utilisant string.to_sym ) si vous savez que vous le ferez :

  1. besoin d'accéder de manière répétée au symbole
  2. pas besoin de les modifier

Comme je l'ai dit précédemment, ils sont utiles pour des choses comme les hachages - où l'on se soucie davantage de l'indice de confiance. identité de la variable que sa valeur. Les symboles, lorsqu'ils sont correctement utilisés, constituent un moyen lisible et efficace de transmettre une identité.

Je vais expliquer ce que je veux dire sur l'immuabilité des symboles RE votre commentaire.

Les chaînes de caractères sont comme des tableaux ; elles peuvent être modifiées sur place :

12:17:44 ~$ irb
irb(main):001:0> string = "Hello World!"
=> "Hello World!"
irb(main):002:0> string[5] = 'z'
=> "z"
irb(main):003:0> string
=> "HellozWorld!"
irb(main):004:0> 

Les symboles ressemblent davantage à des chiffres ; ils ne peuvent pas être modifiés sur place :

irb(main):011:0> symbol = :Hello_World
=> :Hello_World
irb(main):012:0> symbol[5] = 'z'
NoMethodError: undefined method `[]=' for :Hello_World:Symbol
    from (irb):12
    from :0

0 votes

Si un symbole n'est pas créé dynamiquement, alors il ne peut pas être modifié ? pouvez-vous me donner un exemple ?

1 votes

Quelqu'un pourrait-il mettre à jour cette question pour préciser Ruby 2.1 o Versions de Ruby antérieures à 2.2

10voto

stef Points 6478

Un symbole est le même objet et la même allocation de mémoire, quel que soit l'endroit où il est utilisé :

>> :hello.object_id
=> 331068
>> a = :hello
=> :hello
>> a.object_id
=> 331068
>> b = :hello
=> :hello
>> b.object_id
=> 331068
>> a = "hello"
=> "hello"
>> a.object_id
=> 2149256980
>> b = "hello"
=> "hello"
>> b.object_id
=> 2149235120
>> b = "hell" + "o"

Deux chaînes qui sont "identiques" en ce sens qu'elles contiennent les mêmes caractères peuvent ne pas référencer la même mémoire, ce qui peut être inefficace si vous utilisez des chaînes pour, par exemple, des hachages.

Les symboles peuvent donc être utiles pour réduire la charge de la mémoire. Toutefois, ils constituent une fuite de mémoire potentielle, car les symboles ne peuvent pas être récupérés une fois créés. La création de milliers et de milliers de symboles allouerait la mémoire et ne serait pas récupérable. Oups !

1 votes

Pour autant que je sache, vous ne pouvez pas faire de garbage collection des symboles. Vous pouvez lancer le garbage collection à tout moment avec GC.start . Voici un bon article sur le sujet : viewsourcecode.org/why/hacking/theFullyUpturnedBin.html

6voto

Robert Kajic Points 2416

Il peut être particulièrement mauvais de créer des symboles à partir de l'entrée de l'utilisateur sans valider l'entrée par rapport à une sorte de liste blanche (par exemple, pour les paramètres de chaîne de requête dans RoR). Si l'entrée utilisateur est convertie en symboles sans validation, un utilisateur malveillant peut faire en sorte que votre programme consomme de grandes quantités de mémoire qui ne seront jamais collectées.

Mauvais (un symbole est créé indépendamment de l'entrée de l'utilisateur) :

name = params[:name].to_sym

Bon (un symbole n'est créé que si l'entrée de l'utilisateur est autorisée) :

whitelist = ['allowed_value', 'another_allowed_value']
raise ArgumentError unless whitelist.include?(params[:name])
name = params[:name].to_sym

6voto

sidj Points 119

Démarrer Ruby 2.2 et plus Symboles sont automatiquement ramassés et cela ne devrait donc pas poser de problème.

2voto

David Grayson Points 22459

Si vous utilisez Ruby 2.2.0 ou une version ultérieure, il n'y a généralement pas de problème à créer dynamiquement un grand nombre de symboles, car ils seront ramassés en fonction de la méthode de récupération des déchets. Annonce de Ruby 2.2.0-preview1 qui contient un lien vers plus de détails sur le nouveau symbole GC . Cependant, si vous passez vos symboles dynamiques à un code qui les convertit en ID (un concept interne de l'implémentation de Ruby utilisé dans le code source C), ils seront alors épinglés et ne seront jamais collectés. Je ne sais pas si cela se produit fréquemment.

Vous pouvez considérer les symboles comme le nom de quelque chose, et les chaînes de caractères (en gros) comme une séquence de caractères. Dans de nombreux cas, vous pouvez utiliser soit un symbole, soit une chaîne, soit un mélange des deux. Les symboles sont immuables, ce qui signifie qu'ils ne peuvent pas être modifiés après leur création. De la manière dont les symboles sont implémentés, il est très efficace de comparer deux symboles pour voir s'ils sont égaux, de sorte que leur utilisation comme clés de hachage devrait être un peu plus rapide que celle des chaînes de caractères. Les symboles ne possèdent pas beaucoup de méthodes comme les chaînes de caractères, telles que start_with? vous devrez donc utiliser to_s pour convertir le symbole en chaîne de caractères avant d'appeler ces méthodes.

Vous pouvez en savoir plus sur les symboles dans la documentation :

http://www.ruby-doc.org/core-2.1.3/Symbol.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X