ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: mame@ruby-lang.org
To: ruby-core@ruby-lang.org
Subject: [ruby-core:96479] [Ruby master Feature#16291] Introduce support for resize in rb_ary_freeze and prefer internal use of rb_ary_freeze and rb_str_freeze for String and Array types
Date: Thu, 26 Dec 2019 02:24:51 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-83407.20191226022450.7b5e8a9d1ce08068@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16291.20191104134503@ruby-lang.org

Issue #16291 has been updated by mame (Yusuke Endoh).

Target version set to 2.8
Assignee set to nobu (Nobuyoshi Nakada)
Tracker changed from Misc to Feature

This ticket was discussed at the previous dev meeting, and @nobu will review the patch and merge it if okay.

----------------------------------------
Feature #16291: Introduce support for resize in rb_ary_freeze and prefer internal use of rb_ary_freeze and rb_str_freeze for String and Array types
https://bugs.ruby-lang.org/issues/16291#change-83407

* Author: methodmissing (Lourens Naudé)
* Status: Open
* Priority: Normal
* Assignee: nobu (Nobuyoshi Nakada)
* Target version: 2.8
----------------------------------------
References Github PR https://github.com/ruby/ruby/pull/2640

### Why?

While working on https://github.com/ruby/ruby/pull/2037#issuecomment-548633141 I also looked at the `rb_ary_freeze` helper to determine if the same optimization of shrinking capacity can be applied there as well.

Further investigation revealed that `rb_str_freeze` attempts to resize / shrink strings on freeze, but we currently don't do the same for arrays despite API for it being exposed.

The gist of the change:

* Let `rb_ary_freeze` also attempt to right size an array before freezing it
* Replaced internal use of `rb_obj_freeze` and `OBJ_FREEZE` of callsites that pass a String or Array type in with `rb_ary_freeze` and `rb_str_freeze` specifically.

### Results

Saves about 3MB of Array and String specific heap footprints on a redmine production env boot on Rails 6 (custom local upgrade - it does not officially support it yet):

```
Loading production environment (Rails 6.1.0.alpha)
irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 2.7.0dev (2019-11-02T06:32:49Z master 772b0613c5) [x86_64-linux]"
irb(main):002:0> require 'objspace'
=> true
irb(main):003:0> GC.start
=> nil
irb(main):004:0> ObjectSpace.each_object(Array).sum {|o| ObjectSpace.memsize_of(o) }
=> 4451200
irb(main):005:0> ObjectSpace.each_object(String).sum {|o| ObjectSpace.memsize_of(o) }
=> 8608472
irb(main):006:0> exit
```

```
Loading production environment (Rails 6.1.0.alpha)
irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 2.7.0dev (2019-11-02T16:52:34Z obj-freeze-specifi.. 3bc4048899) [x86_64-linux]"
irb(main):002:0> require 'objspace'
=> true
irb(main):003:0> GC.start
=> nil
irb(main):004:0> ObjectSpace.each_object(Array).sum {|o| ObjectSpace.memsize_of(o) }
=> 3233432
irb(main):005:0> ObjectSpace.each_object(String).sum {|o| ObjectSpace.memsize_of(o) }
=> 6748422
```

irb - the best calculator ...

```
irb(main):002:0> (4451200 - 3233432) / 1024
=> 1189
irb(main):003:0> (8608472 - 6748422) / 1024
=> 1816
```

### Open questions

* Would it make sense to let `rb_obj_freeze` switch on object type instead and apply this optimization without "polluting" internals with custom callsite changes? Native extensions can then benefit from the resize feature too.
* HOWEVER: Discovered in testing that `rb_str_freeze` can fail asserts in `rb_str_tmp_frozen_release` when sprinkled too generously especially in `io.c`. And other issues may lurk too, thus incorporating the resizing in `rb_obj_freeze` won't work.  See https://github.com/ruby/ruby/pull/2640#issuecomment-549119359

I think it could also make sense to split the PR in 2:

* One changeset for `rb_ary_freeze` attempting to resize Arrays on freeze, special case internal `rb_obj_freeze` of Arrays to prefer the new API
* Apply `rb_str_resize` at internal call sites where `rb_obj_freeze` is used with String types

Thoughts?



-- 
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>

  parent reply	other threads:[~2019-12-26  2:25 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-16291.20191104134503@ruby-lang.org>
2019-11-04 13:45 ` [ruby-core:95665] [Ruby master Misc#16291] Introduce support for resize in rb_ary_freeze and prefer internal use of rb_ary_freeze and rb_str_freeze for String and Array types lourens
2019-11-05  1:49 ` [ruby-core:95684] " shyouhei
2019-11-08 22:31 ` [ruby-core:95765] " lourens
2019-12-26  2:24 ` mame [this message]
2019-12-31  6:43 ` [ruby-core:96606] [Ruby master Feature#16291] " sam.saffron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-83407.20191226022450.7b5e8a9d1ce08068@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).