Project

General

Profile

Feature #15331 » 0001-Hash-code-memoization-for-short-fstrings-v2.patch

alanwu (Alan Wu), 11/23/2018 06:42 PM

View differences:

benchmark/freeze_unique_strings.yml
prelude: |
str = +"1000000"
benchmark:
freeze_unique_strings: |
str.succ!
-str
loop_count: 1000000 # freeze this many unique strings
benchmark/hash_aref_fstr.rb
h = {}
strs = ('a'..'z').to_a.map!(&:-@)
strs.each { |s| h[s] = s }
200_000.times { strs.each { |s| h[s] } }
benchmark/hash_aref_long_str.rb
h = {}
strs = ['a' * 100] * 10
strs.each { |s| h[s] = s }
200_000.times { strs.each { |s| h[s] } }
string.c
RBASIC(str)->flags |= (tmp_n) << RSTRING_EMBED_LEN_SHIFT;\
} while (0)
#define MEMO_HASH_LEN_MAX (int)(sizeof(((struct RString*)0)->as) - sizeof(st_index_t) - 1)
struct memoized_hash_embeded_str {
char ary[MEMO_HASH_LEN_MAX + 1];
st_index_t memoized_hash;
};
STATIC_ASSERT(memoized_hash_type_punning, sizeof(struct memoized_hash_embeded_str) == sizeof(((struct RString*)0)->as));
#define SET_HASH_MEMO(str, hash) do { \
struct RString *rstr = (struct RString*) (str);\
((struct memoized_hash_embeded_str*) &rstr->as)->memoized_hash = hash;\
} while (0)
#define GET_HASH_MEMO(str) (((struct memoized_hash_embeded_str*) &(((struct RString*) (str))->as))->memoized_hash)
#define CAN_MEMO_HASH(str) \
(RB_FL_TEST_RAW((str), RSTRING_NOEMBED | RUBY_FL_FREEZE) == RUBY_FL_FREEZE && RSTRING_EMBED_LEN(str) <= MEMO_HASH_LEN_MAX)
#define STR_SET_LEN(str, n) do { \
if (STR_EMBED_P(str)) {\
STR_SET_EMBED_LEN((str), (n));\
......
str = str_new_frozen(rb_cString, str);
}
}
if (CAN_MEMO_HASH(str)) {
SET_HASH_MEMO(str, rb_str_hash(str));
}
RBASIC(str)->flags |= RSTRING_FSTR;
*key = *value = *fstr = str;
......
st_index_t
rb_str_hash(VALUE str)
{
if (FL_TEST(str, RSTRING_FSTR) && CAN_MEMO_HASH(str)) {
return GET_HASH_MEMO(str);
}
int e = ENCODING_GET(str);
if (e && rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
e = 0;
(3-3/8)