Hi all,
I have started implementing some structural sharing and performance improvements in HashSet. The basic contains/apply method is pretty good, but there is a lot of room for improvement for operations that take two sets as arguments, such as
union, intersection, diff, subsetOf. Filter can also be improved to reuse the original tree as much as possible.
Since this is a bigger change, I made a little toy project on github containing the new implementation of the HashSet operations as well as tests and caliper benchmarks.
Here it is:
https://github.com/rklaehn/hashsetHere are some results from the caliper benchmark. subsetOf is the only method I have fully optimized. Set.subsetOf is quite important since it is used for set equality.
As you can see the new implementation is orders of magnitude faster than the old one, which is not surprising if you consider that you sometimes just have to do a bitmap operation where the old method calls contains for every single element of the set!
The benchmark suite is quite comprehensive. It covers {subsetof, diff, intersection, union} for four different data types {int, string, collision and vector} and different overlap between the sets. An offset of 0 means that the two sets are identical, whereas an offset of 1 means that there is no overlap.
The types are to test different things you might want to put into a set: Int has extremely fast hashcode and equals. String has fast hashcode but slow equals. collision is designed to produce a lot of hash code collisions, and vector has slow hashcode and slow equals.
In the benchmark result below I have disabled everything except int subsetof tests, because otherwise the benchmark takes hours. The other operations (union, intersection, diff and filter) are also already implemented, but they are sometimes slower than the current version, so obviously they still need some tweaking.
cheers,
Rüdiger
---
[info]
[info] offset size collectionType ns linear runtime
[info] 0 2 hashset2 12.31 =
[info] 0 2 hashset 29.26 =
[info] 0 10 hashset2 46.67 =
[info] 0 10 hashset 102.80 =
[info] 0 100 hashset2 1208.46 =
[info] 0 100 hashset 2033.84 =
[info] 0 1000 hashset2 13869.10 ============
[info] 0 1000 hashset 32112.92 ==============================
[info] 0.33 2 hashset2 12.19 =
[info] 0.33 2 hashset 30.07 =
[info] 0.33 10 hashset2 1.41 =
[info] 0.33 10 hashset 17.29 =
[info] 0.33 100 hashset2 10.99 =
[info] 0.33 100 hashset 44.82 =
[info] 0.33 1000 hashset2 10.92 =
[info] 0.33 1000 hashset 116.69 =
[info] 0.66 2 hashset2 1.40 =
[info] 0.66 2 hashset 16.87 =
[info] 0.66 10 hashset2 1.43 =
[info] 0.66 10 hashset 16.93 =
[info] 0.66 100 hashset2 1.41 =
[info] 0.66 100 hashset 48.35 =
[info] 0.66 1000 hashset2 10.93 =
[info] 0.66 1000 hashset 42.11 =
[info] 1 2 hashset2 1.40 =
[info] 1 2 hashset 17.63 =
[info] 1 10 hashset2 1.40 =
[info] 1 10 hashset 16.97 =
[info] 1 100 hashset2 11.05 =
[info] 1 100 hashset 26.93 =
[info] 1 1000 hashset2 10.92 =
[info] 1 1000 hashset 31.88 =
[info]
[info] vm: java
[info] trial: 0
[info] benchmark: SubsetOf
[info] keyType: int
[info]
[info] View current and previous benchmark results online:
[info]
http://microbenchmarks.appspot.com/run/rkl...@gmail.com/SetBenchmark
[info]
[info] Writing results to /home/rklaehn/projects_git/rklaehn/hashset/caliper-results/SetBenchmark.2013