I tried a very naive version of this, just to demonstrate the performance gain.

First off, if you never call cleanup during add, the size of the list will quickly grow to consume all memory. The objects the weakrefs point at will be collected, but the weakrefs themselves will not. Some cleanup is necessary during add, though it could probably only be run every N calls to add.

If we ignore this, however, and increase the heap size to allow the list to grow, the performance gains moving to a list are still nowhere near eliminating OS entirely:

For test: 1_000_000.times { <four literal strings> }
normal run, 512M, OS as-is: 17.3s
sync ArrayList, 512M, OS saves weakrefs: 16.4s
sync ArrayList, 512M, OS saves objects: 22s
unsync ArrayList, 512M, OS saves weakrefs: 16.2s
unsync ArrayList pre-alloc 5M entries, 512M, OS saves weakrefs: 14.8s
normal run, 512M, OS disabled: 7s

So what does this tell us?

First off, maintaining any sort of list is bad...ArrayList or otherwise. Even if we throw out things we need, like cleaning the list, and make the list huge to begin with, it's still over 2x as slow as not maintaining a list in the first place.

Second, maintaining weakrefs is actually cheaper than maintaining the objects, probably because most of them are immediately collected in this contrived example.

Third, it seems that nothing we do is going to reduce the cost of OS to an unnoticeable level. Look at it logically:

Object Creation Without OS:
- instantiate object (cheap)
- set RubyClass (cheap if we reference builtin classes directly)
- set tainting (cheap)

Object Creation With OS:
- all of the above plus...
- list maintenance (potentially very expensive for a set or growing arraylist)
- hashing (if using a set) (very expensive)
- WeakRef creation (cheap)
- cleanup (expensive)

Even if we eliminate cleanup and hashing, we're still instantiating twice as many objects and maintaining a list.

At this point, my vote goes to OS being disabled by default, with a flag to turn it on.

On 6/5/06, Ola Bini < [EMAIL PROTECTED]> wrote:
Hi.

The big problem with ObjectSpace seems to be that it punishes even those
who aren't using it in the current implementation. If we changed the
implementation to something like this:
    private List references = new ArrayList();
    private Set realReferences = null;
    private ReferenceQueue deadReferences = new ReferenceQueue();

    public void add(IRubyObject object) {
        references.add(new WeakReference(object, deadReferences));
    }

    public Iterator iterator(RubyModule rubyClass) {
        cleanup();
        realReferences = new HashSet(references);
        return new ObjectSpaceIterator(rubyClass);
    }


The point of this exercise being that it _should_ be dead fast to create
a new WeakReference, and add at the end of an arraylist. If something
actually wants to iterate over ObjectSpace, this will be slower, since
we do both cleanup and hash all the objects we have references too. But
this hit will only be for those using ObjectSpace.

What d'you think?

/O



--
Charles Oliver Nutter @ headius.blogspot.com
JRuby Developer @ jruby.sourceforge.net
Application Architect @ www.ventera.com
_______________________________________________
Jruby-devel mailing list
Jruby-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jruby-devel

Reply via email to