Skip to content
This repository has been archived by the owner on Jan 1, 2024. It is now read-only.

Allocation performance is *terrible* under JRuby when UUID.state_file = false #19

Closed
chuckremes opened this issue Dec 28, 2011 · 8 comments

Comments

@chuckremes
Copy link


Chuck-Remess-Mac-Pro:perf cremes$ ruby uuid_bench.rb 
Rehearsal -------------------------------------------------------------------------
class allocation:                      59.914000   0.000000  59.914000 ( 59.914000)
uuid generation:                        0.020000   0.000000   0.020000 (  0.020000)
--------------------------------------------------------------- total: 59.934000sec

                                            user     system      total        real
class allocation:                      59.310000   0.000000  59.310000 ( 59.310000)
uuid generation:                        0.013000   0.000000   0.013000 (  0.013000)
Chuck-Remess-Mac-Pro:perf cremes$ ruby -v
jruby 1.7.0.dev (ruby-1.8.7-p352) (2011-12-19 f404f75) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_29) [darwin-x86_64-java]
Chuck-Remess-Mac-Pro:perf cremes$ rvm system
Chuck-Remess-Mac-Pro:perf cremes$ ruby uuid_bench.rb 
Rehearsal -------------------------------------------------------------------------
class allocation:                       0.003916   0.000361   0.004277 (  0.004240)
uuid generation:                        0.005223   0.000498   0.005721 (  0.005720)
---------------------------------------------------------------- total: 0.009998sec

                                            user     system      total        real
class allocation:                       0.003570   0.000199   0.003769 (  0.003759)
uuid generation:                        0.003729   0.000237   0.003966 (  0.003967)
Chuck-Remess-Mac-Pro:perf cremes$ ruby -v
rubinius 2.0.0dev (1.8.7 964a1a2b yyyy-mm-dd JI) [x86_64-apple-darwin10.8.0]

Generated by code:

# Test the performance of creating UUID instances and generating
# UUID values.
#

require 'rubygems'
require 'benchmark'
require 'uuid'
UUID.state_file = false

class Bar1

  def alloc_it
    UUID.new
  end
end # Bar1

class Bar2
  def initialize
    @uuid = UUID.new
  end

  def alloc_it
    @uuid.generate
  end
end

@bar1 = Bar1.new
@bar2 = Bar2.new

Iterations = 100

Benchmark.bmbm("Compare UUID allocation and generation".size) do |x|
  x.report("class allocation:") do
    Iterations.times { @bar1.alloc_it }
  end

  x.report("uuid generation:") do
    Iterations.times { @bar2.alloc_it }
  end

end
@chuckremes
Copy link
Author

When I profile this, all of the time was in systemu which is a dependency for macaddr.

@assaf
Copy link
Owner

assaf commented Dec 28, 2011

This gem is designed to generate UUID as fast as possible. It is not designed to generate UUID generators very fast. The common case application only uses one UUID generator.

@assaf assaf closed this as completed Dec 28, 2011
@chuckremes
Copy link
Author

Would you accept a patch that adds a class method (UUID.mac_address) that cached the system's MAC so new instantiations of the class didn't have to query the system interfaces for that (unchanging) information?

@assaf
Copy link
Owner

assaf commented Dec 28, 2011

Since an application is not supposed to generate many (most common, exactly one) classes, the performance difference would be unmeasurable. No amount of code is worth an unmeasurable gain.

@chuckremes
Copy link
Author

Pull request has been sent. The amount of code hasn't increased and all tests still pass. The performance is 100x better on JRuby.

I would appreciate it if you accepted the patch so I don't have to maintain my own fork.

@assaf
Copy link
Owner

assaf commented Dec 28, 2011

Performance has not improved for the case where one UUID object is necessary, and the case where you'll need to create 100 UUID objects still need to be explained.

@chuckremes
Copy link
Author

Performance for the singular case has not worsened either. With the current release version of the uuid gem (2.3.4), it takes approximately 1200 milliseconds for JRuby to allocate a single UUID instance with UUID.state_file=nil. That is entirely due to macaddr and its dependent gem systemu calling out to the system to retrieve the MAC address. Even for a single UUID object, that is ridiculous. My patch solves it.

Anyway, my use-case is as follows.

I have a distributed application comprised of hundreds of classes (it's a very big app). Many of these classes use UUID for a globally unique identifier to identify themselves as they pass messages around the network.

It is not reasonable for me to change method signatures so that a global "parent" object can allocate a singular UUID generator and then pass it around to all objects. Some objects are rather deeply nested in the system, so this would require intermediate objects (that have no use for a UUID generator) to save a reference to pass it along to the children objects.

I suppose I could use a global variable or a constant high in the namespace to hold it.

What do you suggest? My simple fix? Do you suggest that I move to a global or constant to satisfy the restrictions of your gem? Should I just fork it?

@assaf
Copy link
Owner

assaf commented Dec 29, 2011

Use UUID.generate. It guarantees you won't get duplicate UUIDs.

Avoid generating many UUID objects. You're going to run into all sorts of issues, including duplicate UUIDs.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants