Issue #18293 has been updated by k0kubun (Takashi Kokubun).


FYI, the current iseq is:

```
irb(main)[01:0]> puts RubyVM::InstructionSequence.of(Time.method(:at)).disasm
== disasm: #<ISeq:at@<internal:timev>:270 (270,2)-(272,5)> (catch: FALSE)
local table (size: 7, argc: 1 [opts: 2, rest: -1, post: 0, block: -1, kw: 1@0, kwrest: -1])
[ 7] time@0<Arg>[ 6] subsec@1<Opt=0>[ 5] unit@2<Opt=7>[ 4] in@3       [ 3] ?@4        [ 2] nosubsec@5 [ 1] nounit@6
0000 putobject                              true                      ( 270)[Li]
0002 dup
0003 setlocal_WC_0                          nosubsec@5
0005 setlocal_WC_0                          subsec@1
0007 putobject                              true
0009 dup
0010 setlocal_WC_0                          nounit@6
0012 setlocal_WC_0                          unit@2
0014 getlocal_WC_0                          time@0                    ( 271)[LiCa]
0016 getlocal_WC_0                          subsec@1
0018 getlocal_WC_0                          unit@2
0020 getlocal_WC_0                          in@3
0022 getlocal_WC_0                          nosubsec@5
0024 getlocal_WC_0                          nounit@6
0026 invokebuiltin                          <builtin!time_s_at/6>
0028 leave                                                            ( 272)[Re]
```

obviously this would be slower than things like:

```
irb(main)[02:0]> puts RubyVM::InstructionSequence.of(Kernel.method(:Float)).disasm
== disasm: #<ISeq:Float@<internal:kernel>:171 (171,2)-(173,5)> (catch: FALSE)
local table (size: 3, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: 1@0, kwrest: -1])
[ 3] arg@0<Arg> [ 2] exception@1[ 1] ?@2
0000 opt_invokebuiltin_delegate_leave       <builtin!rb_f_float/2>, 0 ( 172)[LiCa]
0003 leave                                                            ( 173)[Re]
```

> I don't understand why we need to detect wether the parameters were passed, why can't we just have default values?

I'm not aware of that, but if we can eliminate `nosubsec` and `nounit` local variables, we could convert `invokebuiltin` to `opt_invokebuiltin_delegate_leave` and I guess that would be a large improvement. It would then look like:

```
== disasm: #<ISeq:at@<internal:timev>:274 (274,2)-(276,5)> (catch: FALSE)
local table (size: 5, argc: 1 [opts: 2, rest: -1, post: 0, block: -1, kw: 1@0, kwrest: -1])
[ 5] time@0<Arg>[ 4] subsec@1<Opt=0>[ 3] unit@2<Opt=4>[ 2] in@3       [ 1] ?@4
0000 putobject                              true                      ( 274)
0002 setlocal_WC_0                          subsec@1
0004 putobject                              true
0006 setlocal_WC_0                          unit@2
0008 opt_invokebuiltin_delegate_leave       <builtin!time_s_at2/4>, 0 ( 275)[LiCa]
0011 leave                                                            ( 276)[Re]
```

It'd be nice if we can eliminate `setlocal` for `subsec` and `unit` as well, but it seems inevitable as long as you use positional arguments with default values.

----------------------------------------
Bug #18293: Time.at in master branch was 25% slower then Ruby 3.0
https://bugs.ruby-lang.org/issues/18293#change-94545

* Author: watson1978 (Shizuo Fujita)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.1.0dev (2021-11-08T13:15:21Z master bd2674ad33) [arm64-darwin21]
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN
----------------------------------------
       | Ruby 3.0.2 | Ruby 3.1.0-dev | result
--       | --         | --             | --
Time.at  | 8.223M     | 6.190M         | 0.753x

### Environment
- MacBook Pro (14inch, 2021)
- macOS 12.0
- Apple M1 Max
- Apple clang version 13.0.0 (clang-1300.0.29.3)

### Ruby 3.1.0-dev
```
$ ruby -v time.rb
ruby 3.1.0dev (2021-11-08T13:15:21Z master bd2674ad33) [arm64-darwin21]
Warming up --------------------------------------
             Time.at   614.843k i/100ms
Calculating -------------------------------------
             Time.at      6.190M ( 0.3%) i/s -     31.357M in   5.065559s
```

### Ruby 3.0.2
```
$ ruby -v time.rb
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [arm64-darwin21]
Warming up --------------------------------------
             Time.at   821.722k i/100ms
Calculating -------------------------------------
             Time.at      8.223M ( 0.6%) i/s -     41.908M in   5.096820s
```

### Test code
```ruby
require 'benchmark/ips'

Benchmark.ips do |x|
  x.report('Time.at') { Time.at(0) }
end
```

---Files--------------------------------
patch.diff (2.52 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>