[ruby-core:93458] [Ruby master Feature#15940] Coerce symbols internal fstrings in UTF8 rather than ASCII to better share memory with string literals

From: eregontp@...
Date: 2019-07-01 17:25:36 UTC
List: ruby-core #93458
Issue #15940 has been updated by Eregon (Benoit Daloze).


byroot (Jean Boussier) wrote:
> What do you mean by performance ? String comparisons ? If so it doesn't really matter much for symbols AFAIK.

I mean performance of String operations on a UTF-8 vs a US-ASCII String.
As @nirvdrum said above, some optimizations might only apply to US-ASCII, although in most cases the coderange should make it apply to UTF-8 too.

> IMO there's two arguments here:
>   - Consistency / Least surprise: UTF-8 is now the default source file encoding, it would make sense that the symbols created out of these files (not just `Symbol` instances, but module names, method names etc) would be UTF-8 as well.

Right, that argument makes sense to me.

Does this PR also addresses module and method names?
FWIW, TruffleRuby already uses UTF-8 for module and method names, and it seems not to be a compatibility problem.

It will be a bit weird if there is a magic encoding comment though, as then Symbols, module/method names will be UTF-8 if 7-bit but the specified magic encoding if not 7-bit.

----------------------------------------
Feature #15940: Coerce symbols internal fstrings in UTF8 rather than ASCII to better share memory with string literals
https://bugs.ruby-lang.org/issues/15940#change-79005

* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Patch: https://github.com/ruby/ruby/pull/2242

It's not uncommon for symbols to have literal string counterparts, e.g.

```ruby
class User
  attr_accessor :name

  def as_json
    { 'name' => name }
  end
end
```

Since the default source encoding is UTF-8, and that symbols coerce their internal fstring to ASCII when possible, the above snippet will actually keep two instances of `"name"` in the fstring registry. One in ASCII, the other in UTF-8.

Considering that UTF-8 is a strict superset of ASCII, storing the symbols fstrings as UTF-8 instead makes no significant difference, but allows in most cases to reuse the equivalent string literals.

The only notable behavioral change is `Symbol#to_s`.

Previously `:name.to_s.encoding` would be `#<Encoding:US-ASCII>`.
After this patch it's `#<Encoding:UTF-8>`. I can't foresee any significant compatibility impact of this change on existing code.

However, there are several ruby specs asserting this behavior, but I don't know if they can be changed or not: https://github.com/ruby/spec/commit/a73a1c11f13590dccb975ba4348a04423c009453

If this specification is impossible to change, then we could consider changing the encoding of the String returned by `Symbol#to_s`, e.g in ruby pseudo code:

```ruby
def to_s
  str = fstr.dup
  str.force_encoding(Encoding::ASCII) if str.ascii_only?
  str
end
```





-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread

Prev Next