Skip to content

Commit

Permalink
Optimize PackedLongHashSet. (#137)
Browse files Browse the repository at this point in the history
The optimization is based on the boxing elimination, now `PackedLongHashSet.contains` directly uses the performant `getEntry(long)` method thus avoiding the boxing and associated allocations

Before:
```
Benchmark                                                  Mode  Cnt   Score   Error   Units
dataStructures.JMHPackedLongHashSetBenchmark.tryContains  thrpt   30  14,195 ± 1,574  ops/ms
```

After:
```
Benchmark                                                  Mode  Cnt   Score   Error   Units
dataStructures.JMHPackedLongHashSetBenchmark.tryContains  thrpt   30  46,406 ± 1,430  ops/ms
```
  • Loading branch information
semoro authored and jk1 committed Apr 26, 2024
1 parent fff23c0 commit 9fd6c35
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright ${inceptionYear} - ${year} ${owner}
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.exodus.benchmark.dataStructures;

import jetbrains.exodus.core.dataStructures.hash.PackedLongHashSet;
import org.openjdk.jmh.annotations.*;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@SuppressWarnings({"UnusedDeclaration"})
@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class JMHPackedLongHashSetBenchmark {

protected static final int SET_SIZE = 100000;

final PackedLongHashSet setForContains = new PackedLongHashSet();


final long[] testData = new long[10000];

@Setup
public void prepare() {
Random r = new Random();
for (int i = 0; i < SET_SIZE; i++) {
setForContains.add(r.nextLong());
}

for (int i = 0; i < testData.length; i++) {
testData[i] = r.nextLong();
}
}


@Benchmark
@Warmup(iterations = 4, time = 1)
@Measurement(iterations = 6, time = 1)
@Fork(5)
public Object tryAdd() {
final PackedLongHashSet setForAdd = new PackedLongHashSet();
for (long testDatum : testData) {
setForAdd.add(testDatum);
}
return setForAdd;
}

@Benchmark
@Warmup(iterations = 4, time = 1)
@Measurement(iterations = 6, time = 1)
@Fork(5)
public boolean tryContains() {
boolean c = true;
for (long testDatum : testData) {
c ^= setForContains.contains(testDatum);
}
return c;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ class LongLongHashMap @JvmOverloads constructor(capacity: Int = 0, private val l
}
}

private fun getEntry(key: Long): Entry? {
/**
* This function returns Entry without Long boxing for better performance.
*/
internal fun getEntry(key: Long): Entry? {
val table = table
val index = HashUtil.indexFor(key, table.size, mask)
var e = table[index]
Expand Down Expand Up @@ -182,7 +185,7 @@ class LongLongHashMap @JvmOverloads constructor(capacity: Int = 0, private val l
}
}

private class Entry(override val key: Long, override var value: Long) : MutableMap.MutableEntry<Long?, Long> {
internal class Entry(override val key: Long, override var value: Long) : MutableMap.MutableEntry<Long?, Long> {

var hashNext: Entry? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class PackedLongHashSet(source: Collection<Long>? = null, loadFactor: Float = Ha
}

override fun contains(element: Long): Boolean {
val v = map[element.key]
return v != null && v and masks[element.bit] != 0L
val v = map.getEntry(element.key)
return v != null && v.value and masks[element.bit] != 0L
}

override fun add(element: Long): Boolean {
Expand Down

0 comments on commit 9fd6c35

Please sign in to comment.