--17pEHd4RhPHOinZp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Just hacked it.
I am using the Jenkins' implementation from Perl 5.8. Moreover, I got
rid of the modulus operations (and the prime numbers) by using bitwise
AND and ensuring that num_bins is 2^n - 1 (this implies that I've had
to add 1 in a number of places, but I believe it is more important to
make FIND_ENTRY as fast as possible).
I'm sorry I didn't put the HASH_JENKINS magic into configure.in; I have
little experience with autoconf. I'll try harder next time :)
Here's the result of an informal benchmark comparing 1.6.8/1.8.0 (CVS
head as of Feb. 28 ~17H) with Jenkins against the vanilla versions:
10000 30000 100000 300000 500000 1000000
ruby-1.6.8.jenkins 0.0910 0.3198 1.2080 10.0227 7.7709 18.0764
ruby-1.6.8.jenkins.orig 0.0907 0.3254 1.2281 10.2327 8.0457 18.3917
ruby.jenkins 0.0857 0.2942 1.3588 4.2214 8.0908 17.9354
ruby.jenkins.orig 0.0902 0.3133 1.4469 4.5248 8.5991 18.7564
(.orig means the version without Jenkins)
[BTW it seems 1.8's GC has been improved quite a bit as shown by the
great difference for 300000 iterations; great work! :) ]
The script used is a minimal modification of the one at The Great Computer
Language Shootout:
#!/usr/local/bin/ruby
# -*- mode: ruby -*-
# $Id: hash.ruby,v 1.3 2001/10/09 23:25:12 doug Exp $
# http://www.bagley.org/~doug/shootout/
# with help from Aristarkh A Zagorodnikov
start ime.new
n ARGV.shift || 1).to_i
hash }
for i in 1..n
hash['%x' % i]
end
c
n.downto 1 do |i|
c + if hash.has_key? i.to_s
end
puts(Time.new - start)
And here's the code that drives the benchmarks:
batsman@tux-chan:~/src/cvs$ cat benchmark.rb
dirs "ruby-1.6.8.jenkins", "ruby-1.6.8.jenkins.orig",
"ruby.jenkins", "ruby.jenkins.orig" ]
sizes 10000 , 30000, 100000, 300000, 500000, 1000000 ]
res }
dirs.each do |x|
res[x] }
sizes.each do |size|
total .0
6.times do
out #{x}/ruby /tmp/hash.rb #{size}`
total + loat(out)
end
#puts "Total: #{total}"
res[x][size] otal / 6
end
end
print " " * 23
sizes.each { |x| print "%9d " % x }
puts
dirs.each do |d|
print "%23s" % d
sizes.each { |s| printf "%10.4 f" % res[d][s] }
puts
end
Hope this is useful. It's not a huge performance increase but even 5% in
this particular test is OK as this is all very simple.
--
_ _
| |__ __ _| |_ ___ _ __ ___ __ _ _ __
| '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \
| |_) | (_| | |_\__ \ | | | | | (_| | | | |
|_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com
A Linux machine! Because a 486 is a terrible thing to waste!
-- Joe Sloan, jjs / wintermute.ucr.edu
--17pEHd4RhPHOinZp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ruby-1.6.8-jenkins-0.0.1.patch"
--- ruby-1.6.8.jenkins.orig/st.c 2002-02-27 08:46:50.000000000 +0100
+++ ruby-1.6.8.jenkins/st.c 2003-02-28 19:41:29.000000000 +0100
@@ -10,6 +10,7 @@
#include <malloc.h>
#endif
+#define HASH_JENKINS 1
typedef struct st_table_entry st_table_entry;
struct st_table_entry {
@@ -65,7 +66,11 @@
#define EQUAL(table,x,y) ((x) y) || (*table->type->compare)((x),(y)) 0)
#define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key))
+#ifdef HASH_JENKINS
+#define do_hash_bin(key,table) (do_hash(key, table)&(table)->num_bins)
+#else
#define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins)
+#endif
/*
* MINSIZE is the minimum size of a dictionary.
@@ -73,6 +78,7 @@
#define MINSIZE 8
+#ifndef HASH_JENKINS
/*
Table of prime numbers 2^n+a, 2<