Skip to content

Commit ec21880

Browse files
committed
Add repository benchmarks.
See: #4939 Original Pull Request: #4970
1 parent 2e52276 commit ec21880

File tree

3 files changed

+713
-0
lines changed

3 files changed

+713
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.repository;
17+
18+
import org.junit.platform.commons.annotation.Testable;
19+
import org.openjdk.jmh.annotations.Benchmark;
20+
import org.openjdk.jmh.annotations.Level;
21+
import org.openjdk.jmh.annotations.Scope;
22+
import org.openjdk.jmh.annotations.Setup;
23+
import org.openjdk.jmh.annotations.State;
24+
import org.openjdk.jmh.annotations.TearDown;
25+
26+
import org.springframework.aot.test.generate.TestGenerationContext;
27+
import org.springframework.core.test.tools.TestCompiler;
28+
import org.springframework.data.mongodb.core.MongoOperations;
29+
import org.springframework.data.mongodb.core.MongoTemplate;
30+
import org.springframework.data.mongodb.microbenchmark.AbstractMicrobenchmark;
31+
import org.springframework.data.mongodb.repository.aot.MongoRepositoryContributor;
32+
import org.springframework.data.mongodb.repository.aot.TestMongoAotRepositoryContext;
33+
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
34+
import org.springframework.data.mongodb.repository.support.QuerydslMongoPredicateExecutor;
35+
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;
36+
import org.springframework.data.projection.ProjectionFactory;
37+
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
38+
import org.springframework.data.repository.core.RepositoryMetadata;
39+
import org.springframework.data.repository.core.support.RepositoryComposition;
40+
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
41+
import org.springframework.data.repository.core.support.RepositoryFragment;
42+
import org.springframework.data.repository.query.ValueExpressionDelegate;
43+
44+
import com.mongodb.client.MongoClient;
45+
import com.mongodb.client.MongoClients;
46+
47+
/**
48+
* Benchmark for AOT repositories.
49+
*
50+
* @author Mark Paluch
51+
*/
52+
@Testable
53+
public class AotRepositoryBenchmark extends AbstractMicrobenchmark {
54+
55+
@State(Scope.Benchmark)
56+
public static class BenchmarkParameters {
57+
58+
public static Class<?> aot;
59+
public static TestMongoAotRepositoryContext repositoryContext = new TestMongoAotRepositoryContext(
60+
SmallerPersonRepository.class,
61+
RepositoryComposition.of(RepositoryFragment.structural(SimpleMongoRepository.class),
62+
RepositoryFragment.structural(QuerydslMongoPredicateExecutor.class)));
63+
64+
MongoClient mongoClient;
65+
MongoTemplate mongoTemplate;
66+
RepositoryComposition.RepositoryFragments fragments;
67+
SmallerPersonRepository repositoryProxy;
68+
69+
@Setup(Level.Trial)
70+
public void doSetup() {
71+
72+
mongoClient = MongoClients.create();
73+
mongoTemplate = new MongoTemplate(mongoClient, "jmh");
74+
75+
if (this.aot == null) {
76+
77+
TestGenerationContext generationContext = new TestGenerationContext(PersonRepository.class);
78+
79+
new MongoRepositoryContributor(repositoryContext).contribute(generationContext);
80+
81+
TestCompiler.forSystem().withCompilerOptions("-parameters").with(generationContext).compile(compiled -> {
82+
83+
try {
84+
this.aot = compiled.getClassLoader().loadClass(SmallerPersonRepository.class.getName() + "Impl__Aot");
85+
} catch (Exception e) {
86+
throw new RuntimeException(e);
87+
}
88+
});
89+
}
90+
91+
try {
92+
RepositoryFactoryBeanSupport.FragmentCreationContext creationContext = getCreationContext(repositoryContext);
93+
fragments = RepositoryComposition.RepositoryFragments
94+
.just(aot.getConstructor(MongoOperations.class, RepositoryFactoryBeanSupport.FragmentCreationContext.class)
95+
.newInstance(mongoTemplate, creationContext));
96+
97+
this.repositoryProxy = createRepository(fragments);
98+
} catch (Exception e) {
99+
throw new RuntimeException(e);
100+
}
101+
}
102+
103+
private RepositoryFactoryBeanSupport.FragmentCreationContext getCreationContext(
104+
TestMongoAotRepositoryContext repositoryContext) {
105+
106+
RepositoryFactoryBeanSupport.FragmentCreationContext creationContext = new RepositoryFactoryBeanSupport.FragmentCreationContext() {
107+
@Override
108+
public RepositoryMetadata getRepositoryMetadata() {
109+
return repositoryContext.getRepositoryInformation();
110+
}
111+
112+
@Override
113+
public ValueExpressionDelegate getValueExpressionDelegate() {
114+
return ValueExpressionDelegate.create();
115+
}
116+
117+
@Override
118+
public ProjectionFactory getProjectionFactory() {
119+
return new SpelAwareProxyProjectionFactory();
120+
}
121+
};
122+
123+
return creationContext;
124+
}
125+
126+
@TearDown(Level.Trial)
127+
public void doTearDown() {
128+
mongoClient.close();
129+
}
130+
131+
public SmallerPersonRepository createRepository(RepositoryComposition.RepositoryFragments fragments) {
132+
MongoRepositoryFactory repositoryFactory = new MongoRepositoryFactory(mongoTemplate);
133+
return repositoryFactory.getRepository(SmallerPersonRepository.class, fragments);
134+
}
135+
136+
}
137+
138+
@Benchmark
139+
public SmallerPersonRepository repositoryBootstrap(BenchmarkParameters parameters) {
140+
return parameters.createRepository(parameters.fragments);
141+
}
142+
143+
@Benchmark
144+
public Object findDerived(BenchmarkParameters parameters) {
145+
return parameters.repositoryProxy.findByFirstname("foo");
146+
}
147+
148+
@Benchmark
149+
public Object findAnnotated(BenchmarkParameters parameters) {
150+
return parameters.repositoryProxy.findByThePersonsFirstname("foo");
151+
}
152+
153+
}

0 commit comments

Comments
 (0)