Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ractor makes much slower when using in ULID.sample 😄 #120

Closed
kachick opened this issue May 8, 2021 · 2 comments
Closed

Ractor makes much slower when using in ULID.sample 😄 #120

kachick opened this issue May 8, 2021 · 2 comments
Labels
development offtopic performance Optimized for performance question Further information is requested

Comments

@kachick
Copy link
Owner

kachick commented May 8, 2021

$ ruby -v
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin20]

This is the current code

ruby-ulid/lib/ulid.rb

Lines 73 to 118 in e6c5d11

# @param [Range<Time>, Range<nil>, Range[ULID], nil] period
# @overload sample(number, period: nil)
# @param [Integer] number
# @return [Array<ULID>]
# @raise [ArgumentError] if the given number is lager than `ULID spec limits` or `Possibilities of given period`, or given negative number
# @overload sample(period: nil)
# @return [ULID]
# @note Major difference of `Array#sample` interface is below
# * Do not ensure the uniqueness
# * Do not take random generator for the arguments
# * Raising error instead of truncating elements for the given number
def self.sample(*args, period: nil)
int_generator = if period
ulid_range = range(period)
min, max, exclude_end = ulid_range.begin.to_i, ulid_range.end.to_i, ulid_range.exclude_end?
possibilities = (max - min) + (exclude_end ? 0 : 1)
raise ArgumentError, "given range `#{ulid_range.inspect}` does not have possibilities" unless possibilities.positive?
-> {
SecureRandom.random_number(possibilities) + min
}
else
RANDOM_INTEGER_GENERATOR
end
case args.size
when 0
from_integer(int_generator.call)
when 1
number = args.first
raise ArgumentError, 'accepts no argument or integer only' unless Integer === number
if number > MAX_INTEGER || number.negative?
raise ArgumentError, "given number #{number} is larger than ULID limit #{MAX_INTEGER} or negative: #{number.inspect}"
end
if period && (number > possibilities)
raise ArgumentError, "given number #{number} is larger than given possibilities #{possibilities}"
end
Array.new(number) { from_integer(int_generator.call) }
else
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0..1)"
end
end

AFAIK, Proc can't be passed.

irb(main):012:0> Ractor.new(->{}) {}
<internal:ractor>:267:in `new': allocator undefined for Proc (TypeError)

And using constants makes slower, written in https://techlife.cookpad.com/entry/2020/12/26/131858

So I have just experiment to use Ractor with following code.

      ractors = Array.new(number) do
        Ractor.new(self, MAX_INTEGER, SecureRandom) do |klass, max_int, rng|
          klass.from_integer(rng.random_number(max_int))
        end
      end
      ractors.map(&:take)

The products looks okay, but much slower.

irb(main):004:0> ULID.sample_old(10000); nil
processing time: 0.161876s
irb(main):005:0> ULID.sample(10000); nil #=> Stack!
^C/Users/kachick/.rubies/ruby-3.0.1/lib/ruby/3.0.0/irb.rb:427:in `raise': abort then interrupt! (IRB::Abort) 

irb(main):007:0> ULID.sample_old(100); nil
processing time: 0.065385s
irb(main):008:0> ULID.sample(100); nil
processing time: 1.370176s

ref: https://github.com/ruby/ruby/blob/e3e55967826668dcf6f04c550cab5ef8df71fdb7/doc/ractor.md

@kachick
Copy link
Owner Author

kachick commented May 20, 2022

This issue is just a note.

@kachick
Copy link
Owner Author

kachick commented Jul 2, 2022

💭 Generating 10000 ractos sounds 👿

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
development offtopic performance Optimized for performance question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant