Project

General

Profile

Bug #15118

Updated by chopraanmol1 (Anmol Chopra) about 6 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 

   def self.[]=(str, val) 
     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 method4 
   NopId["sometext"] = 'othertext' 
 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 
 print_iseq :method4 

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

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

 **Output:** 

 ~~~ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method1@../test_aref.rb:21 (21,0)-(23,3)> #<ISeq:method1@../test_aref.rb:17 (17,0)-(19,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    22)[LiCa] 18)[LiCa] 
 0003 getconstant                    :NopId 
 0005 setinlinecache                 <is:0> 
 0007 opt_aref_with                  "sometext", <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0011 leave                                                              (    23)[Re] 19)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method2@../test_aref.rb:25 (25,0)-(27,3)> #<ISeq:method2@../test_aref.rb:21 (21,0)-(23,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    26)[LiCa] 22)[LiCa] 
 0003 getconstant                    :SampleHash 
 0005 setinlinecache                 <is:0> 
 0007 opt_aref_with                  "sometext", <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0011 leave                                                              (    27)[Re] 23)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method3@../test_aref.rb:29 (29,0)-(31,3)> #<ISeq:method3@../test_aref.rb:25 (25,0)-(27,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    30)[LiCa] 26)[LiCa] 
 0003 getconstant                    :NopProc 
 0005 setinlinecache                 <is:0> 
 0007 opt_aref_with                  "sometext", <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0011 leave                                                              (    31)[Re] 27)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method4@../test_aref.rb:33 (33,0)-(35,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    34)[LiCa] 
 0003 getconstant                    :NopId 
 0005 setinlinecache                 <is:0> 
 0007 putobject                      "othertext" 
 0009 swap 
 0010 topn                           1 
 0012 opt_aset_with                  "sometext", <callinfo!mid:[]=, argc:2, ARGS_SIMPLE>, <callcache> 
 0016 pop 
 0017 leave                                                              (    35)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
                  user       system        total          real 
 method[]       0.120000     0.004000 0.000000     0.124000 0.120000 (    0.121883) 0.121639) 
 hash[]         0.088000     0.000000     0.088000 (    0.088723) 0.089411) 
 proc[]         0.132000 0.136000     0.000000     0.132000 0.136000 (    0.133687) 0.133279) 
 method[]=      0.128000     0.000000     0.128000 (    0.126702) 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 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) 


 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 method[]= 
 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:21 (21,0)-(23,3)> #<ISeq:method1@../test_aref.rb:17 (17,0)-(19,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    22)[LiCa] 18)[LiCa] 
 0003 getconstant                    :NopId 
 0005 setinlinecache                 <is:0> 
 0007 putobject                      "sometext" 
 0009 opt_aref                       <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0012 leave                                                              (    23)[Re] 19)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method2@../test_aref.rb:25 (25,0)-(27,3)> #<ISeq:method2@../test_aref.rb:21 (21,0)-(23,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    26)[LiCa] 22)[LiCa] 
 0003 getconstant                    :SampleHash 
 0005 setinlinecache                 <is:0> 
 0007 putobject                      "sometext" 
 0009 opt_aref                       <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0012 leave                                                              (    27)[Re] 23)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method3@../test_aref.rb:29 (29,0)-(31,3)> #<ISeq:method3@../test_aref.rb:25 (25,0)-(27,3)> (catch: FALSE) 
 0000 getinlinecache                 7, <is:0>                             (    30)[LiCa] 26)[LiCa] 
 0003 getconstant                    :NopProc 
 0005 setinlinecache                 <is:0> 
 0007 putobject                      "sometext" 
 0009 opt_aref                       <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache> 
 0012 leave                                                              (    31)[Re] 27)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 == disasm: #<ISeq:method4@../test_aref.rb:33 (33,0)-(35,3)> (catch: FALSE) 
 0000 putnil                                                             (    34)[LiCa] 
 0001 getinlinecache                 8, <is:0> 
 0004 getconstant                    :NopId 
 0006 setinlinecache                 <is:0> 
 0008 putobject                      "sometext" 
 0010 putobject                      "othertext" 
 0012 setn                           3 
 0014 opt_aset                       <callinfo!mid:[]=, argc:2, ARGS_SIMPLE>, <callcache> 
 0017 pop 
 0018 leave                                                              (    35)[Re] 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
                  user       system        total          real 
 method[]       0.092000 0.100000     0.004000     0.096000 0.104000 (    0.094751) 0.100786) 
 hash[]         0.088000     0.000000     0.088000 (    0.087865) 0.089176) 
 proc[]         0.116000 0.108000     0.000000     0.116000 0.108000 (    0.117047) 0.107366) 
 method[]=      0.096000     0.000000     0.096000 (    0.096765) 
 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
 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) 


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


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

Back