I've recently been tasked with benchmarking some features of our API, and I've been using Caliper to do so. It seems fairly straightforward and is actually quite powerful, I've been following the tutorials here:
I'm working with Guice in our current app, so when I try to run the benchmark, I make sure to inject the services I need
Provided below is my code. I've tried setting the variables with their own @injected
annotation, I've tried initiating them directly (although there's too many dependencies to deal with, and I'd have to initiate them as well). @Parms
annotation won't work because I need to have a string type to iterate through (the parms only takes strings, there's documentation of what to do if it's another type, but it needs a .toString
type method)
package com.~~~.~~~.api.benchmark;
import com.~~~.ds.mongo.orm.user.User;
import com.~~~.~~~.api.exceptions.auth.AccessDeniedException;
import com.~~~.~~~.api.service.authorization.UserService;
import com.~~~.~~~.api.service.campaign.CampaignMetadataService;
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import com.google.caliper.Param;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class CampaignBenchmark {
// === SERVICE INJECTIONS
@Inject
private CampaignMetadataService campaignMetadataService;
@Inject
private UserService userService;
// =============================================
// === BENCHMARK PARMS
@Param({
"7ca8c319",
"49191829"
})
String userId;
@Param({
"485",
"500"
})
String hashAdvertiserId;
// =============================================
// === TESTING PARMS
private User user;
// =============================================
// === SETUP
@Inject
public CampaignBenchmark(){
Injector injector = Guice.createInjector();
this.userService = injector.getInstance(UserService.class);
this.campaignMetadataService = injector.getInstance(CampaignMetadataService.class);
}
@BeforeExperiment
void setUp(){
this.user = userService.getUserByHashedId(userId);
}
// =============================================
// === BENCHMARKS
@Benchmark
int fetchAllCampaign(int reps) throws AccessDeniedException {
VideoIqUser user = this.user;
String hashAdvertiserId = this.hashAdvertiserId;
int dummy = 0;
for(int i=0 ; i<reps ; i++){
dummy |= campaignMetadataService.fetchAllCampaigns(user, hashAdvertiserId).size();
}
return dummy;
}
}
When we try to run it with
mvn exec:java -Dexec.mainClass="com.google.caliper.runner.CaliperMain" -Dexec.args="com.~~~.~~~.api.benchmark.CampaignBenchmark"
We get the following
WARNING: All illegal access operations will be denied in a future release
Experiment selection:
Benchmark Methods: [fetchAllCampaign]
Instruments: [allocation, runtime]
User parameters: {hashAdvertiserId=[485, 500], userId=[7ca8c319, 49191829]}
Virtual machines: [default]
Selection type: Full cartesian product
This selection yields 16 experiments.
Could not create an instance of the benchmark class following reasons:
1) Explicit bindings are required and com.~~~.~~~.api.service.campaign.CampaignMetadataService is not explicitly bound.
2) Explicit bindings are required and com.~~~.~~~.api.service.authorization.UserService is not explicitly bound.
The question is: at what point should I be doing injections, and how do I go about that? Should I have a wrapper class setup?
Quick Update
I forgot to mention that is part of a DropWizard (0.7.1) application. We use resources and inject them into the environment
Ex:
environment.jersey().register(injector.getInstance(CampaignManagementResource.class));
These resources contain the services needed to run them, and they are included as @Inject, though we never actually specify a binding anywhere else.
@Inject
private CampaignMetadataService apiCampaignMetadataService;
Is there something I should adjust for DropWizard, or should I just mock up the services?