Project

General

Profile

Bug #13519

Improve performance of some Time methods

Added by watson1978 (Shizuo Fujita) over 2 years ago. Updated about 2 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:80915]

Description

This is related to https://bugs.ruby-lang.org/issues/13503

Some Time methods will call internal quov() function and
quov() calls Numeric#quo -> Rational#quo -> ...

This patch will add rb_numeric_quo() as internal C API to call Numeric#quo directly.
And this will use rb_numeric_quo() instead of rb_funcall() for Numeric#quo to internal objects.

Time#- will be faster around 15%.

Before

Calculating -------------------------------------
         Time#subsec      2.029M (± 8.6%) i/s -     10.078M in   5.003036s
              Time#-      4.225M (± 2.1%) i/s -     21.130M in   5.003600s
           Time#to_f      5.580M (± 2.1%) i/s -     27.955M in   5.011881s
           Time#to_r      1.862M (± 9.8%) i/s -      9.253M in   5.016749s

After

Calculating -------------------------------------
         Time#subsec      2.196M (±10.7%) i/s -     10.879M in   5.010285s
              Time#-      4.991M (± 2.2%) i/s -     24.966M in   5.005041s
           Time#to_f      6.809M (±13.5%) i/s -     32.204M in   5.005536s
           Time#to_r      1.980M (± 9.6%) i/s -      9.854M in   5.020879s

Test code

require 'benchmark/ips'

Benchmark.ips do |x|
  x.report "Time#subsec" do |t|
    time = Time.now
    t.times { time.subsec }
  end

  x.report "Time#-" do |t|
    time1 = Time.now
    time2 = Time.now
    t.times { time1 - time2 }
  end

  x.report "Time#to_f" do |t|
    time = Time.now
    t.times { time.to_f }
  end

  x.report "Time#to_r" do |t|
    time = Time.now
    t.times { time.to_r }
  end
end

Patch

https://github.com/ruby/ruby/pull/1601

Associated revisions

Revision 6fcb76ed
Added by watson1978 (Shizuo Fujita) about 2 years ago

Improve performance of some Time methods

internal.h : add rb_numeric_quo() as internal API.
rational.c : rename numeric_quo() to rb_numeric_quo() as internal API.
time.c (quov): optimize by invoking rb_numeric_quo() to retrieve a value of
Numeric#quo instead of method dispatching via rb_funcall().

Time#subsec ->  7 % up
Time#-      -> 26 % up
Time#to_f   -> 30 % up
Time#to_r   ->  7 % up

[ruby-core:80915] [Bug #13519] [Fix GH-1601]

Before

     Time#subsec      2.024M (± 8.7%) i/s -     10.062M in   5.009762s
          Time#-      5.049M (± 4.7%) i/s -     25.186M in   5.002379s
       Time#to_f      5.625M (± 4.2%) i/s -     28.066M in   5.000749s
       Time#to_r      1.880M (± 9.7%) i/s -      9.361M in   5.027527s

After

     Time#subsec      2.155M (± 9.7%) i/s -     10.724M in   5.022579s
          Time#-      6.362M (± 2.0%) i/s -     31.824M in   5.004625s
       Time#to_f      7.287M (± 4.8%) i/s -     36.402M in   5.010983s
       Time#to_r      2.020M (± 9.4%) i/s -     10.059M in   5.021852s

Test code

require 'benchmark/ips'

Benchmark.ips do |x|
x.report "Time#subsec" do |t|
time = Time.now
t.times { time.subsec }
end

x.report "Time#-" do |t|
time1 = Time.now
time2 = Time.now
t.times { time1 - time2 }
end

x.report "Time#to_f" do |t|
time = Time.now
t.times { time.to_f }
end

x.report "Time#to_r" do |t|
time = Time.now
t.times { time.to_r }
end
end

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58921 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 58921
Added by watson1978 (Shizuo Fujita) about 2 years ago

Improve performance of some Time methods

internal.h : add rb_numeric_quo() as internal API.
rational.c : rename numeric_quo() to rb_numeric_quo() as internal API.
time.c (quov): optimize by invoking rb_numeric_quo() to retrieve a value of
Numeric#quo instead of method dispatching via rb_funcall().

Time#subsec ->  7 % up
Time#-      -> 26 % up
Time#to_f   -> 30 % up
Time#to_r   ->  7 % up

[ruby-core:80915] [Bug #13519] [Fix GH-1601]

Before

     Time#subsec      2.024M (± 8.7%) i/s -     10.062M in   5.009762s
          Time#-      5.049M (± 4.7%) i/s -     25.186M in   5.002379s
       Time#to_f      5.625M (± 4.2%) i/s -     28.066M in   5.000749s
       Time#to_r      1.880M (± 9.7%) i/s -      9.361M in   5.027527s

After

     Time#subsec      2.155M (± 9.7%) i/s -     10.724M in   5.022579s
          Time#-      6.362M (± 2.0%) i/s -     31.824M in   5.004625s
       Time#to_f      7.287M (± 4.8%) i/s -     36.402M in   5.010983s
       Time#to_r      2.020M (± 9.4%) i/s -     10.059M in   5.021852s

Test code

require 'benchmark/ips'

Benchmark.ips do |x|
x.report "Time#subsec" do |t|
time = Time.now
t.times { time.subsec }
end

x.report "Time#-" do |t|
time1 = Time.now
time2 = Time.now
t.times { time1 - time2 }
end

x.report "Time#to_f" do |t|
time = Time.now
t.times { time.to_f }
end

x.report "Time#to_r" do |t|
time = Time.now
t.times { time.to_r }
end
end

Revision 58921
Added by watson1978 (Shizuo Fujita) about 2 years ago

Improve performance of some Time methods

internal.h : add rb_numeric_quo() as internal API.
rational.c : rename numeric_quo() to rb_numeric_quo() as internal API.
time.c (quov): optimize by invoking rb_numeric_quo() to retrieve a value of
Numeric#quo instead of method dispatching via rb_funcall().

Time#subsec ->  7 % up
Time#-      -> 26 % up
Time#to_f   -> 30 % up
Time#to_r   ->  7 % up

[ruby-core:80915] [Bug #13519] [Fix GH-1601]

Before

     Time#subsec      2.024M (± 8.7%) i/s -     10.062M in   5.009762s
          Time#-      5.049M (± 4.7%) i/s -     25.186M in   5.002379s
       Time#to_f      5.625M (± 4.2%) i/s -     28.066M in   5.000749s
       Time#to_r      1.880M (± 9.7%) i/s -      9.361M in   5.027527s

After

     Time#subsec      2.155M (± 9.7%) i/s -     10.724M in   5.022579s
          Time#-      6.362M (± 2.0%) i/s -     31.824M in   5.004625s
       Time#to_f      7.287M (± 4.8%) i/s -     36.402M in   5.010983s
       Time#to_r      2.020M (± 9.4%) i/s -     10.059M in   5.021852s

Test code

require 'benchmark/ips'

Benchmark.ips do |x|
x.report "Time#subsec" do |t|
time = Time.now
t.times { time.subsec }
end

x.report "Time#-" do |t|
time1 = Time.now
time2 = Time.now
t.times { time1 - time2 }
end

x.report "Time#to_f" do |t|
time = Time.now
t.times { time.to_f }
end

x.report "Time#to_r" do |t|
time = Time.now
t.times { time.to_r }
end
end

Revision 58921
Added by watson1978 (Shizuo Fujita) about 2 years ago

Improve performance of some Time methods

internal.h : add rb_numeric_quo() as internal API.
rational.c : rename numeric_quo() to rb_numeric_quo() as internal API.
time.c (quov): optimize by invoking rb_numeric_quo() to retrieve a value of
Numeric#quo instead of method dispatching via rb_funcall().

Time#subsec ->  7 % up
Time#-      -> 26 % up
Time#to_f   -> 30 % up
Time#to_r   ->  7 % up

[ruby-core:80915] [Bug #13519] [Fix GH-1601]

Before

     Time#subsec      2.024M (± 8.7%) i/s -     10.062M in   5.009762s
          Time#-      5.049M (± 4.7%) i/s -     25.186M in   5.002379s
       Time#to_f      5.625M (± 4.2%) i/s -     28.066M in   5.000749s
       Time#to_r      1.880M (± 9.7%) i/s -      9.361M in   5.027527s

After

     Time#subsec      2.155M (± 9.7%) i/s -     10.724M in   5.022579s
          Time#-      6.362M (± 2.0%) i/s -     31.824M in   5.004625s
       Time#to_f      7.287M (± 4.8%) i/s -     36.402M in   5.010983s
       Time#to_r      2.020M (± 9.4%) i/s -     10.059M in   5.021852s

Test code

require 'benchmark/ips'

Benchmark.ips do |x|
x.report "Time#subsec" do |t|
time = Time.now
t.times { time.subsec }
end

x.report "Time#-" do |t|
time1 = Time.now
time2 = Time.now
t.times { time1 - time2 }
end

x.report "Time#to_f" do |t|
time = Time.now
t.times { time.to_f }
end

x.report "Time#to_r" do |t|
time = Time.now
t.times { time.to_r }
end
end

History

Updated by normalperson (Eric Wong) over 2 years ago

watson1978@gmail.com wrote:

Bug #13519: Improve performance of some Time methods
https://bugs.ruby-lang.org/issues/13519

Some Time methods will call internal quov() function and
quov() calls Numeric#quo -> Rational#quo -> ...

This patch will add rb_numeric_quo() as internal C API to call Numeric#quo directly.
And this will use rb_numeric_quo() instead of rb_funcall() for Numeric#quo to internal objects.

I guess this is OK...

I notice this change; along with many similar optimizations in
time.c such as r54218, r54203, ... do not check method
redefinition flags on Integer.

Are we OK with this? (I am)

I guess 2.4 was released with some of these changes;
and nobody complained so far...

Can we disable/disallow redefinition of more methods? :)

#2

Updated by watson1978 (Shizuo Fujita) about 2 years ago

  • Status changed from Open to Closed

Applied in changeset trunk|r58921.


Improve performance of some Time methods

internal.h : add rb_numeric_quo() as internal API.
rational.c : rename numeric_quo() to rb_numeric_quo() as internal API.
time.c (quov): optimize by invoking rb_numeric_quo() to retrieve a value of
Numeric#quo instead of method dispatching via rb_funcall().

Time#subsec ->  7 % up
Time#-      -> 26 % up
Time#to_f   -> 30 % up
Time#to_r   ->  7 % up

[ruby-core:80915] [Bug #13519] [Fix GH-1601]

Before

     Time#subsec      2.024M (± 8.7%) i/s -     10.062M in   5.009762s
          Time#-      5.049M (± 4.7%) i/s -     25.186M in   5.002379s
       Time#to_f      5.625M (± 4.2%) i/s -     28.066M in   5.000749s
       Time#to_r      1.880M (± 9.7%) i/s -      9.361M in   5.027527s

After

     Time#subsec      2.155M (± 9.7%) i/s -     10.724M in   5.022579s
          Time#-      6.362M (± 2.0%) i/s -     31.824M in   5.004625s
       Time#to_f      7.287M (± 4.8%) i/s -     36.402M in   5.010983s
       Time#to_r      2.020M (± 9.4%) i/s -     10.059M in   5.021852s

Test code

require 'benchmark/ips'

Benchmark.ips do |x|
x.report "Time#subsec" do |t|
time = Time.now
t.times { time.subsec }
end

x.report "Time#-" do |t|
time1 = Time.now
time2 = Time.now
t.times { time1 - time2 }
end

x.report "Time#to_f" do |t|
time = Time.now
t.times { time.to_f }
end

x.report "Time#to_r" do |t|
time = Time.now
t.times { time.to_r }
end
end

Also available in: Atom PDF