在Ruby中何时使用符号而不是字符串?
如果脚本中至少有两个相同字符串的实例,我是否应该使用符号?TL;博士 一个简单的经验法则是每次需要内部标识符时都使用符号。对于Ruby<2.2,只有在不动态生成符号时才使用符号,以避免内存泄漏 完整答案 不将它们用于动态生成的标识符的唯一原因是内存问题 这个问题很常见,因为许多编程语言没有符号,只有字符串,因此字符串在代码中也用作标识符。你应该担心符号的含义,而不仅仅是你应该使用符号的时候。符号是指标识符。如果你遵循这一理念,你很可能会把事情做好 符号和字符串的实现有几个不同之处。关于符号,最重要的是它们是不可变的。这意味着它们的价值永远不会改变。因此,符号的实例化速度比字符串快,而比较两个符号等操作也更快 符号是不可变的这一事实允许Ruby在每次引用符号时使用相同的对象,从而节省内存。因此,每次解释器读取在Ruby中何时使用符号而不是字符串?,ruby,symbols,Ruby,Symbols,如果脚本中至少有两个相同字符串的实例,我是否应该使用符号?TL;博士 一个简单的经验法则是每次需要内部标识符时都使用符号。对于Ruby
:my_key
时,它都可以从内存中获取它,而不是再次实例化它。这比每次初始化一个新字符串要便宜
您可以获得一个列表,列出已使用命令Symbol实例化的所有符号。所有符号:
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引入了,它释放了动态生成的符号,因此通过动态创建符号生成的内存泄漏不再是一个问题
回答你的问题:
如果我的应用程序或脚本中至少有两个相同的字符串,那么我必须使用符号而不是字符串,这是真的吗
如果您要寻找的是代码内部使用的标识符,那么应该使用符号。如果您正在打印输出,您应该使用字符串,即使它多次出现,甚至在内存中分配两个不同的对象
原因如下:
打印符号将比打印字符串慢,因为它们被强制转换为字符串李>
拥有大量不同的符号将增加应用程序的总体内存使用量,因为它们永远不会被释放。而且您永远不会同时使用代码中的所有字符串
@AlanDert的用例
@AlanDert:如果我在haml代码中多次使用%input{type::checkbox}之类的东西,我应该使用什么作为复选框
我:是的
@AlanDert:但要在html页面上打印符号,它应该转换为字符串,不是吗?那么使用它有什么意义呢
输入的类型是什么?要使用的输入类型的标识符或要向用户显示的内容
诚然,它在某个时候会变成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代码进行一些修改才能看到,但是如果您在标识符的概念中继续使用符号,您的应用程序将更快、更可靠。当问题出现时,对其进行基准测试并获得答案。简单地说,符号是一个名称,由字符组成,但不可变。相反,字符串是字符的有序容器,其内容允许更改。这是我在codecademy找到的一个不错的字符串与符号基准:
require 'benchmark'
string_AZ = Hash[("a".."z").to_a.zip((1..26).to_a)]
symbol_AZ = Hash[(:a..:z).to_a.zip((1..26).to_a)]
string_time = Benchmark.realtime do
1000_000.times { string_AZ["r"] }
end
symbol_time = Benchmark.realtime do
1000_000.times { symbol_AZ[:r] }
end
puts "String time: #{string_time} seconds."
puts "Symbol time: #{symbol_time} seconds."
输出为:
String time: 0.21983 seconds.
Symbol time: 0.087873 seconds.
- 使用符号作为散列键标识符
{key:“value”}
- 符号允许您以不同的顺序调用该方法
def写入(文件:,数据:,模式:“ascii”)
#为简洁起见,请删除
结束
写入(数据:123,文件:“test.txt”)
- 冻结以保留为字符串并保存内存
label='My label'。冻结
+1。符号和字符串是完全不同的东西。对于使用哪一个符号,真的没有任何混淆,除非他们被教得不好(即“符号只是一个不变的字符串”谬论)。你有一个观点,但是不要回答提出的问题。OP把字符串和符号混淆了,仅仅告诉它是不同的东西是不够的——你应该帮助他理解它们的相似之处以及它们是什么different@J似乎网络上到处都在发生的事情,除非你查阅文档,或者幸运地发现有人关心解释事情的真实情况。让我们不要忘记这是十分之一秒的事实。这都是相对的。有时百分之一百很重要。一百万次迭代中的百分之一秒?如果这是您可用的最佳优化,那么我认为您的程序已经进行了很好的优化。@andrewcockerham您提供的链接不起作用(错误-404)。你必须去掉最后一个
def write(file:, data:, mode: "ascii")
# removed for brevity
end
write(data: 123, file: "test.txt")