A
ara.t.howard
Raising an error might be a better way to ensure people don't run
code without ObjectSpace enabled, certainly. But maybe they don't
care?
they care.... why not just use autoload charles?
a @ http://codeforpeople.com/
Raising an error might be a better way to ensure people don't run
code without ObjectSpace enabled, certainly. But maybe they don't
care?
ara.t.howard said:they care.... why not just use autoload charles?
Because ObjectSpace needs to be loaded/enabled *before* the objects
you want to track come into existance. Unlike Ruby's simple GC and
memory model, in JRuby we have to explicitly add objects created to
a walkable list. There's no capability on most modern GCed VMs to
walk the heap at will. Because of that, any objects created before
ObjectSpace is enabled would not be visible during any subsequent
walk. Generally, autoload would be far too late.
ara.t.howard said:hmmm. an exception seems best then - force the require up front. or,
is there perhaps a lighter weight method to mark things so you *could*
bootstrap ObjectSpace once it was loaded?
Charles said:In general, the tricky bit is that there's at least one key library in
stdlib that depends on ObjectSpace: test/unit, which uses it to locate
tests. However I've implemented in JRuby the ability to walk all child
classes from a parent class, which provides the each_object(Class) used
in test/unit.
Joel said:Does your mechanism to walk child classes prevent them from being
collected, if there are no other references to them? If so, then it
isn't quite bug-compatible (though it is unlikely to matter):
Joel said:The dependence on ObjectSpace is kind of nasty, isn't it? A library
shouldn't use ObjectSpace in this way, because what it finds there may
depend on whether GC has run recently or not.
Good to hear you found a way to support it anyway, though.
Does your mechanism to walk child classes prevent them from being
collected, if there are no other references to them? If so, then it
isn't quite bug-compatible (though it is unlikely to matter):
Not really; we've made it as lightweight as possible. The problem
is that there's no capability in the JVM to say "let me walk all
objects", largely because of how that would impact GC operation and
security (should objects created in other classloaders be walkable?
internal JVM objects? should you be able to reach objects you'd
*never* be able to construct or reference yourself? so many
questions).
So the only way to ever be able to reach objects in the future is
to have a reference to them somewhere. So we create a very
lightweight linked list of references to all objects created.
However it gets more complicated: ObjectSpace references shouldn't
keep objects from getting collected. So every reference is a Java
weak reference, and we periodically clean the list of dead references.
Tracking every object created + weak references + periodic cleanup
= slow.
So ObjectSpace either needs to be there when the object is created,
or you must accept that you can't ever walk it.
M. Edward (Ed) Borasky said:What is "patch 5000"??[...]
1.8.6 5000 i686-linux 13.607635 73488
[...]
Lionel said:IIRC on my Gentoo I got +80% on this particular benchmark withDaniel said:Gentoo Linux on Intel Pentium 4 2.40GHz (512 KB cache):
Ruby Patch Platform Seconds Iterations per second
===== ===== =================== ========= =====================
1.8.6 111 i686-linux (gentoo) 32.801483 30486
1.8.6 5000 i686-linux 13.607635 73488
1.9.0 0 i686-linux 3.988949 250692
1.8.5 3876 java 63.589 15725
1.8.5 3876 java (-J-server) 44.173 22638
1.8.5 3876 java (-O) 36.917 27087
1.8.5 3876 java (-O -J-server) 15.194 65815
The first is the system installed ruby.
USE="-threads". Given this huge difference I looked at the speedup for
the test suite of one of my Rails applications and got only ~ +10%.
[...]
Well, you need to explicitly reference ObjectSpace in most cases to
access it, right?
In general, the tricky bit is that there's at least one key library
in stdlib that depends on ObjectSpace: test/unit, which uses it to
locate tests.
Yes, it's very easy to do so. In fact, it's so easy that I implementedJames said:Couldn't test/unit define an inherited() hook and locate test cases
that way? I haven't looked at the code, but it seems like that could
work.
James Edward Gray II
Ola said:Yes, it's very easy to do so. In fact, it's so easy that I implemented
it a few months back:
http://ola-bini.blogspot.com/2007/07/objectspace-to-have-or-not-to-have.html
I didn't integrate it with test/unit at that point, but it should be
easy-easy to do.
How fast does your Ruby run?
Followup, with the newly released 1.8.6p100
robert-mcgoverns-computer:~/Documents/Programming robertmcgovern$ ruby test.rb
55
Ruby 1.8.6 patch 110 on i686-darwin8.10.1
It took 9.955669 seconds to run. 100445 iterations persecond.
Slightly slower, running on battery but I don't think it makes any difference.
How fast does my Ruby run?! You've never heard of The Millenium Ruby?
It's the version that made the GNU/Kessel run in less than 12
parsecs!
It's run faster than Imperial programming languages. Not the local
bulk Java installs, mind you. I'm talking the big MS C# installs.
She's fast enough for you, old man.
JRUBY:
C:\jruby\jruby-trunk\bin>jruby calculate.rb
55
It took 41.125 seconds to run. 24316 iterations per
second.
Not so good. Let's disable ObjectSpace:
C:\jruby\jruby-trunk\bin>jruby -O calculate.rb
55
It took 11.109 seconds to run. 90017 iterations per
second.
That was good. Now let's give it some more juice:
C:\jruby\jruby-trunk\bin>jruby -J-server -O calculate.rb
55
It took 5.75 seconds to run. 173913 iterations per
second.
--------------------------------------------
MRI:One-Click
ruby calculate.rb
55
Ruby 1.8.6 patch 0 on i386-mswin32
It took 15.828 seconds to run. 63179 iterations per
second.
Program changed a little:
n = 3_000_000
start_time = Time.now
t = 0
1.upto(n) do |i|
t = (1..10).inject {|x, y| x + y }
end
finish_time = Time.now
p t
puts
RUBY_VERSION ||= "unknown version"
RUBY_PATCHLEVEL ||= "unknown patchlevel"
RUBY_PLATFORM ||= "unknown platform"
print "Ruby ", RUBY_VERSION, " patch ", RUBY_PATCHLEVEL, " on ",
RUBY_PLATFORM
puts
print "It took #{finish_time - start_time} seconds to run."
print " #{(n / (finish_time - start_time)).to_i} iterations per
second.\n"
D:\>ruby calc.rb
55
Ruby 1.9.1 patch 378 on i386-mingw32
It took 6.414366 seconds to run. 467700 iterations per second.
Dell with Intel Quad Core Q6600
=================================================================
C:\>ruby19\bin\ruby.exe calc.rb
55
Ruby 1.9.1 patch 378 on i386-mingw32
It took 5.289302 seconds to run. 567182 iterations per second.
Dell with Intel i7 920, 2.67GHz
the same machine, but using Ruby 1.8.7:
Ruby 1.8.7 patch 249 on i386-mingw32
It took 20.26816 seconds to run. 148015 iterations per second.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.