Daniel Schömer wrote:
1.8.5 3876 java (-O -J-server) 15.194 65815
The first is the system installed ruby.
IIRC on my Gentoo I got +80% on this particular benchmark with
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%.
That said I use Xpath in one Ruby script and the speedup was
unbelievable : maybe +1000% (yes 3 zeros, the script took more than a
minute, maybe several and with USE="-threads" it went through the data
in less than ten seconds).
I believe Ruby compiled with pthread is known to have performance
problems (at least on Linux as I’ve seen reports of such behavior on
Linux before)…
If you want speed on Linux (and maybe other flavours of Unix), you
should look at compiling it without pthread. Warning: as some classes
may use system libs that are compiled with pthread, you might not have
this choice (IIRC the pthread support is there just to support such
libraries).
If someone knows more about this subject (and how to tell if compiling
without pthread is safe), I’d love to know the details.
Regards,
Lionel
Lionel B. wrote:
1.8.5 3876 java (-O) 36.917 27087
minute, maybe several and with USE="-threads" it went through the data
If someone knows more about this subject (and how to tell if compiling
without pthread is safe), I’d love to know the details.
Regards,
Lionel
Well, on Gentoo you’d need to turn off the “threads” USE flag globally.
Either everything (in this case Ruby and Tcl/Tk for sure) is with
“threads” or everything is without it. Personally, on my two UP systems
(non-SMP) I turn it off and on my dual-core SMP system I turn it on. But
that’s really superstition more than anything based on measurements.
I can’t speak for other distros, Windows, Intel vs. AMD, etc. But as far
as I know on Gentoo it’s safe to go “-threads” across the board even on
an SMP system. I’m going to go ahead and turn it off on the dual-core
and see what happens – I’m wrapping up some benchmarking tests this
weekend so it’s a good time to play around with it in a controlled
environment.
Charles Oliver N. wrote:
1.8.5 3876 java (-O) 36.917 27087
Just a question – assuming it’s off by default, how do you know when
you need to turn it on?
Charles Oliver N. wrote:
We’d print a warning if it’s used without being enabled.
Let me re-phrase that … how do I know when I’m coding that I’m not
going to ask for it? Do I need to explicitly call/require/include
something to get it?
M. Edward (Ed) Borasky wrote:
Charles Oliver N. wrote:
FYI, we’re debating making ObjectSpace something you must turn on at
command line or through a library call, rather than something you have
to turn off. Practically nothing uses it, and it’s a huge perf hit for
JRuby.
Just a question – assuming it’s off by default, how do you know when
you need to turn it on?
We’d print a warning if it’s used without being enabled.
Charles Oliver N.:
Just a question – assuming it’s off by default, how do you know when
you need to turn it on?
We’d print a warning if it’s used without being enabled.
Wouldn’t it be better to throw?
On Gentoo, Ruby with threads is ridiculously slow. Machine is an Xeon
E5320 1.86GHz.
$ ruby-nothreads calculate.rb
55
Ruby 1.8.6 patch 111 on i686-linux
It took 9.759139 seconds to run. 102468 iterations per
second.
$ ruby-threads calculate.rb
55
Ruby 1.8.6 patch 111 on i686-linux
It took 21.473884 seconds to run. 46568 iterations per
second.
M. Edward (Ed) Borasky wrote:
Let me re-phrase that … how do I know when I’m coding that I’m not
going to ask for it? Do I need to explicitly call/require/include
something to get it?
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. 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. Currently, you can turn off ObjectSpace support in JRuby
and still have test/unit run.
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?
It’s an open question at the moment, but I don’t see that there’s any
way ObjectSpace is going to have good performance on these new
implementations where we don’t have intimate control over memory and GC.
I expect this is going to be a concern for IronRuby/Ruby.NET too. As far
as I know, JRuby’s the only general-purpose VM implementation of Ruby
that’s even attempted to make ObjectSpace work.
ara.t.howard wrote:
On Oct 27, 2007, at 11:04 PM, Charles Oliver N. wrote:
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?
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.
On Oct 27, 2007, at 11:04 PM, Charles Oliver N. wrote:
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/
On Oct 27, 2007, at 11:46 PM, Charles Oliver N. wrote:
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.
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?
cheers.
a @ http://codeforpeople.com/
ara.t.howard wrote:
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?
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.
Joel VanderWerf wrote:
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):
Oh, just saw your other post: you use weak refs, so the behavior should
be like ObjectSpace.
Charles Oliver N. wrote:
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.
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):
require ‘test/unit’
def add_a_test_case str
puts “adding test case #{str}”
Class.new(Test::Unit::TestCase).class_eval do
define_method :test_foo do
puts “running test case #{str}”
end
end
end
at_exit { GC.start }
at_exit { add_a_test_case 1 }
at_exit { add_a_test_case 2 }
at_exit { add_a_test_case 3 }
at_exit { add_a_test_case 4 }
END
adding test case 4
adding test case 3
adding test case 2
adding test case 1
Loaded suite -
Started
running test case 1
.
Finished in 0.000918 seconds.
1 tests, 0 assertions, 0 failures, 0 errors
On Oct 28, 2007, at 12:17 AM, Charles Oliver N. wrote:
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).
better you than me 
So ObjectSpace either needs to be there when the object is created,
or you must accept that you can’t ever walk it.
hmmm. ok i’m brainstorming here which you can ignore if you like as
i know less that nothing about jvms or implementing ruby but here
goes: what if you could invert the problem? what i objects knew
about the global ObjectSpaceThang and could be forced to register
themselves on demand somehow? without a reference i’ve no idea how,
just throwing that out there. or, another stupid idea, what if the
objects themselves were the tree/graph of weak references parent →
children. crawling it would be, um, fun - but you could prune dead
objects only when walking the graph. this should be possible in
ruby since you always have the notion of a parent object - which is
Object - so all objects should be either reachable or leaks. now
back to drinking my regularly scheduled beer…
cheers.
a @ http://codeforpeople.com/
Joel VanderWerf wrote:
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.
Yes, ObjectSpace is a useful tool for walking the heap when you really
want to, but it’s not deterministic about whether or when it will find
the object(s) you want. So I agree it’s a bad feature to use as part of
libraries you want to work the same way every time.
In the case of test/unit, most TestCase descendants get hard-referenced
as classes assigned to constants somewhere. However if you constructed a
test case as follows:
Class.new(Test::Unit::TestCase) { def test_something; end }
…it may or may not run with the default loader.
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):
No, the references to child classes are all weak references; if they go
away, the references will go away. It’s a much smaller price to pay than
attaching weak references to all constructed objects (to my knowledge,
it costs almost nothing, and test/unit still works.
The typical way I think people would fix test/unit’s use of ObjectSpace
would be to add a Class#inherited hook that records all subclasses of
TestCase. But nobody’s gone ahead with that change yet.
M. Edward (Ed) Borasky wrote:
Daniel Schömer wrote:
[…]
1.8.6 5000 i686-linux 13.607635 73488
[…]
What is “patch 5000”??
That’s what ruby from the svn checkout
http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8 thinks is
it’s patchlevel.
| # cat ruby_1_8/version.h
| #define RUBY_VERSION “1.8.6”
| #define RUBY_RELEASE_DATE “2007-10-26”
| #define RUBY_VERSION_CODE 186
| #define RUBY_RELEASE_CODE 20071026
| #define RUBY_PATCHLEVEL 5000
|
| #define RUBY_VERSION_MAJOR 1
| #define RUBY_VERSION_MINOR 8
| #define RUBY_VERSION_TEENY 6
| #define RUBY_RELEASE_YEAR 2007
| #define RUBY_RELEASE_MONTH 10
| #define RUBY_RELEASE_DAY 26
|
| #ifdef RUBY_EXTERN
| RUBY_EXTERN const char ruby_version[];
| RUBY_EXTERN const char ruby_release_date[];
| RUBY_EXTERN const char ruby_platform[];
| RUBY_EXTERN const int ruby_patchlevel;
| #endif
Daniel