Project

General

Profile

Feature #17135

Improve performance of Integer#size method

Added by S_H_ (Shun Hiraoka) about 2 months ago. Updated 23 days ago.

Status:
Assigned
Priority:
Normal
Target version:
-
[ruby-core:99779]

Description

Integer#size seems to show improved performance when written in ruby.

benchmark:

prelude: |
  n = 42
benchmark:
  size: |
    n.size
loop_count: 20000000

result:

sh@MyComputer:~/rubydev/build$ make benchmark/integer_size.yml -e COMPARE_RUBY=~/.rbenv/shims/ruby -e BENCH_RUBY=../install/bin/ruby
# Iteration per second (i/s)

|      |compare-ruby|built-ruby|
|:-----|-----------:|---------:|
|size  |     65.749M|   87.117M|
|      |           -|     1.33x|

COMPARE_RUBY is ruby 2.8.0dev (2020-08-28T10:47:29Z master 7e1fddba4a) [x86_64-linux]. BENCH_RUBY is patched.

pull request:
https://github.com/ruby/ruby/pull/3476

#1

Updated by S_H_ (Shun Hiraoka) about 2 months ago

  • Description updated (diff)
#2

Updated by sawa (Tsuyoshi Sawada) about 2 months ago

  • Description updated (diff)
  • Subject changed from Improve perfomance for Integer#size method to Improve performance of Integer#size method

Updated by shyouhei (Shyouhei Urabe) about 2 months ago

  • Assignee set to ko1 (Koichi Sasada)
  • Status changed from Open to Assigned

The patch looks good to me. HOWEVER, let me -1 this.
Integer#size HAS to be as fast as what is proposed here, without any extra hustle like this.
ko1 (Koichi Sasada) any idea what is preventing it from running smoothly?

Updated by S_H_ (Shun Hiraoka) about 1 month ago

I try to improve performance of Integer#size in C code with refer to TrueClass#to_s

static VALUE rb_cInteger_fix_size;

static VALUE
int_size (VALUE num)
{
    if (FIXNUM_P (num)) {
return rb_cInteger_fix_size;
    }
    else if (RB_TYPE_P (num, T_BIGNUM)) {
return rb_big_size_m (num);
    }
    return Qnil;
}

void
Init_Numeric (void)
{
    rb_cInteger_fix_size = INT2FIX (sizeof (long));
    rb_gc_register_mark_object (rb_cInteger_fix_size);
    rb_define_method (rb_cInteger, "size", int_size, 0);
}

benchmark:

prelude: |
  n = 42
benchmark: benchmark:
  size: |
    n.size
loop_count: 20000000

result:

sh@MyComputer:~/rubydev/build$ make benchmark/benchmark.yml -e COMPARE_RUBY=~/.rbenv/shims/ruby -e BENCH_RUBY=../install/bin/ruby
# Iteration per second (i/s)

|      |compare-ruby|built-ruby|
|:-----|-----------:|---------:|
|size  |     56.456M|   75.074M|
|      |           -|     1.33x|

As a result, seems to be expected improve performance.

COMPARE_RUBY is ruby 3.0.0dev (2020-09-20T11:39:25Z master 84c4c7bec8) [x86_64-linux]. BENCH_RUBY is patched.

Updated by mrkn (Kenta Murata) 23 days ago

INT2FIX(sizeof(long) is a constant expression because INT2FIX is a constant inline function that only does some arithmetic operations. So, I guess you don't need to keep that value in rb_cInteger_fix_size global variable.

Updated by ko1 (Koichi Sasada) 23 days ago

shyouhei (Shyouhei Urabe) wrote in #note-3:

The patch looks good to me. HOWEVER, let me -1 this.
Integer#size HAS to be as fast as what is proposed here, without any extra hustle like this.
ko1 (Koichi Sasada) any idea what is preventing it from running smoothly?

what is the "extra hustle"?

Updated by shyouhei (Shyouhei Urabe) 23 days ago

ko1 (Koichi Sasada) wrote in #note-6:

shyouhei (Shyouhei Urabe) wrote in #note-3:

The patch looks good to me. HOWEVER, let me -1 this.
Integer#size HAS to be as fast as what is proposed here, without any extra hustle like this.
ko1 (Koichi Sasada) any idea what is preventing it from running smoothly?

what is the "extra hustle"?

The proposed patch is basically Primitive.cexpr! 'int_size(self)'. Why it must be faster than rb_define_method(rb_cInteger, "size", int_size, 0)? They should at least perform identically.

Also available in: Atom PDF