From: Robert Klemme Date: 2011-07-26T16:28:54+09:00 Subject: Re: Why aren't string literals treated similarly to symbols? Jeremy Bopp wrote in post #1013041: > Explaining the difference between symbols and strings got me wondering > why string literals aren't treated similarly to symbols by the > interpreter. To be clear it seems that string literals could be > allocated 1 time each, where duplicates simply reference the first > created instance. Actually this is what happens with COW underneath. Still you get multiple instances which is correct and needed (see below). > The trick would be to make each reference to the literal a dup of the > singular, hidden instance. With the COW semantics that dup'd strings > have (or should have), this should be a more memory efficient way to > deal with programs that have many instances of a string literal. This is what happens. Note, it's not a dup of the reference but a dup of the instance (i.e. like CONSTANT_STRING.dup was called). > One such possibly common place that could benefit from this optimization > would be within frequently called methods or iterated loops that > directly use string literals for read-only purposes. If a developer > wants to avoid the allocation problem of string literals as things > currently stand, he/she would have to be aware of this problem first and > then find ways to push his/her literals into constants or other exterior > references. > > For example: > > 1.upto(2) do > string = "example" > puts string > end > > Unless I misunderstand the current implementation in MRI, a loop such as > the one above would needlessly create a new instance of "good" for every > pass through the loop. You probably meant "example" instead of "good". And you are wrong about "needless". To elaborate what Matz said: your suggestion will break with this code irb(main):004:0> a=[] => [] irb(main):005:0> 3.times {|i| a << ("foo" << i.to_s)} => 3 irb(main):006:0> a => ["foo0", "foo1", "foo2"] It will behave like this irb(main):007:0> a=[] => [] irb(main):008:0> s="foo" => "foo" irb(main):009:0> 3.times {|i| a << (s << i.to_s)} => 3 irb(main):010:0> a => ["foo012", "foo012", "foo012"] > One possible fix would be something like: > > string = "example" > 1.upto(2) do > puts string > end > > In this trivial case, the solution is good enough, but the general case > requires more knowledge about how to optimize for the interpreter than > should be necessary. I'm probably missing something obvious, so if > anyone knows what it is, please point it out. Maybe MRI already does > this obvious thing. It's doing COW already internally. http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_9_2/string.c?revision=31809&view=markup See e.g. lines 1984ff. Then functions rb_str_resize rb_str_modify str_independent str_make_independent Kind regards robert -- Posted via http://www.ruby-forum.com/.