I played with this a bit yesterday too. I left RubyObject hashCode the way it was. Then set a breakpoint there. Then ran scripts. When I saw a core class which used it I would add a hashCode impl that did what ever they had for 'hash'. If they didn't have anything I used System.identityHashCode. This all worked fine. I believe it is also a zero-sum change.
My observations on this is that Rail/webrick startup probably only hit hashCode like 60-70 times (I am ignoring the stuff JRuby did as part of startup - Each ENV var would generate 2 calls during startup). I am guessing rubygems rdoc hits this a lot. Do you know how many of these hashCode calls in the rubygems scenario you mentioned was from user-defined classes versus core ones? My patch would obviously not help those. I would be extremely hesitant to consider toString() as part of the hashing algorithm. Consider user-defined classes I think those would generate the same string a lot (look at RubyObject's toString() impl). We could memoize RubyObject hash impl at the cost of an extra int in every object (its not like we are space efficient right now anyways. Or we could even remove hashCode from RubyObject all together and say all Ruby object by default have the same hash as the java object holding their state? The JVM may even optimize for this. I will throw my patch out just for sake of comparison. -Tom On Sun, 18 Jun 2006, Ola Bini defenestrated me: > Hi, > > Yes, of course that's needed. But on the other hand, the change actually > already found us a place where our test code was wrong (see my post on > TestRubyHash). Incidentally, my first approach was to try and see how > System.identityHashCode() would work out as the general > hashCode-algorithm. I've been using rubygems setup, gem install and the > rails script as different tests to see if the changes break anything, > and it was very apparent when I changed to identityHashCode that nothing > at all worked. With my current changes everything seems really fine, though! > > /O > > ----- Original Message ----- > From: Charles O Nutter <[EMAIL PROTECTED]> > Date: Sunday, June 18, 2006 6:22 am > Subject: Re: [Jruby-devel] JRuby, RDoc and speed... > To: jruby-devel@lists.sourceforge.net > > > This is pretty promising; we need to do an audit of how all the > > core objects > > are used in various places, however, especially in our > > implementation of > > Ruby's hash, so we're not breaking anything; but it has always > > bothered me > > that java's hashCode and Ruby's hash were synonymous in JRuby. This > > lookslike a good first step, and ought to help performance in a > > number of places. > > > > On 6/17/06, Ola Bini <[EMAIL PROTECTED]> wrote: > > > > > > Hi > > > > > > I've done a few easy things to try to speed up JRuby, when doing > > RDoc. I > > > have three timings for you today. The first one is C Ruby doing > > it. The > > > second is recent JRuby without my new enhancements, and the third > > is my > > > final version right now: > > > > > > [EMAIL PROTECTED] /cygdrive/d/project/jruby > > > $ time ruby d:/programming/ruby/bin/gem install rake > > > Attempting local installation of 'rake' > > > Successfully installed rake, version 0.7.1 > > > Installing RDoc documentation for rake-0.7.1... > > > > > > real 0m13.915s > > > user 0m0.000s > > > sys 0m0.000s > > > > > > [EMAIL PROTECTED] /cygdrive/d/project/jruby > > > $ time bin/jruby.bat bin/gem install rake > > > Attempting local installation of 'rake' > > > Successfully installed rake, version 0.7.1 > > > Installing RDoc documentation for rake-0.7.1... > > > > > > real 1m42.985s > > > user 0m0.000s > > > sys 0m0.010s > > > > > > [EMAIL PROTECTED] /cygdrive/d/project/jruby > > > $ time bin/jruby.bat bin/gem install rake > > > Attempting local installation of 'rake' > > > Successfully installed rake, version 0.7.1 > > > Installing RDoc documentation for rake-0.7.1... > > > > > > real 0m59.946s > > > user 0m0.000s > > > sys 0m0.010s > > > > > > As you can see, C Ruby does this in about 14s, old JRuby in 100s > > and my > > > new > > > version in 60s. For these purposes we are only 5 times slower > > than C Ruby, > > > half a magnitude. =) > > > > > > So, what was the "error" in the former version? I'll let the code > > speak> for > > > itself. This is from RubyObject: > > > public final int hashCode() { > > > return RubyNumeric.fix2int(callMethod("hash")); > > > } > > > > > > Yes, you read that right. We call a Ruby-method for EVERY > > HashMap#get,> HashMap#put and HashSet#add etc... Not even a > > memoized version. And those > > > operations are used fairly heavy in JRuby. HashMap#get is on the > > top 5 > > > time > > > thieves accord to hprof. > > > > > > So, I replaced the former with this in RubyObject: > > > public int hashCode() { > > > return toString().hashCode(); > > > } > > > > > > and added very simple new ones to > > > RubyArray.java > > > RubyBignum.java > > > RubyDir.java > > > RubyFile.java > > > RubyFixnum.java > > > RubyHash.java > > > RubyModule.java > > > RubyString.java > > > RubyThread.java > > > RubyTime.java > > > > > > ... Right now my source tree is slightly unclean, so I can't give > > a patch > > > for these modifications, but everyone of the is very simple. I > > just call > > > hashCode on the value object inside the object most times. > > RubyModule uses > > > classId == null ? 0 : classId.hashCode(); ... and RubyThread uses > > > threadImpl.hashCode(). > > > > > > Regards > > > Ola Bini > > > > > > > > > > > > > > > _______________________________________________ > > > Jruby-devel mailing list > > > Jruby-devel@lists.sourceforge.net > > > https://lists.sourceforge.net/lists/listinfo/jruby-devel > > > > > > > > > > > -- > > 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 -- + http://www.tc.umn.edu/~enebo +---- mailto:[EMAIL PROTECTED] ----+ | Thomas E Enebo, Protagonist | "Luck favors the prepared | | | mind." -Louis Pasteur |
Index: .classpath =================================================================== RCS file: /cvsroot/jruby/jruby/.classpath,v retrieving revision 1.26 diff -u -r1.26 .classpath --- .classpath 8 Jun 2006 22:42:54 -0000 1.26 +++ .classpath 18 Jun 2006 14:01:38 -0000 @@ -7,5 +7,6 @@ <classpathentry kind="lib" path="lib/junit.jar"/> <classpathentry kind="lib" path="lib/ant.jar"/> <classpathentry kind="lib" path="lib/jvyaml.jar"/> + <classpathentry kind="lib" path="lib/plaincharset.jar"/> <classpathentry kind="output" path="build/classes/jruby"/> </classpath> Index: src/org/jruby/RubyArray.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyArray.java,v retrieving revision 1.59 diff -u -r1.59 RubyArray.java --- src/org/jruby/RubyArray.java 26 May 2006 02:48:23 -0000 1.59 +++ src/org/jruby/RubyArray.java 18 Jun 2006 14:01:41 -0000 @@ -114,7 +114,11 @@ } public RubyFixnum hash() { - return getRuntime().newFixnum(list.hashCode()); + return getRuntime().newFixnum(hashCode()); + } + + public int hashCode() { + return list.hashCode(); } /** rb_ary_modify Index: src/org/jruby/RubyBoolean.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyBoolean.java,v retrieving revision 1.16 diff -u -r1.16 RubyBoolean.java --- src/org/jruby/RubyBoolean.java 26 Oct 2005 05:34:13 -0000 1.16 +++ src/org/jruby/RubyBoolean.java 18 Jun 2006 14:01:41 -0000 @@ -74,6 +74,10 @@ public boolean isFalse() { return !value; } + + public int hashCode() { + return System.identityHashCode(this); + } public static RubyClass createFalseClass(IRuby runtime) { RubyClass falseClass = runtime.defineClass("FalseClass", runtime.getObject()); Index: src/org/jruby/RubyClass.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyClass.java,v retrieving revision 1.43 diff -u -r1.43 RubyClass.java --- src/org/jruby/RubyClass.java 10 Feb 2006 21:53:25 -0000 1.43 +++ src/org/jruby/RubyClass.java 18 Jun 2006 14:01:42 -0000 @@ -85,7 +85,7 @@ public boolean isClass() { return true; } - + public static void createClassClass(RubyClass classClass) { CallbackFactory callbackFactory = classClass.getRuntime().callbackFactory(RubyClass.class); classClass.defineSingletonMethod("new", callbackFactory.getOptSingletonMethod("newClass")); Index: src/org/jruby/RubyFixnum.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyFixnum.java,v retrieving revision 1.33 diff -u -r1.33 RubyFixnum.java --- src/org/jruby/RubyFixnum.java 20 Apr 2006 01:14:32 -0000 1.33 +++ src/org/jruby/RubyFixnum.java 18 Jun 2006 14:01:42 -0000 @@ -98,7 +98,11 @@ } public RubyFixnum hash() { - return newFixnum((int) value ^ (int) (value >> 32)); + return newFixnum(hashCode()); + } + + public int hashCode() { + return (int) value ^ (int) (value >> 32); } // Methods of the Fixnum Class (fix_*): Index: src/org/jruby/RubyHash.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyHash.java,v retrieving revision 1.34 diff -u -r1.34 RubyHash.java --- src/org/jruby/RubyHash.java 22 Apr 2006 22:54:21 -0000 1.34 +++ src/org/jruby/RubyHash.java 18 Jun 2006 14:01:43 -0000 @@ -89,6 +89,10 @@ }; } + public int hashCode() { + return System.identityHashCode(this); + } + public IRubyObject getDefaultValue(IRubyObject[] args) { return defaultValueCallback != null ? defaultValueCallback.execute(this, args) : getRuntime().getNil(); } Index: src/org/jruby/RubyModule.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyModule.java,v retrieving revision 1.108 diff -u -r1.108 RubyModule.java --- src/org/jruby/RubyModule.java 23 Apr 2006 14:34:30 -0000 1.108 +++ src/org/jruby/RubyModule.java 18 Jun 2006 14:01:45 -0000 @@ -120,6 +120,10 @@ return (RubyModule)cref.getNext().getValue(); } + public int hashCode() { + return System.identityHashCode(this); + } + public Map getMethods() { return methods; } Index: src/org/jruby/RubyNil.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyNil.java,v retrieving revision 1.15 diff -u -r1.15 RubyNil.java --- src/org/jruby/RubyNil.java 8 Oct 2005 13:07:07 -0000 1.15 +++ src/org/jruby/RubyNil.java 18 Jun 2006 14:01:45 -0000 @@ -80,6 +80,10 @@ return true; } + public int hashCode() { + return System.identityHashCode(this); + } + // Methods of the Nil Class (nil_*): /** nil_to_i Index: src/org/jruby/RubyObject.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyObject.java,v retrieving revision 1.90 diff -u -r1.90 RubyObject.java --- src/org/jruby/RubyObject.java 22 Apr 2006 22:54:20 -0000 1.90 +++ src/org/jruby/RubyObject.java 18 Jun 2006 14:01:47 -0000 @@ -758,7 +758,7 @@ * to subclasses that we know will have the same hash value. */ // TODO: Consider making some standard library call System.identityHashCode directly - public final int hashCode() { + public int hashCode() { return RubyNumeric.fix2int(callMethod("hash")); } Index: src/org/jruby/RubyString.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyString.java,v retrieving revision 1.51 diff -u -r1.51 RubyString.java --- src/org/jruby/RubyString.java 6 Jun 2006 02:40:53 -0000 1.51 +++ src/org/jruby/RubyString.java 18 Jun 2006 14:01:48 -0000 @@ -145,6 +145,10 @@ return getRuntime().newFixnum(toString().hashCode()); } + public final int hashCode() { + return toString().hashCode(); + } + // Common enough check to make it a convenience method. private boolean sameAs(Object other) { return toString().equals(other.toString()); Index: src/org/jruby/RubySymbol.java =================================================================== RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubySymbol.java,v retrieving revision 1.29 diff -u -r1.29 RubySymbol.java --- src/org/jruby/RubySymbol.java 15 Jun 2006 14:17:22 -0000 1.29 +++ src/org/jruby/RubySymbol.java 18 Jun 2006 14:01:49 -0000 @@ -136,7 +136,11 @@ } public RubyFixnum hash() { - return getRuntime().newFixnum(symbol.hashCode()); + return getRuntime().newFixnum(hashCode()); + } + + public int hashCode() { + return symbol.hashCode(); } public IRubyObject to_sym() { Index: ____temp_zlib_file =================================================================== RCS file: ____temp_zlib_file diff -N ____temp_zlib_file --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ____temp_zlib_file 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,1 @@ +? ????J???IJ,? nU? Index: aaa =================================================================== RCS file: aaa diff -N aaa --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ aaa 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,2 @@ + +{
_______________________________________________ Jruby-devel mailing list Jruby-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jruby-devel