Не являются ли современные компьютеры достаточно мощными для работы со строками без необходимости использования символов (в Ruby) - PullRequest
5 голосов
/ 18 марта 2009

Каждый текст, который я читал о символах Ruby, говорит об эффективности символов над строками. Но это не 1970-е годы. Мой компьютер может справиться с небольшим сбором мусора. Я ошибся? У меня новейший двухъядерный процессор Pentium и 4 гигабайта оперативной памяти. Я думаю, этого должно быть достаточно для обработки некоторых строк.

Ответы [ 5 ]

17 голосов
/ 18 марта 2009

Ваш компьютер вполне может справиться с «небольшим сбором мусора», но что делать, когда этот «маленький» происходит во внутреннем цикле, который выполняется миллионы раз? А как насчет того, когда он работает на встроенной системе с ограниченной памятью?

Есть много мест, в которых вы можете с легкостью использовать строки, но в некоторых вы не можете. Все зависит от контекста.

13 голосов
/ 18 марта 2009

Это правда, вам не нужны так сильно токены по причинам памяти. Ваш компьютер, несомненно, может обрабатывать все виды обработки грубых строк.

Но, помимо того, что токены быстрее, они имеют дополнительное преимущество (особенно при окраске контекста), заключающееся в визуальном крике: посмотри на меня, я ключ к ключевой паре. Это достаточно веская причина, чтобы использовать их для меня.

Есть и другие причины ... и прирост производительности на многих из них может быть больше, чем вы думаете, особенно при выполнении чего-то вроде сравнения.

При сравнении двух символов ruby ​​интерпретатор просто сравнивает два адреса объекта. При сравнении двух строк интерпретатор должен сравнивать каждый символ по одному. Подобные вычисления могут сложиться, если вы делаете много этого.

Символы имеют свои собственные проблемы с производительностью, хотя ... они никогда не собираются мусором.

Стоит прочитать эту статью: http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol

2 голосов
/ 24 марта 2011

Вот реальная причина разницы: строки никогда не бывают одинаковыми. Каждый экземпляр строки является отдельным объектом, даже если содержимое идентично. И большинство операций над строками создаст новые строковые объекты. Учтите следующее:

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

На первый взгляд было бы легко утверждать, что a и b одинаковы. Большинство операций здравого смысла будут работать так, как вы ожидаете. Но:

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

Они выглядят одинаковыми, но это разные объекты. Руби пришлось дважды выделить память, дважды выполнить метод String#initialize и т. Д. Они занимают два отдельных места в памяти. И эй! Когда вы пытаетесь их изменить, становится еще веселее:

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

Здесь мы добавляем Ничего к a и оставляем содержимое точно таким же - но Руби не знает этого. Он по-прежнему выделяет новый объект String, переназначает ему переменную a, и старый объект String бездействует в ожидании возможной сборки мусора. Да, и пустая строка '' также получает временный объект String, выделенный только на время этой строки кода. Попробуйте и посмотрите:

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

Быстрое ли распределение объектов на вашем гладком мульти-гигагерцовом процессоре? Конечно, они есть. Будут ли они жевать большую часть ваших 4 ГБ оперативной памяти? Нет, они не будут. Но сделайте это несколько миллионов раз, и это начнет складываться. Большинство приложений повсеместно используют временные строки, и ваш код, вероятно, полон строковых литералов внутри ваших методов и циклов. Каждый из этих строковых литералов и тому подобное будет выделять новый объект String, каждый раз, когда эта строка кода запускается. Настоящая проблема даже не в потере памяти; это время, потраченное впустую, когда сборка мусора запускается слишком часто, и ваше приложение начинает зависать.

Для сравнения взгляните на символы:

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

Как только символ :zowie будет создан, он никогда не станет другим. Каждый раз, когда вы ссылаетесь на данный символ, вы ссылаетесь на один и тот же объект. Там нет ни времени, ни памяти, потраченной на новые распределения. Это также может быть недостатком, если вы сходите с ума от них - они никогда не собирают мусор, поэтому, если вы начнете создавать бесчисленные символы динамически из пользовательского ввода, вы рискуете бесконечной утечкой памяти. Но для простых литералов в вашем коде, таких как постоянные значения или ключи хеша, они почти идеальны.

Это помогает? Дело не в том, что ваше приложение делает один раз. Это о том, что он делает миллионы раз.

2 голосов
/ 18 марта 2009

Приятно, что символы гарантированно уникальны - это может иметь некоторые приятные эффекты, которые вы не получите от String (например, их адреса всегда точно равны).

Кроме того, они имеют разное значение, и вы хотели бы использовать их в разных областях, но Рубин в любом случае не слишком строг к таким вещам, поэтому я могу понять ваш вопрос.

1 голос
/ 18 марта 2009

На один символ меньше. Вот и все оправдание, которое мне нужно, чтобы использовать их над строками для хеш-ключей и т. Д.

...