Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ public class FieldLevelTrackingApproach {

private static class CallStack implements InstrumentationState {

private final IntMap expectedFetchCountPerLevel = new IntMap();
private final IntMap fetchCountPerLevel = new IntMap();
private final IntMap expectedStrategyCallsPerLevel = new IntMap();
private final IntMap happenedStrategyCallsPerLevel = new IntMap();
private final IntMap happenedOnFieldValueCallsPerLevel = new IntMap();
private final LevelMap expectedFetchCountPerLevel = new LevelMap();
private final LevelMap fetchCountPerLevel = new LevelMap();
private final LevelMap expectedStrategyCallsPerLevel = new LevelMap();
private final LevelMap happenedStrategyCallsPerLevel = new LevelMap();
private final LevelMap happenedOnFieldValueCallsPerLevel = new LevelMap();

private final Set<Integer> dispatchedLevels = new LinkedHashSet<>();

CallStack() {
expectedStrategyCallsPerLevel.increment(1, 1);
expectedStrategyCallsPerLevel.set(1, 1);
}

void increaseExpectedFetchCount(int level, int count) {
Expand Down Expand Up @@ -95,11 +95,11 @@ public boolean dispatchIfNotDispatchedBefore(int level) {
}

public void clearAndMarkCurrentLevelAsReady(int level) {
expectedFetchCountPerLevel.reset();
fetchCountPerLevel.reset();
expectedStrategyCallsPerLevel.reset();
happenedStrategyCallsPerLevel.reset();
happenedOnFieldValueCallsPerLevel.reset();
expectedFetchCountPerLevel.clear();
fetchCountPerLevel.clear();
expectedStrategyCallsPerLevel.clear();
happenedStrategyCallsPerLevel.clear();
happenedOnFieldValueCallsPerLevel.clear();
dispatchedLevels.clear();

// make sure the level is ready
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,26 @@

import java.util.Arrays;

/**
* This data structure tracks the number of expected calls on a given level
*/
@Internal
public class IntMap {
public class LevelMap {

// A reasonable default that guarantees no additional allocations for most use cases.
private static final int DEFAULT_INITIAL_SIZE = 16;

// this array is mutable in both size and contents.
private int[] countsByLevel;

public IntMap(int initialSize) {
public LevelMap(int initialSize) {
if (initialSize < 0) {
throw new IllegalArgumentException("negative size " + initialSize);
}
countsByLevel = new int[initialSize];
}

public IntMap() {
public LevelMap() {
this(DEFAULT_INITIAL_SIZE);
}

Expand All @@ -35,14 +38,23 @@ public int get(int level) {
}

public void increment(int level, int by) {
mutatePreconditions(level);
countsByLevel[level] += by;
}

public void set(int level, int newValue) {
mutatePreconditions(level);
countsByLevel[level] = newValue;
}

private void mutatePreconditions(int level) {
if (level < 0) {
throw new IllegalArgumentException("negative level " + level);
}
if (level + 1 > countsByLevel.length) {
int newSize = level == 0 ? 1 : level * 2;
countsByLevel = Arrays.copyOf(countsByLevel, newSize);
}
countsByLevel[level] += by;
}

@Override
Expand All @@ -56,7 +68,7 @@ public String toString() {
return result.toString();
}

public void reset() {
public void clear() {
Arrays.fill(countsByLevel, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package graphql.execution.instrumentation.dataloader

import spock.lang.Specification

class IntMapTest extends Specification {
class LevelMapTest extends Specification {

def "increase adds levels"() {
given:
IntMap sut = new IntMap(0) // starts empty
LevelMap sut = new LevelMap(0) // starts empty

when:
sut.increment(2, 42) // level 2 has count 42
Expand All @@ -19,7 +19,7 @@ class IntMapTest extends Specification {

def "increase count by 10 for every level"() {
given:
IntMap sut = new IntMap(0)
LevelMap sut = new LevelMap(0)

when:
5.times {Integer level ->
Expand All @@ -31,10 +31,9 @@ class IntMapTest extends Specification {
sut.get(level) == 10
}
}

def "increase yields new count"() {
given:
IntMap sut = new IntMap(0)
LevelMap sut = new LevelMap(0)

when:
sut.increment(1, 0)
Expand All @@ -55,9 +54,32 @@ class IntMapTest extends Specification {
sut.get(1) == 101
}

def "set yields new value"() {
given:
LevelMap sut = new LevelMap(0)

when:
sut.set(1, 1)

then:
sut.get(1) == 1

when:
sut.increment(1, 100)

then:
sut.get(1) == 101

when:
sut.set(1, 666)

then:
sut.get(1) == 666
}

def "toString() is important for debugging"() {
given:
IntMap sut = new IntMap(0)
LevelMap sut = new LevelMap(0)

when:
sut.toString()
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/benchmark/IntMapBenchmark.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package benchmark;

import graphql.execution.instrumentation.dataloader.IntMap;
import graphql.execution.instrumentation.dataloader.LevelMap;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Measurement;
Expand Down Expand Up @@ -33,7 +33,7 @@ public void benchmarkLinkedHashMap(Blackhole blackhole) {

@Benchmark
public void benchmarkIntMap(Blackhole blackhole) {
IntMap result = new IntMap(16);
LevelMap result = new LevelMap(16);
for (int i = 0; i < 30; i++) {
int level = i % 10;
int count = i * 2;
Expand Down