Project

General

Profile

Bug #15118

Updated by chopraanmol1 (Anmol Chopra) over 2 years ago

Calling ["something"] on object or proc (non-hash aref implementation) does not respect frozen_string_literal: true comment 

 **Script:** 

 ~~~ 
 # frozen_string_literal: true 

 require 'benchmark' 
 require 'memory_profiler' 
 class NopId 
   def self.[](str) 
     str.__id__ 
   end 
 end 

 SampleHash = {"sometext" => 0} 

 NopProc = proc{|a| a.__id__} 

 N = 1_000_000 

 def method1 
   NopId["sometext"] 
 end 

 def method2 
   SampleHash["sometext"] 
 end 

 def method3 
   NopProc["sometext"] 
 end 

 def print_iseq method_name 
   puts "-+"*20 
   puts RubyVM::InstructionSequence.disasm method(method_name) 
   puts "-+"*20 
 end 

 def print_memory_profiler title, &block 
   puts "-+"*20 
   puts title 
   MemoryProfiler.report{N.times(&block)}.pretty_print(detailed_report: false, allocated_strings: 0, retained_strings: 0) 
   puts "-+"*20 
 end 


 print_iseq :method1 
 print_iseq :method2 
 print_iseq :method3 

 Benchmark.bm(10) do |bm| 
   bm.report("method[]"){ N.times{ method1 } } 
   bm.report("hash[]"){ N.times{ method2 } } 
   bm.report("proc[]"){ N.times{ method3 } } 
 end 

 print_memory_profiler("method[]"){method1} 
 print_memory_profiler("hash[]"){method2} 
 print_memory_profiler("proc[]"){method3} 
 ~~~ 

 **Output:** 

 ~~~ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method1@../test_aref.rb:17 (17,0)-(19,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    18)[LiCa] 
 0003 getconstant                    :NopId 
 0005 setinlinecache                 <is:0> 
 0007 opt_aref_with                  "sometext", <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0011 leave                                                              (    19)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method2@../test_aref.rb:21 (21,0)-(23,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    22)[LiCa] 
 0003 getconstant                    :SampleHash 
 0005 setinlinecache                 <is:0> 
 0007 opt_aref_with                  "sometext", <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0011 leave                                                              (    23)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method3@../test_aref.rb:25 (25,0)-(27,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    26)[LiCa] 
 0003 getconstant                    :NopProc 
 0005 setinlinecache                 <is:0> 
 0007 opt_aref_with                  "sometext", <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0011 leave                                                              (    27)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
                  user       system        total          real 
 method[]       0.120000     0.000000     0.120000 (    0.121639) 
 hash[]         0.088000     0.000000     0.088000 (    0.089411) 
 proc[]         0.136000     0.000000     0.136000 (    0.133279) 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 method[] 
 Total allocated: 40000000 bytes (1000000 objects) 
 Total retained:    0 bytes (0 objects) 


 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 hash[] 
 Total allocated: 0 bytes (0 objects) 
 Total retained:    0 bytes (0 objects) 


 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 proc[] 
 Total allocated: 40000000 bytes (1000000 objects) 
 Total retained:    0 bytes (0 objects) 


 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 ~~~ 

 As you can observe calling NopClass["something"] & NopProc["something"] doesnot respect frozen_string_literal: true comment 

 **Patch:** 
 **https://github.com/ruby/ruby/pull/1957** 

 **After Patch Result:** 

 ~~~ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method1@../test_aref.rb:17 (17,0)-(19,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    18)[LiCa] 
 0003 getconstant                    :NopId 
 0005 setinlinecache                 <is:0> 
 0007 putobject                      "sometext" 
 0009 opt_aref                       <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0012 leave                                                              (    19)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method2@../test_aref.rb:21 (21,0)-(23,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    22)[LiCa] 
 0003 getconstant                    :SampleHash 
 0005 setinlinecache                 <is:0> 
 0007 putobject                      "sometext" 
 0009 opt_aref                       <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0012 leave                                                              (    23)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method3@../test_aref.rb:25 (25,0)-(27,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    26)[LiCa] 
 0003 getconstant                    :NopProc 
 0005 setinlinecache                 <is:0> 
 0007 putobject                      "sometext" 
 0009 opt_aref                       <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0012 leave                                                              (    27)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
                  user       system        total          real 
 method[]       0.100000     0.004000     0.104000 (    0.100786) 
 hash[]         0.088000     0.000000     0.088000 (    0.089176) 
 proc[]         0.108000     0.000000     0.108000 (    0.107366) 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 method[] 
 Total allocated: 0 bytes (0 objects) 
 Total retained:    0 bytes (0 objects) 


 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 hash[] 
 Total allocated: 0 bytes (0 objects) 
 Total retained:    0 bytes (0 objects) 


 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 proc[] 
 Total allocated: 0 bytes (0 objects) 
 Total retained:    0 bytes (0 objects) 


 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 ~~~

Back