symbol.h: memoize hashval for RSymbol

This speeds up the hash function for dynamic symbols.
[ruby-core:70129] [Bug #11396], nearly up to Ruby 2.1 levels

Power-of-two hash sizing [Feature #9425] speeds up cases where we
have a good hash, but this means we can no longer hide behind weak
hashes.  Unfortunately, object IDs do not hash well, but we may
use the extra space in the RSymbol struct to memoize the hash value.

Further optimizations should be possible.  For now, the st.c APIs
force us to calculate rb_str_hash redundantly at dsym registration.

* symbol.h (struct RSymbol): add hashval field
* symbol.c (dsymbol_alloc): setup hashval field once
* hash.c (rb_any_hash): return RSymbol->hashval directly
* common.mk: hash.o depends on symbol.h
  Thanks to Bruno Escherl <bruno@escherl.net> for the bug report
  [ruby-core:70129] [Bug #11396]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51410 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
normal 2015-07-27 22:25:30 +00:00
Родитель dc9ca079bb
Коммит 442b77e721
5 изменённых файлов: 19 добавлений и 1 удалений

Просмотреть файл

@ -1,3 +1,12 @@
Tue Jul 28 07:23:03 2015 Eric Wong <e@80x24.org>
* symbol.h (struct RSymbol): add hashval field
* symbol.c (dsymbol_alloc): setup hashval field once
* hash.c (rb_any_hash): return RSymbol->hashval directly
* common.mk: hash.o depends on symbol.h
Thanks to Bruno Escherl <bruno@escherl.net> for the bug report
[ruby-core:70129] [Bug #11396]
Tue Jul 28 03:26:15 2015 Aaron Patterson <tenderlove@ruby-lang.org>
* ext/openssl/lib/openssl/ssl.rb (module OpenSSL): raise a more

Просмотреть файл

@ -1532,6 +1532,7 @@ hash.$(OBJEXT): {$(VPATH)}oniguruma.h
hash.$(OBJEXT): {$(VPATH)}probes.h
hash.$(OBJEXT): {$(VPATH)}st.h
hash.$(OBJEXT): {$(VPATH)}subst.h
hash.$(OBJEXT): {$(VPATH)}symbol.h
hash.$(OBJEXT): {$(VPATH)}util.h
hash.$(OBJEXT): {$(VPATH)}vm_opts.h
inits.$(OBJEXT): $(hdrdir)/ruby/ruby.h

3
hash.c
Просмотреть файл

@ -17,6 +17,7 @@
#include <errno.h>
#include "probes.h"
#include "id.h"
#include "symbol.h"
#ifdef __APPLE__
# ifdef HAVE_CRT_EXTERNS_H
@ -149,7 +150,7 @@ rb_any_hash(VALUE a)
hnum = rb_str_hash(a);
}
else if (BUILTIN_TYPE(a) == T_SYMBOL) {
hnum = rb_objid_hash((st_index_t)a);
return RSYMBOL(a)->hashval;
}
else if (BUILTIN_TYPE(a) == T_FLOAT) {
return rb_dbl_hash(rb_float_value(a));

Просмотреть файл

@ -505,12 +505,18 @@ static VALUE
dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type)
{
const VALUE dsym = rb_newobj_of(klass, T_SYMBOL | FL_WB_PROTECTED);
st_index_t hashval;
rb_enc_associate(dsym, enc);
OBJ_FREEZE(dsym);
RB_OBJ_WRITE(dsym, &RSYMBOL(dsym)->fstr, str);
RSYMBOL(dsym)->id = type;
/* we want hashval to be in Fixnum range [ruby-core:15713] r15672 */
hashval = rb_str_hash(str);
hashval <<= 1;
RSYMBOL(dsym)->hashval = (st_index_t)RSHIFT(hashval, 1);
register_sym(str, dsym);
rb_hash_aset(global_symbols.dsymbol_fstr_hash, str, Qtrue);

Просмотреть файл

@ -25,6 +25,7 @@
struct RSymbol {
struct RBasic basic;
st_index_t hashval;
VALUE fstr;
ID id;
};