https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112013-10-08T03:04:22ZRuby Issue Tracking SystemRuby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423162013-10-08T03:04:22Zko1 (Koichi Sasada)
<ul><li><strong>Category</strong> set to <i>core</i></li><li><strong>Assignee</strong> set to <i>matz (Yukihiro Matsumoto)</i></li></ul><blockquote>
<p>If we do not want to overload the existing .freeze method in this way, we could follow suggestions in <a href="http://bugs.ruby-lang.org/issues/8977" class="external">http://bugs.ruby-lang.org/issues/8977</a> to add a new "frozen" method (or some other name) that the compiler would understand.</p>
</blockquote>
<p>I like this idea. No compatibility issue.</p>
<p>(except naming issue)</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423172013-10-08T03:10:04Zcalebthompson (Caleb Thompson)caleb@calebthompson.io
<ul></ul><p>Optimizing the #freeze or #frozen methods to do this make a lot more sense to me<br>
than the <code>""f</code> suffix to me.</p>
<p>I'm +1 on #frozen and preventing redefinition of that method, but I further<br>
propose that we raise an error if redefining frozen rather than silently<br>
ignoring it, which would be very surprising.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423182013-10-08T03:18:37ZAnonymous
<ul></ul><p>+1 for optimized String#freeze as it will work on previous versions of Ruby:</p>
<p>I've written a patch implementing this feature: <a href="https://gist.github.com/charliesome/6836600" class="external">https://gist.github.com/charliesome/6836600</a></p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423192013-10-08T03:27:29Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>=begin<br>
I am leaning toward #frozen if we want a new name... as in "give me the frozen version of this string". I know that there was some concern that "frozen" was too similar to "freeze" in <a href="http://bugs.ruby-lang.org/issues/8977" class="external">http://bugs.ruby-lang.org/issues/8977</a> but it still feels like the best name.</p>
<p>If we can't do a new name that refers to freezing, I'd rather just stick with .freeze.</p>
<p>And I still kinda like ~@ :-)</p>
<p>class String<br>
alias ~@ freeze<br>
end</p>
<p>...although there's operator precedence problems (puts ~"str".frozen? does not work).<br>
=end</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423202013-10-08T05:33:49ZEregon (Benoit Daloze)
<ul></ul><p>I am happy to see another discussion on this, I feel "str"f is just a hack.</p>
<p>I strongly agree and think #freeze is the right name.</p>
<p>On the aesthetics side, I personally dislike prefix/suffix forms, they feel like u'str' in python which just makes me think it does not support the right strings by default. I kind of like %f{ ... } but #freeze fits even more in Ruby I think, even if a bit long but at least its semantics are clear.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423222013-10-08T07:59:09Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>"headius (Charles Nutter)" <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>I propose that we eliminate the new "f" suffix and just make the compiler<br>
smart enough to see literal strings with .frozen the same way.</p>
<p>So this code:</p>
<p>str = "mystring".freeze</p>
<p>Would be equivalent in the compiler to this code:</p>
<p>str = "mystring"f</p>
<p>And the fstring table would still be used to return pooled instances.</p>
</blockquote>
<p>This is a great idea IMHO. The backwards compatibility is a huge win<br>
and I think this is the best idea so far regarding frozen strings.</p>
<blockquote>
<p>IMPLEMENTATION NOTES:</p>
<p>The fstring table already exists on master and would be used for these<br>
pooled strings. An open question is whether the compiler should<br>
forever optimize "str".frozen to return the pooled version or whether<br>
it should check (inline-cache style) whether String#freeze has been<br>
replaced. I am ok with either, but the best potential comes from<br>
ignoring String#freeze redefinitions...or making it impossible to<br>
redefine String#freeze.</p>
</blockquote>
<p>Initially (a few minutes ago), I thought it'd be better to inline-cache<br>
to minimize surprise/keep compatibility. And maybe spew a loud warning on<br>
String#freeze redefinition.</p>
<p>But thinking about this more, string literals are already special.<br>
String#initialize is already ignored for string literals, so perhaps<br>
#freeze may be unredefinedable, as well.</p>
<blockquote>
<p>If we do not want to overload the existing .freeze method in this way,<br>
we could follow suggestions in <a href="http://bugs.ruby-lang.org/issues/8977" class="external">http://bugs.ruby-lang.org/issues/8977</a><br>
to add a new "frozen" method (or some other name) that the compiler<br>
would understand.</p>
</blockquote>
<p>I think having only .freeze is better (especially for compatibility) and<br>
a new .frozen method would be of minimal benefit.<br>
(But you know Ruby far better than I do)</p>
<blockquote>
<p>I also propose one alternative method name: the unary ~ operator.</p>
<p>There is no ~ on String right now, and it has no meaning for strings that we'd be overriding. So the following two lines would be equivalent:</p>
<p>str = ~"mystring"<br>
str = "mystring"f</p>
</blockquote>
<p>I hate this alternative "name". It's too ambiguous/confusing<br>
(consider: ~"username" or /regexp/ =~ ~"foo"),<br>
not backwards compatible, and hard to search for documentation on.</p>
<p>I think a beginner new to the language would be very confused by this.<br>
You have my strong support of #freeze, but my strongest disapproval of ~</p>
<blockquote>
<p>JUSTIFICATION:</p>
<p>Making the compiler aware of normal method-based String freezing has the following advantages:</p>
<ul>
<li>It will parse in all versions of Ruby.</li>
<li>It will be equivalent in all versions of Ruby other than the fstring pooling.</li>
<li>It extends neatly to Array and Hash; the compiler can see Array or Hash with literal elements and return the same object.</li>
<li>It does not require a pragma (<a href="http://bugs.ruby-lang.org/issues/8976" class="external">http://bugs.ruby-lang.org/issues/8976</a> )</li>
<li>It looks like Ruby.</li>
</ul>
</blockquote>
<p>Amen!</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423402013-10-09T04:24:08Zcibernox (Miguel Camba)miguel.camba@gmail.com
<ul></ul><p>I have another idea What about wrap strings in double backquotes or accents?</p>
<p>"this is an interpolable string"<br>
'this is an uninterpolable string'<br>
<code>this is a frozen string</code> => double backquoute<br>
´this is also a frozen string´ => simple accent</p>
<p>Accents looks elegant, but I don't know if they are cumbersome in some keyboard distributions and I am not sure if they al limited to UTF8 code, but double backquote seems easy to add to the parser and feels pretty natural.</p>
<p>Whatever character(s) you like the most, (<code>string</code>, ´sting´, ^string^, ~string~, \string) I like the idea to be used as a wrapper, not adding a special symbol before or after the string definition.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423432013-10-09T05:35:26Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>cibernox (Miguel Camba) wrote:</p>
<blockquote>
<p>I have another idea What about wrap strings in double backquotes or accents?</p>
<p>"this is an interpolable string"<br>
'this is an uninterpolable string'<br>
<code>this is a frozen string</code> => double backquoute</p>
</blockquote>
<p>I don't think the parser can distinguish this from normal backquotes that are empty...but there's no value to supporting empty shelling-out backquotes, so maybe it's not hard to special-case it.</p>
<p>if backquotes_contains_content<br>
parse_as_normal_backquote<br>
else<br>
parse_as_frozen_string<br>
end</p>
<p>Or something :-D</p>
<blockquote>
<p>´this is also a frozen string´ => simple accent</p>
</blockquote>
<p>Not on standard US keyboards, so this will never fly.</p>
<blockquote>
<p>Whatever character(s) you like the most, (<code>string</code>, ´sting´, ^string^, ~string~, \string) I like the idea to be used as a wrapper, not adding a special symbol before or after the string definition.</p>
</blockquote>
<p>Agreed. I still like just adding smarts for .freeze over any of the other options.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423442013-10-09T06:04:58Zcibernox (Miguel Camba)miguel.camba@gmail.com
<ul></ul><p>Yep, we can discard the accent.</p>
<p>The double pipe can be tricky is you want to set a frozen string as default value of a block argument.<br>
The double ^ has confict with the xor operator.<br>
The double ~ has conflict with the complement operator<br>
The double backslash seems fancy, like an opposite of regex, but since can also be used to break lines and escape characters. And probably is more difficult to parse . You tell me.</p>
<p>I know nothing about the parser internals, but the double backquote feels like a string and seems reasonable easy to implement. Seems the best option.</p>
<p>This idea can just coexist with the .freeze method. Is a bit of syntax sugar.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423472013-10-09T06:47:11ZAnonymous
<ul></ul><p>I feel like we're getting a bit off topic in this thread.</p>
<p>The main benefit of optimizing String#freeze is maintaining backwards compatibility with older Rubies. Think of it as a kind of 'progressive enhancement'.</p>
<p>Introducing new syntax or a new method completely removes any backwards compatibility benefits and will mean that most Ruby code will not be able to use this syntax for quite some time.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423482013-10-09T06:56:20Zsam.saffron (Sam Saffron)sam.saffron@gmail.com
<ul></ul><p>I am actually very concerned about compiler tricks with freeze cause it leads to non-obvious code.</p>
<p>x = "hello".freeze<br>
y = "hello".freeze<br>
x.object_id</p>
<blockquote>
<p>10<br>
x.object_id == y.object_id</p>
</blockquote>
<p>a = "hello"<br>
a.object_id</p>
<blockquote>
<p>100<br>
a.freeze<br>
a.object_id<br>
100 # must be 100</p>
</blockquote>
<hr>
<p>So the way #freeze operates then depends on where it is being executed, I dislike that.</p>
<p>Much prefer just adding #frozen, we can implement it sort of cleanly in 2.0 (except for GC hooking) and simply alias #freeze in 1.9 and earlier.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423532013-10-09T09:25:53Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>sam.saffron (Sam Saffron) wrote:</p>
<blockquote>
<p>I am actually very concerned about compiler tricks with freeze cause it leads to non-obvious code.</p>
<p>x = "hello".freeze<br>
y = "hello".freeze<br>
x.object_id</p>
<blockquote>
<p>10<br>
x.object_id == y.object_id</p>
</blockquote>
</blockquote>
<p>I don't think you should <em>ever</em> rely on this to be true, since it won't be on older Ruby impls or impls that don't yet have #freeze optimizations. Even Java, with its interned Strings, strongly discourages <em>ever</em> using object identity to compare strings. IDEs even flag it as a warning.</p>
<blockquote>
<p>a = "hello"<br>
a.object_id</p>
<blockquote>
<p>100<br>
a.freeze<br>
a.object_id<br>
100 # must be 100<br>
...<br>
So the way #freeze operates then depends on where it is being executed, I dislike that.</p>
</blockquote>
<p>Much prefer just adding #frozen, we can implement it sort of cleanly in 2.0 (except for GC hooking) and simply alias #freeze in 1.9 and earlier.</p>
</blockquote>
<p>So here's the same question I asked in the #frozen feature: why can't #freeze just use the fstring table?</p>
<ul>
<li>fstrings will GC and clear themselves from that table</li>
<li>large strings put into the table will take up no more space than if they were not frozen</li>
</ul>
<p>So #freeze <em>could</em> do what you suggest here and always use the fstring table. In the "literal".freeze case, the compiler could do additional magic to go to the table immediately.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423572013-10-09T11:29:17Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>"headius (Charles Nutter)" <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>So here's the same question I asked in the #frozen feature: why can't<br>
#freeze just use the fstring table?</p>
</blockquote>
<p>That would be an interesting experiment. After all, it is #freeze and<br>
not #freeze!, so maybe we have some leverage there.</p>
<blockquote>
<ul>
<li>fstrings will GC and clear themselves from that table</li>
</ul>
</blockquote>
<p>I think this needs some work for the non-parser case, there seems to<br>
be a bad interaction with lazy sweep. My analysis of my failed<br>
patch for Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: string keys for hash literals should use fstrings (Closed)" href="https://bugs.ruby-lang.org/issues/8998">#8998</a>:<br>
<a href="http://mid.gmane.org/20131009021547.GA1839@dcvr.yhbt.net" class="external">http://mid.gmane.org/20131009021547.GA1839@dcvr.yhbt.net</a></p>
<p>I also get (identical?) segfaults with the following:</p>
<p>diff --git a/object.c b/object.c<br>
--- a/object.c<br>
+++ b/object.c<br>
@@ -1029,6 +1029,8 @@ VALUE<br>
rb_obj_freeze(VALUE obj)<br>
{<br>
if (!OBJ_FROZEN(obj)) {</p>
<ul>
<li>if (TYPE(obj) == T_STRING)</li>
<li>
<pre><code> return rb_fstring(obj);
</code></pre>
OBJ_FREEZE(obj);<br>
if (SPECIAL_CONST_P(obj)) {<br>
if (!immediate_frozen_tbl) {</li>
</ul> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423582013-10-09T12:01:55Zsam.saffron (Sam Saffron)sam.saffron@gmail.com
<ul></ul><p>@hedius</p>
<p>What happens when a string pointer leaks out to a c extension?</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423632013-10-09T14:46:55Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>sam.saffron (Sam Saffron) wrote:</p>
<blockquote>
<p>@hedius</p>
<p>What happens when a string pointer leaks out to a c extension?</p>
</blockquote>
<p>This question applies equally to "str"f logic. I'm not sure what the answer is, because I don't know how frozen strings in @charliesome's patch interact with C extensions.</p>
<p>I don't think making freeze act like Java's String#intern has any better or worse interaction with C extensions than normal "str"f fstrings interact with C extensions.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423642013-10-09T14:48:14Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>headius (Charles Nutter) wrote:</p>
<blockquote>
<p>This question applies equally to "str"f logic. I'm not sure what the answer is, because I don't know how frozen strings in @charliesome's patch interact with C extensions.</p>
</blockquote>
<p>Actually, it occurred to me that the interaction with C extensions is actually even simpler; if a string leaks out to C exts, it's no worse than <em>any</em> string leaking out. The only difference is that the C ext would still have a reference while the fstring table does not. So I think it's no worse than current interaction with strings.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423652013-10-09T14:53:05Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>normalperson (Eric Wong) wrote:</p>
<blockquote>
<p>"headius (Charles Nutter)" <a href="mailto:headius@headius.com" class="email">headius@headius.com</a> wrote:</p>
<blockquote>
<p>So here's the same question I asked in the #frozen feature: why can't<br>
#freeze just use the fstring table?</p>
</blockquote>
<p>That would be an interesting experiment. After all, it is #freeze and<br>
not #freeze!, so maybe we have some leverage there.</p>
</blockquote>
<p>I think we do. The worst case scenario is that <em>while referenced</em> we have more entries in the table, which may include strings that become "shady" and pass out to C exts. But those strings would stay alive under the current definition of "shady" and even under older Ruby versions with a purely conservative GC the effects are no worse.</p>
<p>So basically:</p>
<ul>
<li>If the string is long lived normally, it will take up X bytes for its lifetime.</li>
<li>If the string gets stored in the fstring table, it will last no longer than it would without the fstring table.</li>
<li>If the string is short-lived, it will have a bit more overhead for dealing with fstring table, but very little; hash calculation and table management at most.</li>
</ul>
<p>It seems acceptable to have #freeze basically be Java's #intern.</p>
<blockquote>
<blockquote>
<ul>
<li>fstrings will GC and clear themselves from that table</li>
</ul>
</blockquote>
<p>I think this needs some work for the non-parser case, there seems to<br>
be a bad interaction with lazy sweep. My analysis of my failed<br>
patch for Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: string keys for hash literals should use fstrings (Closed)" href="https://bugs.ruby-lang.org/issues/8998">#8998</a>:<br>
<a href="http://mid.gmane.org/20131009021547.GA1839@dcvr.yhbt.net" class="external">http://mid.gmane.org/20131009021547.GA1839@dcvr.yhbt.net</a></p>
</blockquote>
<p>I don't doubt your analysis, but I don't think it's any worse with #freeze using fstring table. It's just multiplied by the number of strings that get frozen. Critical failure * N is still a critical failure.</p>
<blockquote>
<p>I also get (identical?) segfaults with the following:</p>
<p>diff --git a/object.c b/object.c<br>
--- a/object.c<br>
+++ b/object.c<br>
@@ -1029,6 +1029,8 @@ VALUE<br>
rb_obj_freeze(VALUE obj)<br>
{<br>
if (!OBJ_FROZEN(obj)) {</p>
<ul>
<li>if (TYPE(obj) == T_STRING)</li>
<li>
<pre><code> return rb_fstring(obj);
</code></pre>
OBJ_FREEZE(obj);<br>
if (SPECIAL_CONST_P(obj)) {<br>
if (!immediate_frozen_tbl) {</li>
</ul>
</blockquote>
<p>Same argument here, I think.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424402013-10-14T08:40:23Zsam.saffron (Sam Saffron)sam.saffron@gmail.com
<ul></ul><p>@hedius</p>
<p>There are 3 things being discussed here, I think it is fairly important we split them out.</p>
<ol>
<li>Parser optimisation for "string".freeze</li>
<li>Unconditionally have #freeze return a pooled string</li>
<li>Change the semantics of #freeze so it amends the current object and operates like .NET / Java intern does.</li>
</ol>
<ol>
<li>
<p>is completely doable with little side-effects. My caveat is that if #1 is the only thing done, the semantics for #freeze depend on the invocation. That said, this is minor. I totally accept that and prefer "string".freeze to "string"f.</p>
</li>
<li>
<p>without 3) really scares me.</p>
</li>
</ol>
<p>Imagine the odd semantics:</p>
<p>a = "hello"<br>
a.freeze # freezes one RVALUE in memory and returns a different RVALUE</p>
<p>As to 3) I don't think it can be implemented in MRI. If an RVALUE is moved in memory, MRI is going to have to crawl the heap and rewrite all the RVALUE that hold a ref to it, it does not keep track of this internally.</p>
<p>@charliesome thoughts?</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424422013-10-14T12:53:27Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>(13/10/14 8:40), sam.saffron (Sam Saffron) wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Use String#freeze and compiler tricks to replace "str"f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a> has been updated by sam.saffron (Sam Saffron).</p>
</blockquote>
<p>Thank you for summarizing.</p>
<blockquote>
<p>There are 3 things being discussed here, I think it is fairly important we split them out.</p>
<ol>
<li>Parser optimisation for "string".freeze</li>
</ol>
</blockquote>
<blockquote>
<ol>
<li>is completely doable with little side-effects. My caveat is that if #1 is the only thing done, the semantics for #freeze depend on the invocation. That said, this is minor. I totally accept that and prefer "string".freeze to "string"f.</li>
</ol>
</blockquote>
<p>It's a part of byte-code optimization, not parser. Since we have done<br>
it already for several methods, no problem there.</p>
<blockquote>
<ol start="2">
<li>Unconditionally have #freeze return a pooled string</li>
<li>Change the semantics of #freeze so it amends the current object and operates like .NET / Java intern does.</li>
</ol>
</blockquote>
<blockquote>
<ol start="2">
<li>without 3) really scares me.</li>
</ol>
<p>Imagine the odd semantics:</p>
<p>a = "hello"<br>
a.freeze # freezes one RVALUE in memory and returns a different RVALUE</p>
<p>As to 3) I don't think it can be implemented in MRI. If an RVALUE is moved in memory, MRI is going to have to crawl the heap and rewrite all the RVALUE that hold a ref to it, it does not keep track of this internally.</p>
</blockquote>
<p>Totally agree.</p>
<p>2+3 is wrong idea, I think.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424432013-10-14T15:59:43Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>Ok, let's just focus on #1 for now...</p>
<p>It seems like everyone agrees that "string".freeze is a better choice than adding incompatible syntax now. That was the original proposal in this issue.</p>
<p>Should we remove "string"f on master and replace it with charliesome's patch for "string".freeze? Or do we want to bikeshed a shorter name?</p>
<p>It occurred to me the there's already "string".b which returns a binary string. Should we consider "string".f which is similar to "string"f syntax but is just a normal method?</p>
<p>I think we're in agreement that we want the method format rather than the "f" suffix, so it's just a matter of deciding if we want a different method name for the new compiler-aware method.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424442013-10-14T17:23:19Zphluid61 (Matthew Kerwin)matthew@kerwin.net.au
<ul></ul><p>On Oct 14, 2013 5:00 PM, "headius (Charles Nutter)" <a href="mailto:headius@headius.com" class="email">headius@headius.com</a><br>
wrote:</p>
<blockquote>
<p>Ok, let's just focus on #1 for now...</p>
<p>It seems like everyone agrees that "string".freeze is a better choice<br>
than adding incompatible syntax now. That was the original proposal in this<br>
issue.</p>
<p>Should we remove "string"f on master and replace it with charliesome's<br>
patch for "string".freeze? Or do we want to bikeshed a shorter name?</p>
<p>It occurred to me the there's already "string".b which returns a binary<br>
string. Should we consider "string".f which is similar to "string"f syntax<br>
but is just a normal method?</p>
<p>I think we're in agreement that we want the method format rather than the<br>
"f" suffix, so it's just a matter of deciding if we want a different method<br>
name for the new compiler-aware method.</p>
</blockquote>
<p>Yes. I feel like regexen have suffixes because of decades of perl<br>
precedence, but they (suffixes) don't belong anywhere else.</p>
<p>For a method, I feel like #freeze is the better name, my only question is:<br>
is anyone monkeypatching it (and therefore will be bitten by this<br>
optimisation)? I doubt it, but we should still ask. The same question would<br>
have to be asked of the new method; I think there's more chance of #f being<br>
used in the wild than an overridden #freeze</p>
<p>Also in the favour of #freeze, it gives existing code a boost without any<br>
modification.</p>
<p>Sent from my phone, so excuse the typos.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424452013-10-14T17:29:18Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Nobuyoshi Nakada <a href="mailto:nobu@ruby-lang.org" class="email">nobu@ruby-lang.org</a> wrote:</p>
<blockquote>
<p>(13/10/14 8:40), sam.saffron (Sam Saffron) wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Use String#freeze and compiler tricks to replace "str"f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a> has been updated by sam.saffron (Sam Saffron).</p>
</blockquote>
<p>Thank you for summarizing.</p>
<blockquote>
<p>There are 3 things being discussed here, I think it is fairly important we split them out.</p>
<ol>
<li>Parser optimisation for "string".freeze</li>
</ol>
</blockquote>
<blockquote>
<ol>
<li>is completely doable with little side-effects. My caveat is that if #1 is the only thing done, the semantics for #freeze depend on the invocation. That said, this is minor. I totally accept that and prefer "string".freeze to "string"f.</li>
</ol>
</blockquote>
<p>It's a part of byte-code optimization, not parser. Since we have done<br>
it already for several methods, no problem there.</p>
</blockquote>
<p>So can we move this optimization to the parser instead? I think Sam means:</p>
<pre><code># optimized literal by parser. This may use pooled string since
# the string never existed in ObjectSpace before this line of code:
"string".freeze
</code></pre>
<p>However, if .freeze operates on a variable (and not literal):</p>
<pre><code># leave this optimized by parser to avoid incompatibility
a = "string"
a.freeze => preserve existing behavior
</code></pre>
<blockquote>
<blockquote>
<ol start="2">
<li>Unconditionally have #freeze return a pooled string</li>
<li>Change the semantics of #freeze so it amends the current object and operates like .NET / Java intern does.</li>
</ol>
</blockquote>
<blockquote>
<ol start="2">
<li>without 3) really scares me.</li>
</ol>
<p>Imagine the odd semantics:</p>
<p>a = "hello"<br>
a.freeze # freezes one RVALUE in memory and returns a different RVALUE</p>
</blockquote>
</blockquote>
<p>Yes, this scares me if a.freeze made a different RVALUE</p>
<blockquote>
<blockquote>
<p>As to 3) I don't think it can be implemented in MRI. If an RVALUE is moved in memory, MRI is going to have to crawl the heap and rewrite all the RVALUE that hold a ref to it, it does not keep track of this internally.</p>
</blockquote>
<p>Totally agree.</p>
<p>2+3 is wrong idea, I think.</p>
</blockquote>
<p>Agreed.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424492013-10-14T23:46:32ZAnonymous
<ul></ul><p>Totally agree with ssaffron on options 2 and 3 being scary. 3 is also impossible in MRI at the moment.</p>
<p>I'm happy to commit my patch optimizing #freeze on a literal string if it looks good.</p>
<p>I think we should move the discussion of removing f-suffix and perhaps adding String#f to another ticket.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424552013-10-15T07:57:30Zsam.saffron (Sam Saffron)sam.saffron@gmail.com
<ul></ul><p>+1 for removing f suffix and amending the optimiser for #freeze</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425462013-10-22T21:19:05Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>I have added <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Remove "f" suffix in favor of VM optimization of "literal".freeze (Closed)" href="https://bugs.ruby-lang.org/issues/9042">#9042</a> and <a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: Add String#f method as shortcut for #freeze (Open)" href="https://bugs.ruby-lang.org/issues/9043">#9043</a> for removing the "f" suffix and adding the #f method, respectively.</p>
<p>I'm starting to lean toward making #f be the only magic form, so nobody can complain that we're adding incompatible syntax ("f" suffix) or changing the semantics of an existing method (#freeze optimization).</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425542013-10-23T05:13:47ZAnonymous
<ul></ul><blockquote>
<p>I'm starting to lean toward making #f be the only magic form, so nobody can complain that we're ... changing the semantics of an existing method (#freeze optimization).</p>
</blockquote>
<p>I don't get this argument. Optimized String#freeze doesn't really change semantics in any real way. I'm happy to just ignore anyone that complains about optimizing #freeze on a string literal.</p>
<p>There's only one way this could possibly affect any Ruby code - and that's if the code inspects the object_id of literal strings that it immediately calls #freeze on. I'd say any code that breaks due to this was already fairly brittle anyway.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425652013-10-23T20:52:37ZEregon (Benoit Daloze)
<ul></ul><p>I agree having optimized #freeze is better than #f.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425662013-10-23T21:23:17Zakr (Akira Tanaka)akr@fsij.org
<ul></ul><p>2013/10/8 headius (Charles Nutter) <a href="mailto:headius@headius.com" class="email">headius@headius.com</a>:</p>
<blockquote>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Use String#freeze and compiler tricks to replace "str"f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a>: Use String#freeze and compiler tricks to replace "str"f suffix<br>
<a href="https://bugs.ruby-lang.org/issues/8992" class="external">https://bugs.ruby-lang.org/issues/8992</a></p>
</blockquote>
<a name="Does-anyone-measure-actual-performance-benefit"></a>
<h2 >Does anyone measure actual performance benefit?<a href="#Does-anyone-measure-actual-performance-benefit" class="wiki-anchor">¶</a></h2>
<p>Tanaka Akira</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425812013-10-24T02:23:18Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Tanaka Akira <a href="mailto:akr@fsij.org" class="email">akr@fsij.org</a> wrote:</p>
<blockquote>
<p>2013/10/8 headius (Charles Nutter) <a href="mailto:headius@headius.com" class="email">headius@headius.com</a>:</p>
<blockquote>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Use String#freeze and compiler tricks to replace "str"f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a>: Use String#freeze and compiler tricks to replace "str"f suffix<br>
<a href="https://bugs.ruby-lang.org/issues/8992" class="external">https://bugs.ruby-lang.org/issues/8992</a></p>
</blockquote>
<p>Does anyone measure actual performance benefit?</p>
</blockquote>
<p>Not directly, but I wasn't able to come up with performance benefits<br>
from my patch for <a href="https://bugs.ruby-lang.org/issues/8998" class="external">https://bugs.ruby-lang.org/issues/8998</a><br>
However, I don't have real apps which depend on hash/string-keys<br>
performance.</p>
<p>Perhaps other improvements (RGenGC) make it less useful.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427202013-11-02T11:23:20Zko1 (Koichi Sasada)
<ul></ul><p>Matz, could you conclude this ticket?</p>
<p>I like this idea because:</p>
<ul>
<li>No syntax change</li>
<li>Semantics was changed ("literal".freeze.object_id => anytime same),<br>
but I can't imagine the apps which rely on this behavior.</li>
<li>Except 2nd point, this is no compatibility issue.</li>
</ul>
<p>(2013/10/08 2:56), headius (Charles Nutter) wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Use String#freeze and compiler tricks to replace "str"f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a> has been reported by headius (Charles Nutter).</p>
<hr>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Use String#freeze and compiler tricks to replace "str"f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a>: Use String#freeze and compiler tricks to replace "str"f suffix<br>
<a href="https://bugs.ruby-lang.org/issues/8992" class="external">https://bugs.ruby-lang.org/issues/8992</a></p>
</blockquote>
<p>--<br>
// SASADA Koichi at atdot dot net</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427212013-11-02T11:59:59Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><ul>
<li>I am OK with adding a new method (e.g. String#f) and compiler trick.</li>
<li>I hesitate a bit to change String#freeze semantics.</li>
<li>String#~ is very concise and in that sense attractive, but relation of '~' with patterns may cause confusion.</li>
</ul>
<p>So, my conclusion is adding String#f with compiler trick. I still need some discussion for changing String#freeze.<br>
Note that I don't have strong objection against String#freeze.</p>
<p>Matz.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427222013-11-02T12:18:46Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>matz (Yukihiro Matsumoto) wrote:</p>
<blockquote>
<ul>
<li>I am OK with adding a new method (e.g. String#f) and compiler trick.</li>
</ul>
</blockquote>
<p>Somewhat oppose against "f" with compiler trick.</p>
<p>"f" is a typical meta-syntactic variable of functions.<br>
I guess some programs have the following code.</p>
<p>class String<br>
def f<br>
...<br>
end<br>
end</p>
<p>In fact, I've found some instances in a few minutes:</p>
<p><a href="http://blog.goo.ne.jp/ruby-index/e/91995e39fe1fe72d339d882cf5ded055" class="external">http://blog.goo.ne.jp/ruby-index/e/91995e39fe1fe72d339d882cf5ded055</a><br>
<a href="http://python.g.hatena.ne.jp/mhrs/20060530" class="external">http://python.g.hatena.ne.jp/mhrs/20060530</a></p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427242013-11-02T12:33:18ZAnonymous
<ul></ul><p>Matz, I believe adding a new method will significantly limit the usefulness of this feature.</p>
<p>The reason optimizing "".freeze is superior to a new syntax is that gems can start using this feature now without dropping support for versions < 2.1.</p>
<p>I think many Gem authors will be very hesitant to monkey patch String#f to String#freeze.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427342013-11-04T00:28:15ZAnonymous
<ul></ul><p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/18">@mame (Yusuke Endoh)</a>: Good catch. How about String#fz then?</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=428082013-11-08T04:20:34Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>matz: Thank you for weighing in. I think we are on the same page.</p>
<p>There are a few different versions of this proposal getting tossed around, so I'll try to summarize the key points.</p>
<ol>
<li>We would like a compiler trick to replace the "str"f suffix.</li>
<li>The compiler trick would apply to literal strings with immediate calls to a freeze method and behave as "str"f does today.</li>
<li>The freeze method optimized by the compiler will be #freeze or a new shorter-named method #f or both.</li>
<li>Calls to #freeze against non-literals would behave as now.</li>
<li>Calls to #f, would use the fstring functionality to return a globally cached string (similar to interning in Java, from <a class="issue tracker-1 status-8 priority-4 priority-default closed" title="Bug: TestSignal#test_hup_me hangs up the test suite (Third Party's Issue)" href="https://bugs.ruby-lang.org/issues/8997">#8997</a>)</li>
</ol>
<p>It sounds like almost everyone is in favor of eliminating the "str"f suffix, so I think we can take that as written.</p>
<p>Decisions to make:</p>
<ol>
<li>Do we add a new method that can do <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: String#frozen that takes advantage of the deduping (Closed)" href="https://bugs.ruby-lang.org/issues/8977">#8977</a> behavior?<br>
1a. What do we call it?</li>
<li>If we do not add a new method, should compiler tricks also optimize "string".freeze?</li>
</ol>
<p>I think the following is a good plan:</p>
<ul>
<li>If we all agree that "string"f should go away, then we should switch to "string".freeze compiler trick asap. @charliesome provided a patch.</li>
<li>If we want another method, we should decide on a name and decide whether "string".freeze should still have compiler trick.</li>
</ul> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=428302013-11-10T05:52:45ZAnonymous
<ul></ul><p>At RubyConf Matz approved optimizing #freeze on static string literals and removing f-suffix.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=428322013-11-10T06:03:31ZEregon (Benoit Daloze)
<ul></ul><p>charliesome (Charlie Somerville) wrote:</p>
<blockquote>
<p>At RubyConf Matz approved optimizing #freeze on static string literals and removing f-suffix.</p>
</blockquote>
<p>Great!</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=428872013-11-13T07:20:04Zheadius (Charles Nutter)headius@headius.com
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>This has been completed as of revisions r43627 and r43634.</p>
<p>Thanks for the collaboration, everyone :-)</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=435712013-12-10T19:54:14ZAnonymous
<ul></ul><p>sawa: %-strings are already covered by #freeze optimization:</p>
<pre><code>λ ./miniruby --dump=insns -e '%{}.freeze'
== disasm: <RubyVM::InstructionSequence:<main>@-e>======================
0000 trace 1 ( 1)
0002 opt_str_freeze ""
0004 leave
</code></pre> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=435722013-12-10T19:55:31Zsawa (Tsuyoshi Sawada)
<ul></ul><p>charliesome (Charlie Somerville) wrote:</p>
<blockquote>
<p>sawa: %-strings are already covered by #freeze optimization:</p>
<pre><code>λ ./miniruby --dump=insns -e '%{}.freeze'
== disasm: <RubyVM::InstructionSequence:<main>@-e>======================
0000 trace 1 ( 1)
0002 opt_str_freeze ""
0004 leave
</code></pre>
</blockquote>
<p>Thanks. I should have checked before. I deleted my previous post.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=779942019-05-13T16:41:15Zbughit (bug hit)
<ul></ul><p>I recently had to remind myself what kind of magic is hiding behind 'str'.freeze and would like to provide some feedback.</p>
<p>While tactically this may have been justified, strategically this is a wrong direction. This approach moves the language towards a collection of magical spells. You end up with code that can't be understood through decomposition into primitives.</p>
<p>'str'.method1 - means construct a string object with a value 'str' and call method 'method1' on it.</p>
<p>The notion that a method call should have time travel powers and be able to influence how its already constructed receiver is allocated is absurd. It makes mockery of such fundamental concepts as expression evaluation order and method invocation. Perhaps this is already being done elsewhere, not sure, but that's not a justification, doubling down on nonsense does not make it sense.</p>
<p>Whereas special syntax (whatever it is) does not have this flaw. You get to define what new syntax means without corrupting existing concepts, and in the long run this is more valuable than helping gem authors transition to immutable strings.</p> Ruby master - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=1066522024-02-09T11:23:31Zbyroot (Jean Boussier)byroot@ruby-lang.org
<ul><li><strong>Related to</strong> <i><a class="issue tracker-5 status-5 priority-4 priority-default closed" href="/issues/20222">Misc #20222</a>: Dedup-ing clarification</i> added</li></ul>