Skip to content

Commit f485e93

Browse files
committed
add dataloader performance test
1 parent 389bf16 commit f485e93

File tree

2 files changed

+211
-0
lines changed

2 files changed

+211
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package performance;
2+
3+
import graphql.Assert;
4+
import graphql.ExecutionInput;
5+
import graphql.ExecutionResult;
6+
import graphql.GraphQL;
7+
import graphql.schema.DataFetcher;
8+
import graphql.schema.GraphQLSchema;
9+
import graphql.schema.idl.RuntimeWiring;
10+
import graphql.schema.idl.SchemaGenerator;
11+
import graphql.schema.idl.SchemaParser;
12+
import graphql.schema.idl.TypeDefinitionRegistry;
13+
import org.dataloader.BatchLoader;
14+
import org.dataloader.DataLoader;
15+
import org.dataloader.DataLoaderFactory;
16+
import org.dataloader.DataLoaderRegistry;
17+
import org.openjdk.jmh.annotations.Benchmark;
18+
import org.openjdk.jmh.annotations.BenchmarkMode;
19+
import org.openjdk.jmh.annotations.Fork;
20+
import org.openjdk.jmh.annotations.Measurement;
21+
import org.openjdk.jmh.annotations.Mode;
22+
import org.openjdk.jmh.annotations.OutputTimeUnit;
23+
import org.openjdk.jmh.annotations.Scope;
24+
import org.openjdk.jmh.annotations.Setup;
25+
import org.openjdk.jmh.annotations.State;
26+
import org.openjdk.jmh.annotations.Warmup;
27+
import org.openjdk.jmh.infra.Blackhole;
28+
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.concurrent.CompletableFuture;
32+
import java.util.concurrent.TimeUnit;
33+
import java.util.stream.Collectors;
34+
35+
@State(Scope.Benchmark)
36+
@Warmup(iterations = 2, time = 5)
37+
@Measurement(iterations = 3)
38+
@Fork(3)
39+
public class DataLoaderPerformance {
40+
41+
static Owner o1 = new Owner("O-1", "Andi", List.of("P-1", "P-2", "P-3"));
42+
static Owner o2 = new Owner("O-2", "George", List.of("P-4", "P-5", "P-6"));
43+
static Owner o3 = new Owner("O-3", "Peppa", List.of("P-7", "P-8", "P-9", "P-10"));
44+
45+
static Pet p1 = new Pet("P-1", "Bella", "O-1", List.of("P-2", "P-3", "P-4"));
46+
static Pet p2 = new Pet("P-2", "Charlie", "O-2", List.of("P-1", "P-5", "P-6"));
47+
static Pet p3 = new Pet("P-3", "Luna", "O-3", List.of("P-1", "P-2", "P-7", "P-8"));
48+
static Pet p4 = new Pet("P-4", "Max", "O-1", List.of("P-1", "P-9", "P-10"));
49+
static Pet p5 = new Pet("P-5", "Lucy", "O-2", List.of("P-2", "P-6"));
50+
static Pet p6 = new Pet("P-6", "Cooper", "O-3", List.of("P-3", "P-5", "P-7"));
51+
static Pet p7 = new Pet("P-7", "Daisy", "O-1", List.of("P-4", "P-6", "P-8"));
52+
static Pet p8 = new Pet("P-8", "Milo", "O-2", List.of("P-3", "P-7", "P-9"));
53+
static Pet p9 = new Pet("P-9", "Lola", "O-3", List.of("P-4", "P-8", "P-10"));
54+
static Pet p10 = new Pet("P-10", "Rocky", "O-1", List.of("P-4", "P-9"));
55+
56+
static Map<String, Owner> owners = Map.of(
57+
o1.id, o1,
58+
o2.id, o2,
59+
o3.id, o3
60+
);
61+
static Map<String, Pet> pets = Map.of(
62+
p1.id, p1,
63+
p2.id, p2,
64+
p3.id, p3,
65+
p4.id, p4,
66+
p5.id, p5,
67+
p6.id, p6,
68+
p7.id, p7,
69+
p8.id, p8,
70+
p9.id, p9,
71+
p10.id, p10
72+
);
73+
74+
static class Owner {
75+
public Owner(String id, String name, List<String> petIds) {
76+
this.id = id;
77+
this.name = name;
78+
this.petIds = petIds;
79+
}
80+
81+
String id;
82+
String name;
83+
List<String> petIds;
84+
}
85+
86+
static class Pet {
87+
public Pet(String id, String name, String ownerId, List<String> friendsIds) {
88+
this.id = id;
89+
this.name = name;
90+
this.ownerId = ownerId;
91+
this.friendsIds = friendsIds;
92+
}
93+
94+
String id;
95+
String name;
96+
String ownerId;
97+
List<String> friendsIds;
98+
}
99+
100+
101+
static BatchLoader<String, Owner> ownerBatchLoader = list -> {
102+
List<Owner> collect = list.stream().map(key -> {
103+
Owner owner = owners.get(key);
104+
return owner;
105+
}).collect(Collectors.toList());
106+
return CompletableFuture.completedFuture(collect);
107+
};
108+
static BatchLoader<String, Pet> petBatchLoader = list -> {
109+
List<Pet> collect = list.stream().map(key -> {
110+
Pet owner = pets.get(key);
111+
return owner;
112+
}).collect(Collectors.toList());
113+
return CompletableFuture.completedFuture(collect);
114+
};
115+
116+
static final String ownerDLName = "ownerDL";
117+
static final String petDLName = "petDL";
118+
119+
@State(Scope.Benchmark)
120+
public static class MyState {
121+
122+
GraphQLSchema schema;
123+
GraphQL graphQL;
124+
private String query;
125+
126+
@Setup
127+
public void setup() {
128+
try {
129+
String sdl = PerformanceTestingUtils.loadResource("dataLoaderPerformanceSchema.graphqls");
130+
131+
132+
DataLoaderRegistry registry = new DataLoaderRegistry();
133+
134+
DataFetcher ownersDF = (env -> {
135+
return env.getDataLoader(ownerDLName).loadMany(List.of("O-1", "0-2", "O-3"));
136+
});
137+
DataFetcher petsDf = (env -> {
138+
Owner owner = env.getSource();
139+
return env.getDataLoader(petDLName).loadMany((List) owner.petIds);
140+
});
141+
142+
DataFetcher petFriendsDF = (env -> {
143+
Pet pet = env.getSource();
144+
return env.getDataLoader(petDLName).loadMany((List) pet.friendsIds);
145+
});
146+
147+
DataFetcher petOwnerDF = (env -> {
148+
Pet pet = env.getSource();
149+
return env.getDataLoader(ownerDLName).load(pet.ownerId);
150+
});
151+
152+
153+
TypeDefinitionRegistry typeDefinitionRegistry = new SchemaParser().parse(sdl);
154+
RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
155+
.type("Query", builder -> builder
156+
.dataFetcher("owners", ownersDF))
157+
.type("Owner", builder -> builder
158+
.dataFetcher("pets", petsDf))
159+
.type("Pet", builder -> builder
160+
.dataFetcher("friends", petFriendsDF)
161+
.dataFetcher("owner", petOwnerDF))
162+
.build();
163+
164+
query = "{owners{name pets { name friends{name owner {name }}}}}";
165+
166+
schema = new SchemaGenerator().makeExecutableSchema(typeDefinitionRegistry, runtimeWiring);
167+
168+
graphQL = GraphQL.newGraphQL(schema).build();
169+
170+
} catch (Exception e) {
171+
throw new RuntimeException(e);
172+
}
173+
}
174+
175+
}
176+
177+
@Benchmark
178+
@BenchmarkMode(Mode.AverageTime)
179+
@OutputTimeUnit(TimeUnit.MILLISECONDS)
180+
public void executeRequestWithDataLoaders(MyState myState, Blackhole blackhole) {
181+
DataLoader ownerDL = DataLoaderFactory.newDataLoader(ownerBatchLoader);
182+
DataLoader petDL = DataLoaderFactory.newDataLoader(petBatchLoader);
183+
184+
DataLoaderRegistry registry = DataLoaderRegistry.newRegistry().register(ownerDLName, ownerDL).register(petDLName, petDL).build();
185+
186+
ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(myState.query).dataLoaderRegistry(registry).build();
187+
ExecutionResult execute = myState.graphQL.execute(executionInput);
188+
Assert.assertTrue(execute.isDataPresent());
189+
Assert.assertTrue(execute.getErrors().isEmpty());
190+
blackhole.consume(execute);
191+
}
192+
193+
194+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
type Query {
2+
owners: [Owner]
3+
}
4+
5+
type Owner {
6+
id: ID!
7+
name: String
8+
pets: [Pet]
9+
}
10+
11+
type Pet {
12+
id: ID!
13+
name: String
14+
owner: Owner
15+
friends: [Pet]
16+
}
17+

0 commit comments

Comments
 (0)