ruby - 什么时候在 Ruby 中使用符号而不是字符串?

标签 ruby symbols

如果我的脚本中至少有两个相同字符串的实例,我是否应该改用符号?

最佳答案

长话短说

一个简单的经验法则是每次需要内部标识符时都使用符号。对于 Ruby < 2.2,只有在符号不是动态生成时才使用符号,以避免内存泄漏。

完整答案

不将它们用于动态生成的标识符的唯一原因是内存问题。

这个问题很常见,因为许多编程语言没有符号,只有字符串,因此字符串也被用作代码中的标识符。您应该担心的是什么符号意味着,而不仅仅是您应该在什么时候使用符号。符号是标识符。如果您遵循这一理念,您很可能会把事情做对。

符号和字符串的实现之间存在一些差异。关于符号最重要的一点是它们不可变。这意味着它们的值永远不会改变。因此,符号的实例化速度比字符串快,并且比较两个符号等一些操作也更快。

符号是不可变的这一事实允许 Ruby 在您每次引用符号时使用相同的对象,从而节省内存。因此,每次解释器读取 :my_key 时,它都可以从内存中取出它,而不是再次实例化它。这比每次都初始化一个新字符串要便宜。

您可以使用命令 Symbol.all_symbols 获取已实例化的所有符号的列表:

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.

对于 2.2 之前的 Ruby 版本,一旦一个符号被实例化,这个内存将再也不会空闲。释放内存的唯一方法是重新启动应用程序。所以符号在使用不当的情况下也是造成内存泄漏的一个主要原因。产生内存泄漏的最简单方法是对用户输入数据使用方法to_sym,因为该数据总是会改变,新的内存部分将永远在软件实例中使用。 Ruby 2.2 引入了 symbol garbage collector ,它释放动态生成的符号,因此动态创建符号产生的内存泄漏不再是问题。

回答你的问题:

Is it true I have to use a symbol instead of a string if there is at least two the same strings in my application or script?

如果您要寻找的是在您的代码内部使用的标识符,您应该使用符号。如果你正在打印输出,你应该使用字符串,即使它出现不止一次,甚至在内存中分配两个不同的对象。

这是推理:

  1. 打印符号比打印字符串慢,因为它们被强制转换为字符串。
  2. 拥有大量不同的符号会增加应用程序的整体内存使用量,因为它们永远不会被释放。而且您永远不会同时使用代码中的所有字符串。

@AlanDert 的用例

@AlanDert: if I use many times something like %input{type: :checkbox} in haml code, what should I use as checkbox?

Me: Yes.

@AlanDert: But to print out a symbol on html page, it should be converted to string, shouldn't it? what's the point of using it then?

输入的类型是什么?您要使用的输入类型的标识符或要向用户显示的内容?

的确,它在某些时候会变成 HTML 代码,但在您编写那行代码的那一刻,它意味着成为一个标识符 - 它标识您需要哪种输入字段。因此,它在您的代码中被反复使用,并且始终具有与标识符相同的“字符串”字符,并且不会产生内存泄漏。

也就是说,我们为什么不评估数据以查看字符串是否更快?

这是我为此创建的一个简单基准:

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

三个输出:

# first time
String: 5.14
Symbol: 5.07
#second
String: 5.29
Symbol: 5.050000000000001
#third
String: 4.7700000000000005
Symbol: 4.68

所以使用 smbols 实际上比使用字符串快一点。这是为什么?这取决于 HAML 的实现方式。我需要对 HAML 代码进行一些修改才能看到,但如果您继续在标识符的概念中使用符号,您的应用程序将更快、更可靠。当出现问题时,对其进行基准测试并获得答案。

关于ruby - 什么时候在 Ruby 中使用符号而不是字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16621073/

相关文章:

ruby - 如何运行显示一些信息的 ruby​​ shell 脚本,然后要求输入并进入后台?

ruby - 为什么符号不是卡住的字符串?

r - 获取左箭头和右箭头作为 R 中的绘图符号

mysql - At-在列名之前登录 SQL 语句

ruby - 如何在 sass 上启用调试,以便我可以使用 firesass?

ruby - 在 Sinatra 应用程序中维护单一、持久的 EM 连接

ruby - 如何检测以 Ruby open3 结尾的进程

ruby-on-rails - decent_exposure 每次创建双条目

import - ELF 格式导入符号的源共享库名称

具有 C++ 作用域的 Emacs 点符号