2009-03-17 2 views
5

Jeder Text, den ich über Ruby-Symbole gelesen habe, spricht über die Effizienz von Symbolen über Strings. Aber das ist nicht die 70er Jahre. Mein Computer kann ein wenig zusätzliche Garbage Collection verarbeiten. Liege ich falsch? Ich habe den neuesten und besten Pentium Dual Core Prozessor und 4 GB RAM. Ich denke, das sollte genug sein, um ein paar Strings zu bewältigen.Sind moderne Computer nicht leistungsfähig genug, um Strings zu handhaben, ohne Symbole zu brauchen (in Ruby)

Antwort

17

Ihr Computer „ein wenig zusätzliche Garbage Collection“ zu handhaben kann gut sein können, aber was ist, wenn das „wenig“ findet in einer inneren Schleife, die läuft millionenfach? Was ist, wenn es auf einem eingebetteten System mit begrenztem Speicher ausgeführt wird?

Es gibt viele Orte, an denen Sie mit Strings Willy-Nilly, aber in einigen können Sie nicht wegkommen. Alles hängt vom Kontext ab.

+0

Ja, das stimmt - eine lange laufende Schleife könnte definitiv Ressourcen verschlingen. Ich habe nicht darüber nachgedacht, Strings innerhalb einer Schleife zu erstellen, aber ich denke, Sie könnten das tun. Danke für den Tipp. –

2

Es ist schön, dass Symbole garantiert einzigartig sind - das kann einige nette Effekte haben, die Sie von String nicht bekommen würden (wie ihre Adressen immer genau gleich sind, glaube ich).

Plus sie haben eine andere Bedeutung und Sie würden sie in verschiedenen Bereichen verwenden möchten, aber Ruby ist sowieso nicht so streng über diese Art von Sachen, so kann ich Ihre Frage verstehen.

13

Es ist wahr, Sie brauchen Tokens nicht so sehr aus Speichergründen. Ihr Computer könnte zweifellos alle Arten von gnarly Schnurhandling behandeln.

Aber, zusätzlich zu sein, haben Token den zusätzlichen Vorteil (vor allem mit Kontext Färbung) von schreien visuell: Schau mich an, ich bin ein Schlüssel zu einem Schlüssel-Wert-Paar. Das ist ein guter Grund, sie für mich zu benutzen.

Es gibt noch andere Gründe ... und der Leistungszuwachs bei vielen von ihnen könnte mehr sein, als Ihnen bewusst ist, vor allem, wenn Sie etwas Vergleichendes machen.

Beim Vergleichen zweier Ruby-Symbole vergleicht der Interpreter nur zwei Objektadressen. Beim Vergleich zweier Strings muss der Interpreter jedes Zeichen einzeln vergleichen. Diese Art von Berechnung kann sich addieren, wenn Sie viel tun.

Symbole haben ihre eigenen Leistungsprobleme obwohl ... sie werden nie Müll gesammelt.

Es lohnt sich diesen Artikel lesen: http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol

+0

Interessant. Ich habe nicht daran gedacht, dass Symbole nicht Müll sind. Cooler Artikel. Danke für den Link. Das ist wie "Alles, was du jemals über Symbole wissen wolltest" :) Friede, Alter. –

+0

Die Kontext Färbung Sache ist auch ein guter Punkt. –

1

Ein Zeichen weniger eingeben. Das ist die ganze Rechtfertigung, die ich brauche, um sie über Zeichenfolgen für Hash-Schlüssel usw. zu verwenden.

+2

+1; Als ich das zuerst las, sagte ich mir: "Wow, was für ein oberflächlicher Grund!". Aber je mehr ich darüber nachdachte, desto mehr wurde mir klar, wie groß diese Motivation für meinen eigenen Gebrauch von Symbolen war. Danke, dass du mir geholfen hast, etwas über mich selbst zu erkennen. –

1

Hier ist der wahre Grund für den Unterschied: Strings sind nie gleich. Jede Instanz einer Zeichenfolge ist ein separates Objekt, auch wenn der Inhalt identisch ist. Und die meisten Operationen an Strings machen neue String-Objekte. Beachten Sie Folgendes:

a = 'zowie' 
b = 'zowie' 
a == b   #=> true 

Auf der Oberfläche, würde es leicht sein, zu behaupten, dass a und b gleich sind. Die meisten gesunden Menschenverstand Operationen werden funktionieren, wie Sie es erwarten würden. Aber:

a.object_id #=> 2152589920 (when I ran this in irb) 
b.object_id #=> 2152572980 
a.equal?(b) #=> false 

Sie aussehen die gleiche, aber sie sind verschiedene Objekte. Ruby musste Speicher zweimal reservieren, die Methode String#initialize zweimal ausführen usw. Sie nehmen zwei getrennte Speicherplätze ein. Und hey!Es wird noch mehr Spaß, wenn Sie versuchen, sie zu ändern:

a += ''  #=> 'zowie' 
a.object_id #=> 2151845240 

Hier fügen wir nichts-a und lassen Sie den Inhalt genau das gleiche - aber Rubin weiß nicht, dass. Er weist immer noch ein ganz neues String-Objekt zu, weist ihm die Variable a zu, und das alte String-Objekt wartet darauf, dass eine Garbage Collection stattfindet. Oh, und die leere '' Zeichenfolge erhält auch ein temporäres String-Objekt, das nur für die Dauer dieser Codezeile zugewiesen wird. Probieren Sie es aus und sehen:

''.object_id #=> 2152710260 
''.object_id #=> 2152694840 
''.object_id #=> 2152681980 

Sind diese Objektzuordnungen schnell auf glatten Multi-Gigahertz-Prozessor? Sicher sind sie. Werden sie viel von Ihrem 4 GB RAM kauen? Nein, werden sie nicht. Aber mach es ein paar Millionen Mal und es beginnt sich zu summieren. Die meisten Anwendungen verwenden überall temporäre Zeichenfolgen, und Ihr Code ist wahrscheinlich voll von Zeichenfolgenliteralen in Ihren Methoden und Schleifen. Jedes dieser Zeichenfolgenliterale und dergleichen weist ein neues Zeichenfolgenobjekt jedes Mal zu, in dem diese Codezeile ausgeführt wird. Das eigentliche Problem ist nicht einmal die Speicherverschwendung; Es ist die Zeit, die verschwendet wird, wenn die Garbage Collection zu häufig ausgelöst wird und die Anwendung zu hängen beginnt.

Im Gegensatz dazu einen Blick auf Symbole:

a = :zowie 
b = :zowie 
a.object_id #=> 456488 
b.object_id #=> 456488 
a == b   #=> true 
a.equal?(b) #=> true 

Sobald das Symbol :zowie gemacht wird, wird es nie wieder eine machen. Jedes Mal, wenn Sie auf ein bestimmtes Symbol verweisen, beziehen Sie sich auf dasselbe Objekt. Es gibt keine Zeit oder Speicher für neue Zuweisungen verschwendet. Dies kann auch ein Nachteil sein, wenn Sie zu verrückt mit ihnen gehen - sie sind nie Müll gesammelt, also wenn Sie beginnen, unzählige Symbole dynamisch von Benutzereingabe erstellen, riskieren Sie ein endloses Speicherleck. Aber für einfache Literale in Ihrem Code, wie konstante Werte oder Hash-Keys, sind sie einfach perfekt.

Hilft das? Es geht nicht darum, was Ihre Anwendung einmal tut. Es geht darum, was es millionenfach macht.

Verwandte Themen