Skip to content

Commit

Permalink
feat: add values & keys in IntMapByDynamicHash
Browse files Browse the repository at this point in the history
  • Loading branch information
conghuhu committed Dec 5, 2023
1 parent 2a6002a commit 44d03e8
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

package org.apache.hugegraph.util.collection;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

Expand Down Expand Up @@ -92,8 +95,11 @@ private static int tableSizeFor(int c) {
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

/**
* updated via atomic field updater
*/
@SuppressWarnings("UnusedDeclaration")
private volatile int size; // updated via atomic field updater
private volatile int size;

public IntMapByDynamicHash() {
this(DEFAULT_INITIAL_CAPACITY);
Expand All @@ -110,10 +116,8 @@ public IntMapByDynamicHash(int initialCapacity) {
int cap = (size >= (long) MAXIMUM_CAPACITY) ?
MAXIMUM_CAPACITY : tableSizeFor((int) size);
if (cap >= PARTITIONED_SIZE_THRESHOLD) {
/*
we want 7 extra slots and 64 bytes for each
slot. int is 4 bytes, so 64 bytes is 16 ints.
*/
// we want 7 extra slots and 64 bytes for each
// slot. int is 4 bytes, so 64 bytes is 16 ints.
this.partitionedSize =

Check warning on line 121 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L121

Added line #L121 was not covered by tests
new int[SIZE_BUCKETS * 16];
}
Expand Down Expand Up @@ -293,14 +297,12 @@ public boolean containsKey(int key) {

@Override
public IntIterator keys() {
// TODO impl
return null;
return new KeyIterator();
}

@Override
public IntIterator values() {
// TODO impl
return null;
return new ValueIterator();
}

@Override
Expand Down Expand Up @@ -755,6 +757,113 @@ public String toString() {
}
}

/* ---------------- Iterator -------------- */

private static final class IteratorState {
private Entry[] currentTable;
private int start;
private int end;

private IteratorState(Entry[] currentTable) {
this.currentTable = currentTable;
this.end = this.currentTable.length - 1;
}

private IteratorState(Entry[] currentTable, int start, int end) {
this.currentTable = currentTable;
this.start = start;
this.end = end;
}

Check warning on line 776 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L772-L776

Added lines #L772 - L776 were not covered by tests
}

private abstract class HashIterator implements IntIterator {
private List<IteratorState> todo;
private IteratorState currentState;
private Entry next;
private int index;

protected HashIterator() {
this.currentState = new IteratorState(IntMapByDynamicHash.this.table);
this.findNext();
}

private void findNext() {
while (this.index < this.currentState.end) {
Entry o =
(Entry) IntMapByDynamicHash.tableAt(this.currentState.currentTable, this.index);
if (o == RESIZED || o == RESIZING) {
Entry[] nextArray =
IntMapByDynamicHash.this.helpWithResizeWhileCurrentIndex(
this.currentState.currentTable, this.index);
int endResized = this.index + 1;

Check warning on line 798 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L795-L798

Added lines #L795 - L798 were not covered by tests
while (endResized < this.currentState.end) {
if (IntMapByDynamicHash.tableAt(this.currentState.currentTable,

Check warning on line 800 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L800

Added line #L800 was not covered by tests
endResized) != RESIZED) {
break;

Check warning on line 802 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L802

Added line #L802 was not covered by tests
}
endResized++;

Check warning on line 804 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L804

Added line #L804 was not covered by tests
}
if (this.todo == null) {
this.todo = new ArrayList<>(4);

Check warning on line 807 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L807

Added line #L807 was not covered by tests
}
if (endResized < this.currentState.end) {
this.todo.add(new IteratorState(
this.currentState.currentTable, endResized, this.currentState.end));

Check warning on line 811 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L810-L811

Added lines #L810 - L811 were not covered by tests
}
int powerTwoLength = this.currentState.currentTable.length - 1;
this.todo.add(new IteratorState(nextArray, this.index + powerTwoLength,

Check warning on line 814 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L813-L814

Added lines #L813 - L814 were not covered by tests
endResized + powerTwoLength));
this.currentState.currentTable = nextArray;
this.currentState.end = endResized;
this.currentState.start = this.index;

Check warning on line 818 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L816-L818

Added lines #L816 - L818 were not covered by tests
} else if (o != null) {
this.next = o;
this.index++;
break;
} else {
this.index++;
}
}
if (this.next == null && this.index == this.currentState.end && this.todo != null &&
!this.todo.isEmpty()) {
this.currentState = this.todo.remove(this.todo.size() - 1);
this.index = this.currentState.start;
this.findNext();

Check warning on line 831 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L829-L831

Added lines #L829 - L831 were not covered by tests
}
}

@Override
public final boolean hasNext() {
return this.next != null;
}

final Entry nextEntry() {
Entry e = this.next;
if (e == null) {
throw new NoSuchElementException();

Check warning on line 843 in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java

View check run for this annotation

Codecov / codecov/patch

hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/collection/IntMapByDynamicHash.java#L843

Added line #L843 was not covered by tests
}

if ((this.next = e.getNext()) == null) {
this.findNext();
}
return e;
}
}

private final class ValueIterator extends HashIterator {
@Override
public int next() {
return this.nextEntry().getValue();
}
}

private final class KeyIterator extends HashIterator {
@Override
public int next() {
return this.nextEntry().getKey();
}
}

/* ---------------- Unsafe mechanics -------------- */
private static final Unsafe UNSAFE = IntSet.UNSAFE;
private static final long ENTRY_ARRAY_BASE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import org.apache.hugegraph.util.collection.IntIterator;
import org.apache.hugegraph.util.collection.IntMap;
import org.apache.hugegraph.util.collection.IntMapByDynamicHash;
import org.apache.hugegraph.util.collection.IntMapByDynamicHash2;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.junit.After;
import org.junit.Before;
Expand Down Expand Up @@ -420,7 +419,7 @@ public void testIntFixedMapBySegmentsValuesWithMultiSegs() {

@Test
public void testIntMapByDynamicHashSingleThread() {
IntMapByDynamicHash2 map = new IntMapByDynamicHash2();
IntMap map = new IntMapByDynamicHash();
int mapSize = 2000;
for (int i = 0; i < mapSize; i++) {
map.put(i, i + 1);
Expand All @@ -443,7 +442,7 @@ public void testIntMapByDynamicHashSingleThread() {

@Test
public void testIntMapByDynamicHashMultiThread() throws InterruptedException {
IntMapByDynamicHash2 map = new IntMapByDynamicHash2();
IntMap map = new IntMapByDynamicHash();

//int cpus = IntSet.CPUS;
int cpus = 16;
Expand Down Expand Up @@ -490,6 +489,34 @@ protected void afterExecute(Runnable r, Throwable t) {
Assert.assertEquals(size.get(), map.size());
}

@Test
public void testIntMapByDynamicHashKeys() {
IntMap map = new IntMapByDynamicHash();
for (int i = 0; i < 10000; i++) {
map.put(i, i + 100);
}
IntIterator iterator = map.keys();
for (int i = 0; i < 10000; i++) {
Assert.assertTrue(iterator.hasNext());
Assert.assertEquals(i, iterator.next());
}
Assert.assertFalse(iterator.hasNext());
}

@Test
public void testIntMapByDynamicHashValues() {
IntMap map = new IntMapByDynamicHash();
for (int i = 0; i < 10000; i++) {
map.put(i, i + 100);
}
IntIterator iterator = map.values();
for (int i = 0; i < 10000; i++) {
Assert.assertTrue(iterator.hasNext());
Assert.assertEquals(i + 100, iterator.next());
}
Assert.assertFalse(iterator.hasNext());
}

private IntMap fixed(int capacity) {
return new IntMap.IntMapByFixedAddr(capacity);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@

public class BenchmarkConstants {

public static String OUTPUT_PATH = "./hugegraph-test/target/";
public static String OUTPUT_PATH = "./hugegraph-server/hugegraph-test/target/";
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ public class MapRandomGetPutThroughputTest {

private ConcurrentHashMap<Integer, Integer> concurrentHashMap;

private IntMap.IntMapBySegments intMapBySegments;
private IntMap intMapBySegments;

private IntMapByDynamicHash intMapByDynamicHashNonCap;
private IntMap intMapByDynamicHashNonCap;

private IntMapByDynamicHash intMapByDynamicHash;
private IntMap intMapByDynamicHash;

private static final int THREAD_COUNT = 8;

Expand Down Expand Up @@ -103,7 +103,7 @@ public void randomGetPutOfConcurrentHashMapWithNoneInitCap(ThreadState state) {
@Benchmark
@Threads(THREAD_COUNT)
public void randomGetPutOfConcurrentHashMapWithInitCap(ThreadState state) {
int key = state.next();
int key = state.next() & (MAP_CAPACITY - 1);
if (!this.concurrentHashMap.containsKey(key)) {
this.concurrentHashMap.put(key, state.next());
}
Expand All @@ -112,7 +112,7 @@ public void randomGetPutOfConcurrentHashMapWithInitCap(ThreadState state) {

@Benchmark
@Threads(THREAD_COUNT)
public void randomGetPutOfIntMapBySegments(ThreadState state) {
public void randomGetPutOfIntMapBySegmentsWithInitCap(ThreadState state) {
int key = state.next() & (MAP_CAPACITY - 1);
if (!this.intMapBySegments.containsKey(key)) {
this.intMapBySegments.put(key, state.next());
Expand All @@ -132,8 +132,8 @@ public void randomGetPutOfIntMapByDynamicHashWithNoneCap(ThreadState state) {

@Benchmark
@Threads(THREAD_COUNT)
public void randomGetPutOfIntMapByDynamicHash(ThreadState state) {
int key = state.next();
public void randomGetPutOfIntMapByDynamicHashWithInitCap(ThreadState state) {
int key = state.next() & (MAP_CAPACITY - 1);
if (!this.intMapByDynamicHash.containsKey(key)) {
this.intMapByDynamicHash.put(key, state.next());
}
Expand Down

0 comments on commit 44d03e8

Please sign in to comment.