From ab881e31dca0b724145aceac7f65d485dab65fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lourens=20Naud=C3=A9?= Date: Fri, 15 May 2015 23:20:48 -0400 Subject: [PATCH] Implement Symbol.count as a much cheaper alternative to Symbol.all_symbols.size --- ChangeLog | 16 ++++++++++++++++ include/ruby/intern.h | 4 +++- string.c | 1 + symbol.c | 19 +++++++++++++++++++ test/ruby/test_parse.rb | 6 ------ test/ruby/test_symbol.rb | 12 ++++++++++++ 6 files changed, 51 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 19c5c82..b2fd3ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +Fri May 15 23:32:31 2015 Lourens Naudé + + * symbol.c (rb_sym_count): Implement `rb_sym_count` to expose the number of + Symbol table entries as a numeric value without having to rely on the very + slow `rb_sym_all_symbols` API. + + * include/ruby/intern.h (rb_sym_count): Expose `rb_sym_count` API. Move + `rb_sym_all_symbols` to a symbol.c specific section (does not live in parse.y + anymore) + + * string.c (Init_string): Implement Symbol.count + + * test/ruby/test_symbol.rb: Test for API addition. + + * test/ruby/test_parse.rb: Moved `test_all_symbols` to test/ruby/test_symbol.rb + Fri May 15 18:28:20 2015 Nobuyoshi Nakada * array.c (rb_ary_assoc, rb_ary_rassoc): [DOC] the result when key diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 127de00..2ecc982 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -632,7 +632,6 @@ VALUE rb_backref_get(void); void rb_backref_set(VALUE); VALUE rb_lastline_get(void); void rb_lastline_set(VALUE); -VALUE rb_sym_all_symbols(void); /* process.c */ void rb_last_status_set(int status, rb_pid_t pid); VALUE rb_last_status_get(void); @@ -786,6 +785,9 @@ long rb_str_offset(VALUE, long); size_t rb_str_capacity(VALUE); VALUE rb_str_ellipsize(VALUE, long); VALUE rb_str_scrub(VALUE, VALUE); +/* symbol.c */ +VALUE rb_sym_all_symbols(void); +VALUE rb_sym_count(void); #if defined(__GNUC__) && !defined(__PCC__) #define rb_str_new(str, len) __extension__ ( \ diff --git a/string.c b/string.c index 943c18c..2a0e3db 100644 --- a/string.c +++ b/string.c @@ -9234,6 +9234,7 @@ Init_String(void) rb_undef_alloc_func(rb_cSymbol); rb_undef_method(CLASS_OF(rb_cSymbol), "new"); rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in symbol.c */ + rb_define_singleton_method(rb_cSymbol, "count", rb_sym_count, 0); /* in symbol.c */ rb_define_method(rb_cSymbol, "==", sym_equal, 1); rb_define_method(rb_cSymbol, "===", sym_equal, 1); diff --git a/symbol.c b/symbol.c index 63064d3..07de8bd 100644 --- a/symbol.c +++ b/symbol.c @@ -847,6 +847,25 @@ rb_sym_all_symbols(void) return ary; } +/* + * call-seq: + * Symbol.count => integer + * + * Returns an integer value representing the size of Ruby's symbol table. + * + * Symbol.count #=> 903 + */ + +VALUE +rb_sym_count(void) +{ +#if SIZEOF_LONG == SIZEOF_VOIDP + return ULONG2NUM(global_symbols.str_sym->num_entries); +#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP + return ULL2NUM(global_symbols.str_sym->num_entries); +#endif +} + int rb_is_const_id(ID id) { diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 216cdc0..9f91125 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -846,12 +846,6 @@ def test_intern assert_equal(':"foo=="', "foo==".intern.inspect) end - def test_all_symbols - x = Symbol.all_symbols - assert_kind_of(Array, x) - assert_empty(x.reject {|s| s.is_a?(Symbol) }) - end - def test_is_class_id c = Class.new assert_raise(NameError) do diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index 0a055db..96f7c0c 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -12,6 +12,18 @@ def assert_eval_inspected(sym, valid = true) assert_nothing_raised(SyntaxError) {assert_equal(sym, eval(n))} end + def test_all_symbols + x = Symbol.all_symbols + assert_kind_of(Array, x) + assert_empty(x.reject {|s| s.is_a?(Symbol) }) + end + + def test_count + x = Symbol.count + assert_kind_of(Fixnum, x) + assert_equal x, Symbol.all_symbols.size + end + def test_inspect_invalid # 2) Symbol#inspect sometimes returns invalid symbol representations: assert_eval_inspected(:"!")