From: "k0kubun (Takashi Kokubun)" Date: 2021-11-10T08:07:10+00:00 Subject: [ruby-core:105999] [Ruby master Bug#18293] Time.at in master branch was 25% slower then Ruby 3.0 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: #: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[ 6] subsec@1[ 5] unit@2[ 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 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: #: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 [ 2] exception@1[ 1] ?@2 0000 opt_invokebuiltin_delegate_leave , 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: #: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[ 4] subsec@1[ 3] unit@2[ 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 , 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: