java - Caliper 基准测试期间绑定(bind)实例

标签 java guice caliper

我最近的任务是对我们 API 的一些功能进行基准测试,并且我一直在使用 Caliper 来执行此操作。它看起来相当简单,实际上非常强大,我一直在关注这里的教程:

How to use caliper

Tutorial from the creator

我正在当前的应用程序中使用 Guice,因此当我尝试运行基准测试时,我确保注入(inject)我需要的服务

下面提供的是我的代码。我尝试使用变量自己的 @injected 注释来设置变量,我尝试直接启动它们(尽管有太多的依赖项需要处理,而且我也必须启动它们)。 @Parms 注释不起作用,因为我需要一个字符串类型来迭代(parms 只接受字符串,有文档说明如果它是另一种类型该怎么做,但它需要一个 .toString类型方法)

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;
    }
}

当我们尝试运行它时

mvn exec:java -Dexec.mainClass="com.google.caliper.runner.CaliperMain" -Dexec.args="com.~~~.~~~.api.benchmark.CampaignBenchmark"

我们得到以下内容

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.

问题是:我应该在什么时候进行注入(inject),以及如何进行注入(inject)?我应该有一个包装类设置吗?

快速更新

我忘了提及它是 DropWizard (0.7.1) 应用程序的一部分。我们使用资源并将它们注入(inject)环境中

例如:

environment.jersey().register(injector.getInstance(CampaignManagementResource.class));

这些资源包含运行它们所需的服务,并且它们作为 @Inject 包含在内,尽管我们从未在其他地方实际指定绑定(bind)。

@Inject
private CampaignMetadataService apiCampaignMetadataService;

我应该为 DropWizard 调整一些东西,还是应该模拟服务?

最佳答案

将 Guice 视为一个哈希表。使用 Guice 的工作包含以下部分:

  • 创建哈希表
  • 把东西放进去
  • 从中获取东西

您的代码创建哈希表并查询它,但从未在其中放入任何内容:

public CampaignBenchmark() {
    // Creating the hashtable
    Injector injector = Guice.createInjector();
    // Retrieving from the hashtable
    this.userService = injector.getInstance(UserService.class);
    this.campaignMetadataService = injector.getInstance(CampaignMetadataService.class);
}

Guice 哈希表填充在 Module 中类。毫无疑问,你有一个CampaignModuleAdvertisingModule躺在某处。它可能看起来像这样:

public class CampaignModule extends AbstractModule {
  @Override protected void configure() {
    bind(CampaignMetadataService.class).to(CampaignMetadataServiceImplementation.class);
}

它的作用是输入 <CampaignMetadataService, CampaignMetadataServiceImplementation>进入 Guice 哈希表。展望 future ,无论谁请求 CampaignMetadataService 的实例,接收 CampaignMetadataServiceImplementation 的实例.

所以在你的代码中,你需要让 Guice 了解这个模块:

public CampaignBenchmark() {
    // Creating the hashtable and letting modules populate it
    Injector injector = Guice.createInjector(new CampaignModule(), new UserModule());
    // Retrieving from the hashtable
    this.userService = injector.getInstance(UserService.class);
    this.campaignMetadataService = injector.getInstance(CampaignMetadataService.class);
}

你做的其他事情都很好。旁注:@Inject构造函数和字段上的注释不会执行任何操作,因为您从未要求 Guice 为您提供 CampaignBenchmark 的实例。 。这些可以直接删除。

关于java - Caliper 基准测试期间绑定(bind)实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57485872/

相关文章:

java - guava-11.0.1.jar 和 eclipse 的 Maven 插件

Java 小程序鼓包

java - 使用 java 的 linux 的 mv 命令

java - GWT+Spring+Hibernate 错误 404

java - 在 Guice 中管理同一依赖树的多个版本的最佳模式是什么?

java - 如何获取我们自定义的AlertDialog的值?

scala - 使用 akka 和 scala 实现请求/响应协议(protocol)的最佳方法是什么?

java - 你有什么替代注释的方法?

java - Caliper:如何运行多个基准测试?