Feature #15331 » 0001-Hash-code-memoization-for-short-fstrings-v4.patch
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(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(RSTRING(0)->as));
|
||
#define SET_HASH_MEMO(str, hash) do { \
|
||
struct RString *rstr = RSTRING(str);\
|
||
((struct memoized_hash_embeded_str*) &rstr->as)->memoized_hash = hash;\
|
||
} while (0)
|
||
#define GET_HASH_MEMO(str) (((struct memoized_hash_embeded_str*) &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)
|
||
{
|
||
int e = ENCODING_GET(str);
|
||
int e;
|
||
if (FL_TEST(str, RSTRING_FSTR) && CAN_MEMO_HASH(str)) {
|
||
return GET_HASH_MEMO(str);
|
||
}
|
||
e = ENCODING_GET(str);
|
||
if (e && rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
|
||
e = 0;
|
||
}
|