From: mame@... Date: 2020-10-01T23:56:32+00:00 Subject: [ruby-core:100269] [Ruby master Bug#17209] String#slice allocates Range object in ruby 3.0.0preview1 Issue #17209 has been updated by mame (Yusuke Endoh). Assignee set to ko1 (Koichi Sasada) Status changed from Open to Assigned The optimization has been disabled temporarily because of Ractor. https://github.com/ruby/ruby/blob/c881678cd75432f47903a5d1d8b86a7a723cb023/compile.c#L8647-L8648 ``` // TODO: Ractor can not use cached Range objects if (0 && optimizable_range_item_p(b) && optimizable_range_item_p(e)) { ``` As #15504 was accepted, now can we remove this restriction? @ko1 ---------------------------------------- Bug #17209: String#slice allocates Range object in ruby 3.0.0preview1 https://bugs.ruby-lang.org/issues/17209#change-87856 * Author: bruno.escherl@xing.com (Bruno Escherl) * Status: Assigned * Priority: Normal * Assignee: ko1 (Koichi Sasada) * ruby -v: ruby 3.0.0preview1 (2020-09-25 master 0096d2b895) [x86_64-darwin19] * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN ---------------------------------------- While trying to optimise a use case, where I need to get parts of a string extracted, ignoring a constant length prefix, I noticed that ruby 3.0.0preview1 allocates an additional Range object for String#slice, that ruby 2.7.1 didn't allocate. Test script using memory_profiler gem: ``` ruby require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'memory_profiler' end string = 'const:prefix:and:the:rest' MemoryProfiler.report do 10000.times do string.slice(13..-1) end end.pretty_print ``` Output for ruby 3.0.0preview1 ``` Total allocated: 800000 bytes (20000 objects) Total retained: 0 bytes (0 objects) allocated memory by gem ----------------------------------- 800000 other allocated memory by file ----------------------------------- 800000 profile_string_slice.rb allocated memory by location ----------------------------------- 800000 profile_string_slice.rb:12 allocated memory by class ----------------------------------- 400000 Range 400000 String allocated objects by gem ----------------------------------- 20000 other allocated objects by file ----------------------------------- 20000 profile_string_slice.rb allocated objects by location ----------------------------------- 20000 profile_string_slice.rb:12 allocated objects by class ----------------------------------- 10000 Range 10000 String ``` Output for ruby 2.7.1 ``` Total allocated: 400000 bytes (10000 objects) Total retained: 0 bytes (0 objects) allocated memory by gem ----------------------------------- 400000 other allocated memory by file ----------------------------------- 400000 profile_string_slice.rb allocated memory by location ----------------------------------- 400000 profile_string_slice.rb:12 allocated memory by class ----------------------------------- 400000 String allocated objects by gem ----------------------------------- 10000 other allocated objects by file ----------------------------------- 10000 profile_string_slice.rb allocated objects by location ----------------------------------- 10000 profile_string_slice.rb:12 allocated objects by class ----------------------------------- 10000 String ``` Is this a regression in ruby 3 or something that memory_profiler doesn't record correctly in 2.7? -- https://bugs.ruby-lang.org/ Unsubscribe: