From: alanwucanada@... Date: 2019-04-12T04:17:27+00:00 Subject: [ruby-core:92254] [Ruby trunk Feature#15765] [PATCH] Module#name without global constant search Issue #15765 has been updated by alanwu (Alan Wu). This is for #11119 and #15625. ---------------------------------------- Feature #15765: [PATCH] Module#name without global constant search https://bugs.ruby-lang.org/issues/15765#change-77587 * Author: alanwu (Alan Wu) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- Hello! I have put together a reimplementation of `Module#name`, which works by eagerly naming modules and classes when they are assigned to constants. Besides solving the performance issues for `Module#name` on anonymous modules, there are some other benefits. This patch: - removes more code than it adds - makes normal class and module definition slightly faster (definitions like `class Foo; end`) - slightly reduces memory usage for classes and modules due to the removal of a hidden ivar - improves the performance of defining modules and classes under an anonymous module. This used to execute a global search. ### Behavior changes and caveats: ```ruby mod = Module.new mod::BeforeToS = Module.new mod.const_set(:BeforeToS2, Module.new) mod.to_s # on trunk, the VM starts naming modules assigned under mod after calling to_s mod::AfterToS = Module.new mod.const_set(:AfterToS2, Module.new) p mod::BeforeToS.name p mod::BeforeToS2.name p mod::AfterToS.name p mod::AfterToS2.name ``` This prints 4 nils after my patch, as I think the behavior on trunk is unintentional. A few C APIs also have the same effect as calling to_s. They are all changed to be side-effect free. ```ruby m = Module.new m::Child = Module.new Mod = m p Object.send(:remove_const, :Mod)::Child.name ``` This prints nil on trunk and `Mod::Child` under this patch. `rb_name_class` is removed, as it does nothing in this new implementation. Not sure if this is public API. Since the recursive naming is done with a recursive function. When a deeply nested anonymous module is assigned to a constant, it is technically possible for this implementation to throw a `StackError`. I had a version which does heap allocation to deal with this, but I picked this version for performance in the common cases. Anonymous modules are rare as is, and one would have to build a structure nested thousands level deep for this to happen. On my system it can name a module fifty thousand levels deep without problem. I think these changes are fairly minimal and acceptable. ---Files-------------------------------- benchmarks.rb (3.16 KB) 0001-Eagerly-name-modules-and-classes.patch (19.8 KB) -- https://bugs.ruby-lang.org/ Unsubscribe: