From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS4713 221.184.0.0/13 X-Spam-Status: No, score=-4.1 required=3.0 tests=AWL,BAYES_00, MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by dcvr.yhbt.net (Postfix) with ESMTP id 3922F1F463 for ; Sat, 21 Sep 2019 16:28:03 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id 002AA1209CC; Sun, 22 Sep 2019 01:27:53 +0900 (JST) Received: from xtrwkhkc.outbound-mail.sendgrid.net (xtrwkhkc.outbound-mail.sendgrid.net [167.89.16.28]) by neon.ruby-lang.org (Postfix) with ESMTPS id 703471209C9 for ; Sun, 22 Sep 2019 01:27:50 +0900 (JST) Received: by filter0130p3las1.sendgrid.net with SMTP id filter0130p3las1-15851-5D864F88-1A 2019-09-21 16:27:52.450794535 +0000 UTC m=+98988.162831963 Received: from herokuapp.com (unknown [3.85.105.179]) by ismtpd0036p1iad1.sendgrid.net (SG) with ESMTP id pUmat_xdQYefszgtv5mEhA for ; Sat, 21 Sep 2019 16:27:52.464 +0000 (UTC) Date: Sat, 21 Sep 2019 16:27:52 +0000 (UTC) From: mame@ruby-lang.org Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 70573 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 16153 X-Redmine-Issue-Author: Dan0042 X-Redmine-Sender: mame X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: =?us-ascii?Q?EJh2gqwnyqXtd++xo=2FinyA1V0bXouTB4FkWnzNiKb48M2HDM5=2F=2FxxqIs28Cy53?= =?us-ascii?Q?ERN+E0M5Lr9rF+AIiixCYaSlThoVjs2B=2FpHiFn+?= =?us-ascii?Q?RAU6hC8W0hX7PQHL4ZbL5ZOcjsnmApeB0o6z5Kv?= =?us-ascii?Q?NaiTcJa40sc1M=2F6j54f1DwjegXPkFbx9GQqx91E?= =?us-ascii?Q?xFiwc8hd7p3xgO9b7f7ADLzabhs2u6fFEyQ=3D=3D?= To: ruby-core@ruby-lang.org X-ML-Name: ruby-core X-Mail-Count: 95018 Subject: [ruby-core:95018] [Ruby master Feature#16153] eventually_frozen flag to gradually phase-in frozen strings X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #16153 has been updated by mame (Yusuke Endoh). Matz didn't determine this proposal at the meeting. There were four points discussed: * Before matz accepts this proposal, he must decide the grand design change: Ruby should be immutable by default? * If we want to make Ruby gradually immutable, this proposal is feasible. * However, it is arguable if it is worthwhile consuming one bit for each object for this feature. * Even after Ruby is immutable, it is doubtful if Ruby becomes so faster. --- The following is my opinion. I'm against making Ruby immutable by default. One of the most important properties of Ruby is dynamics. Ruby has allowed users to change almost anything in run time: dynamically (re)defining classes and methods (including core builtin ones), manipulating instance variables and local variables (via Binding) through encapsulation, etc. These features are not recommended to abuse, but they actually bring big flexibility: monkey-patching, DRY, flexible operation, etc. However, blindly freezing objects may spoil this usefulness. It is a bit arguable if this flexibility limits performance. Some people say that it is possible to make Ruby fast with the flexibility kept (TruffleRuby proves it). That being said, I admit that the flexibility actually limits performance in the current MRI, and that we have no development resource to improve MRI so much in near future. I think that my proposal #11934 was one possible way to balance the flexibility and performance. Anyway, we need to estimate how much Ruby can be faster if the flexibility is dropped. If it becomes 10 times faster, it is worth considering of course. If it becomes 10 percent faster, it does not pay (in my opinion). ---------------------------------------- Feature #16153: eventually_frozen flag to gradually phase-in frozen strings https://bugs.ruby-lang.org/issues/16153#change-81645 * Author: Dan0042 (Daniel DeLorme) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- Freezing objects can give us a nice performance boost, but freezing previously non-frozen objects is a backward-incompatible change which is hard to handle because the place where the object is mutated can be far from where it was frozen, and tests might not cover the cases of frozen input vs non-frozen input. I propose adding a flag which gives us a migration path for freezing objects. For purposes of discussion I will call this flag "eventually_frozen". It would act as a pseudo-frozen flag where mutating the object would result in a warning instead of an error. It would also change the return value of `Object#frozen?` so code like `obj = obj.dup if obj.frozen?` would work as expected to remove the warning. Note that eventually_frozen strings cannot be deduplicated, as they are in reality mutable. This way it would be possible for Symbol#to_s (and many others) to return an eventually_frozen string in 2.7 which gives apps and gems time to migrate, before finally becoming a frozen deduplicated string in 3.0. This might even open up a migration path for eventually using `frozen_string_literal:true` as default. For example if it was possible to add `frozen_string_literal:eventual` to all files in a project (or as a global switch), we could run that in production to discover where to fix things, and then change it to `frozen_string_literal:true` for a bug-free performance boost. Proposed changes: * Object#freeze(immediately:true) * if `immediately` keyword is true, set frozen=true and eventually_frozen=false * if `immediately` keyword is false, set eventually_frozen=true UNLESS frozen flag is already true * String#+@ * if eventually_frozen is true, create a duplicate string with eventually_frozen=false * Object#frozen?(immediately:false) * return true if `immediately` keyword is false and eventually_frozen flag is true * rb_check_frozen * output warning if eventually_frozen flag is true -- https://bugs.ruby-lang.org/