Feature #15251
Updated by chopraanmol1 (Anmol Chopra) about 6 years ago
I'm not sure if current behavior is expected one or a bug. So feel fell free to change tracker type. Currently Hash ASET checks if non-tainted string exists in fstring table or not, if it doesn't then ruby duplicates string and freeze it. This works well for string_literal because they are already registered in fstring table, but it doesn't work for non-literal string. Patch https://github.com/ruby/ruby/pull/1993 O/P of attached file(test_hash_keys_deduped.rb) file on trunk: ~~~ string_literal => 1 string times 1 => 1 string times 3 string times 3 string times 3 => 100 interpolated_string => 100 string add => 100 string append => 100 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ fstring -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ string_literal => 1 string times 1 => 1 string times 3 string times 3 string times 3 => 1 interpolated_string => 1 string add => 1 string append => 1 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ fstring + GC -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ string_literal => 1 string times 1 => 1 string times 3 string times 3 string times 3 => 100 interpolated_string => 100 string add => 100 string append => 100 ~~~ after patch ~~~ string_literal => 1 string times 1 => 1 string times 3 string times 3 string times 3 => 1 interpolated_string => 1 string add => 1 string append => 1 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ fstring -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ string_literal => 1 string times 1 => 1 string times 3 string times 3 string times 3 => 1 interpolated_string => 1 string add => 1 string append => 1 -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ fstring + GC -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ string_literal => 1 string times 1 => 1 string times 3 string times 3 string times 3 => 1 interpolated_string => 1 string add => 1 string append => 1 ~~~ Benchmark result(bench_hash_aset.rb): Trunk: ~~~ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`string literal`.dup]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0.880000 0.000000 0.880000 ( 0.880699) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`string non-literal`.dup]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0.980000 0.000000 0.980000 ( 0.978089) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`random text`]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 3.716000 0.004000 3.720000 ( 3.722688) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`string literal`.dup]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0.868000 0.000000 0.868000 ( 0.868405) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`string non-literal`.dup]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0.948000 0.000000 0.948000 ( 0.948946) ~~~ Patched: ~~~ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`string literal`.dup]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0.872000 0.000000 0.872000 ( 0.872410) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`string non-literal`.dup]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0.864000 0.000000 0.864000 ( 0.865356) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`random text`]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 3.780000 0.000000 3.780000 ( 3.779730) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`string literal`.dup]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0.868000 0.000000 0.868000 ( 0.867957) -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Hash#[`string non-literal`.dup]= -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0.872000 0.000000 0.872000 ( 0.873573) ~~~