diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 98b9a634362..f626e197067 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -26,3 +26,5 @@ jobs: CTP_CLIENT_SECRET: ${{ secrets.CTP_CLIENT_SECRET_PR }} CTP_PROJECT_KEY: ${{ secrets.CTP_PROJECT_KEY_PR }} CTP_JVM_SDK_LOG_LEVEL: OFF + - name: Output results + run: cat commercetools/commercetools-sdk-compat-v1/build/results/jmh/results.txt diff --git a/commercetools/commercetools-sdk-compat-v1/build.gradle b/commercetools/commercetools-sdk-compat-v1/build.gradle index 50e981956e9..28d04e2e894 100644 --- a/commercetools/commercetools-sdk-compat-v1/build.gradle +++ b/commercetools/commercetools-sdk-compat-v1/build.gradle @@ -3,9 +3,10 @@ apply plugin: "me.champeau.jmh" jmh { iterations = 10 benchmarkMode = ['thrpt', 'avgt'] - threads = 25 - fork = 3 - timeOnIteration = '1s' + threads = 10 + fork = 1 + timeOnIteration = '3s' + excludes = ['.*retrieveProject.*'] } dependencies { @@ -23,6 +24,7 @@ dependencies { jmhImplementation project(':commercetools:commercetools-async-http-client') jmhImplementation project(':commercetools:commercetools-apachehttp-client') + jmhImplementation ctsdkv1.http version ctsdkv1.version testImplementation project(':commercetools:commercetools-http-client') testImplementation ctsdkv1.client version ctsdkv1.version testImplementation ctsdkv1.models version ctsdkv1.version diff --git a/commercetools/commercetools-sdk-compat-v1/src/jmh/java/com/commercetools/benchmark/ClientBenchmark.java b/commercetools/commercetools-sdk-compat-v1/src/jmh/java/com/commercetools/benchmark/ClientBenchmark.java index b3095eda06a..cf6753ff676 100644 --- a/commercetools/commercetools-sdk-compat-v1/src/jmh/java/com/commercetools/benchmark/ClientBenchmark.java +++ b/commercetools/commercetools-sdk-compat-v1/src/jmh/java/com/commercetools/benchmark/ClientBenchmark.java @@ -2,21 +2,34 @@ package com.commercetools.benchmark; import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import com.commercetools.api.client.ApiInternalLoggerFactory; import com.commercetools.api.client.ProjectApiRoot; import com.commercetools.api.defaultconfig.ApiRootBuilder; import com.commercetools.api.defaultconfig.ServiceRegion; +import com.commercetools.api.models.common.LocalizedString; +import com.commercetools.api.models.product.Product; +import com.commercetools.api.models.product.ProductProjectionPagedQueryResponse; +import com.commercetools.api.models.product_type.AttributeTypeBuilder; +import com.commercetools.api.models.product_type.ProductType; +import com.commercetools.api.models.tax_category.TaxCategory; import com.commercetools.compat.CompatSphereClient; import com.commercetools.http.apachehttp.CtApacheHttpClient; import com.commercetools.http.asynchttp.CtAsyncHttpClient; import com.commercetools.http.okhttp4.CtOkHttp4Client; -import io.sphere.sdk.client.BlockingSphereClient; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.client.SphereClientFactory; +import io.sphere.sdk.client.*; +import io.sphere.sdk.products.ProductProjection; +import io.sphere.sdk.products.queries.ProductProjectionQuery; import io.sphere.sdk.projects.queries.ProjectGet; +import io.sphere.sdk.queries.PagedQueryResult; +import io.vrap.rmf.base.client.ApiHttpResponse; import io.vrap.rmf.base.client.oauth2.ClientCredentials; +import org.assertj.core.api.Assertions; import org.openjdk.jmh.annotations.*; public class ClientBenchmark { @@ -30,46 +43,158 @@ public static class ClientState { private BlockingSphereClient sphereClient; + private BlockingSphereClient sphereApacheClient; + private BlockingSphereClient compatClient; + private BlockingSphereClient compatOkHttpClient; + + private BlockingSphereClient compatApacheClient; + + private List productsList; + + private TaxCategory taxCategory; + + private ProductType productType; + @Setup(Level.Trial) public void init() { ahcApiRoot = ApiRootBuilder.of(new CtAsyncHttpClient()) .defaultClient( ClientCredentials.of().withClientId(getClientId()).withClientSecret(getClientSecret()).build(), ServiceRegion.GCP_EUROPE_WEST1) + .withInternalLoggerFactory(ApiInternalLoggerFactory::get, org.slf4j.event.Level.DEBUG, + org.slf4j.event.Level.DEBUG) .build(getProjectKey()); apacheApiRoot = ApiRootBuilder.of(new CtApacheHttpClient()) .defaultClient( ClientCredentials.of().withClientId(getClientId()).withClientSecret(getClientSecret()).build(), ServiceRegion.GCP_EUROPE_WEST1) + .withInternalLoggerFactory(ApiInternalLoggerFactory::get, org.slf4j.event.Level.DEBUG, + org.slf4j.event.Level.DEBUG) .build(getProjectKey()); okhttpApiRoot = ApiRootBuilder.of(new CtOkHttp4Client()) .defaultClient( ClientCredentials.of().withClientId(getClientId()).withClientSecret(getClientSecret()).build(), ServiceRegion.GCP_EUROPE_WEST1) + .withInternalLoggerFactory(ApiInternalLoggerFactory::get, org.slf4j.event.Level.DEBUG, + org.slf4j.event.Level.DEBUG) .build(getProjectKey()); - final SphereClientFactory factory = SphereClientFactory.of(); + final SphereClientFactory factory = SphereClientFactory.of(SphereAsyncHttpClientFactory::create); final SphereClient client = factory.createClient(getProjectKey(), //replace with your project key getClientId(), //replace with your client id getClientSecret()); //replace with your client secret sphereClient = BlockingSphereClient.of(client, Duration.ofSeconds(10)); + final SphereClientFactory apacheFactory = SphereClientFactory.of(SphereApacheHttpClientFactory::create); + final SphereClient apacheClient = apacheFactory.createClient(getProjectKey(), //replace with your project key + getClientId(), //replace with your client id + getClientSecret()); //replace with your client secret + + sphereApacheClient = BlockingSphereClient.of(apacheClient, Duration.ofSeconds(10)); + compatClient = BlockingSphereClient.of(CompatSphereClient.of(ahcApiRoot), Duration.ofSeconds(10)); + + compatOkHttpClient = BlockingSphereClient.of(CompatSphereClient.of(okhttpApiRoot), Duration.ofSeconds(10)); + + compatApacheClient = BlockingSphereClient.of(CompatSphereClient.of(apacheApiRoot), Duration.ofSeconds(10)); + + productType = createProductType(); + + taxCategory = createTaxCategory(); + productsList = createProducts(taxCategory, productType); } @TearDown(Level.Trial) public void tearDown() { + deleteProducts(productsList); + deleteProductType(productType); + deleteTaxCategory(taxCategory); ahcApiRoot.close(); compatClient.close(); + compatOkHttpClient.close(); + compatApacheClient.close(); apacheApiRoot.close(); + sphereApacheClient.close(); okhttpApiRoot.close(); sphereClient.close(); } + + public ProductType createProductType() { + String suffix = randomKey(); + return ahcApiRoot.productTypes() + .create(builder -> builder.key("benchmark-" + suffix) + .name("benchmark") + .description("benchmark") + .plusAttributes(attributeBuilder -> attributeBuilder.type(AttributeTypeBuilder::textBuilder) + .isRequired(false) + .name("benchmark-color") + .isSearchable(true) + .label(LocalizedString.ofEnglish("color")))) + .executeBlocking() + .getBody(); + } + + private TaxCategory createTaxCategory() { + String suffix = randomKey(); + return ahcApiRoot.taxCategories() + .create(builder -> builder.key("benchmark-" + suffix) + .name("benchmark-" + suffix) + .description("benchmark-" + suffix) + .plusRates(rateBuilder -> rateBuilder.name("Mwst") + .country("DE") + .amount(0.19) + .includedInPrice(true))) + .executeBlocking() + .getBody(); + } + + private List createProducts(TaxCategory taxCategory, ProductType productType) { + String productSuffix = randomKey(); + List products = new ArrayList<>(); + for (int i = 0; i < 150; i++) { + String suffix = productSuffix + "-" + i; + Product product = ahcApiRoot.products() + .create( + builder -> builder.key("benchmark-" + suffix) + .productType(p -> p.id(productType.getId())) + .taxCategory(t -> t.id(taxCategory.getId())) + .name(LocalizedString.ofEnglish("benchmark-" + suffix)) + .slug(LocalizedString.ofEnglish("benchmark-" + suffix)) + .description(LocalizedString.ofEnglish("benchmark-" + suffix)) + .masterVariant(variantBuilder -> variantBuilder.key("benchmark-variant1-" + suffix) + .sku("benchmark-variant1-" + suffix) + .plusPrices(price -> price.country("DE") + .value(moneyBuilder -> moneyBuilder.centAmount(100L) + .currencyCode("EUR"))) + .plusAttributes( + attribute -> attribute.name("benchmark-color").value("red" + suffix)))) + .executeBlocking() + .getBody(); + products.add(product); + } + return products; + } + + private void deleteProducts(List products) { + products.forEach(product -> ahcApiRoot.products().delete(product).executeBlocking()); + } + + private void deleteProductType(ProductType productType) { + ahcApiRoot.productTypes().delete(productType).executeBlocking(); + } + + private void deleteTaxCategory(TaxCategory taxCategory) { + ahcApiRoot.taxCategories().delete(taxCategory).executeBlocking(); + } + + public static String randomKey() { + return "random-key-" + UUID.randomUUID().toString(); + } } @Benchmark @@ -92,11 +217,89 @@ public void retrieveProjectV1_AHC(ClientState state) { state.sphereClient.executeBlocking(ProjectGet.of()); } + @Benchmark + public void retrieveProjectV1_Apache(ClientState state) { + state.sphereApacheClient.executeBlocking(ProjectGet.of()); + } + @Benchmark public void retrieveProjectV2_Compat(ClientState state) { state.compatClient.executeBlocking(ProjectGet.of()); } + @Benchmark + public void retrieveProjectV2_CompatOkHttp(ClientState state) { + state.compatOkHttpClient.executeBlocking(ProjectGet.of()); + } + + @Benchmark + public void retrieveProductsV1_AHC(ClientState state) { + final PagedQueryResult response = state.sphereClient + .executeBlocking(ProductProjectionQuery.ofStaged().withLimit(100)); + Assertions.assertThat(response.getCount()).isEqualTo(100); + } + + @Benchmark + public void retrieveProductsV2_CompatAHC(ClientState state) { + final PagedQueryResult response = state.compatClient + .executeBlocking(ProductProjectionQuery.ofStaged().withLimit(100)); + Assertions.assertThat(response.getCount()).isEqualTo(100); + } + + @Benchmark + public void retrieveProductsV2_AHC(ClientState state) { + final ApiHttpResponse response = state.ahcApiRoot.productProjections() + .get() + .withStaged(true) + .withLimit(100) + .executeBlocking(); + Assertions.assertThat(response.getBody().getCount()).isEqualTo(100); + + } + + @Benchmark + public void retrieveProductsV1_Apache(ClientState state) { + final PagedQueryResult response = state.sphereApacheClient + .executeBlocking(ProductProjectionQuery.ofStaged().withLimit(100)); + Assertions.assertThat(response.getCount()).isEqualTo(100); + } + + @Benchmark + public void retrieveProductsV2_CompatApache(ClientState state) { + final PagedQueryResult response = state.compatApacheClient + .executeBlocking(ProductProjectionQuery.ofStaged().withLimit(100)); + Assertions.assertThat(response.getCount()).isEqualTo(100); + } + + @Benchmark + public void retrieveProductsV2_Apache(ClientState state) { + final ApiHttpResponse response = state.apacheApiRoot.productProjections() + .get() + .withStaged(true) + .withLimit(100) + .executeBlocking(); + + Assertions.assertThat(response.getBody().getCount()).isEqualTo(100); + } + + @Benchmark + public void retrieveProductsV2_CompatOkHttp(ClientState state) { + final PagedQueryResult response = state.compatOkHttpClient + .executeBlocking(ProductProjectionQuery.ofStaged().withLimit(100)); + Assertions.assertThat(response.getCount()).isEqualTo(100); + } + + @Benchmark + public void retrieveProductsV2_OkHtp(ClientState state) { + final ApiHttpResponse response = state.okhttpApiRoot.productProjections() + .get() + .withStaged(true) + .withLimit(100) + .executeBlocking(); + + Assertions.assertThat(response.getBody().getCount()).isEqualTo(100); + } + public static String getProjectKey() { return System.getenv("CTP_PROJECT_KEY"); } diff --git a/commercetools/commercetools-sdk-compat-v1/src/jmh/resources/logback-test.xml b/commercetools/commercetools-sdk-compat-v1/src/jmh/resources/logback-test.xml index 4fcc733a225..9a448740e59 100644 --- a/commercetools/commercetools-sdk-compat-v1/src/jmh/resources/logback-test.xml +++ b/commercetools/commercetools-sdk-compat-v1/src/jmh/resources/logback-test.xml @@ -11,7 +11,7 @@ - + diff --git a/gradle-scripts/extensions.gradle b/gradle-scripts/extensions.gradle index 8e0ef5c905c..d385bfb6ba1 100644 --- a/gradle-scripts/extensions.gradle +++ b/gradle-scripts/extensions.gradle @@ -7,6 +7,7 @@ ext { client: 'com.commercetools.sdk.jvm.core:commercetools-java-client-core:2.9.0', models: 'com.commercetools.sdk.jvm.core:commercetools-models:2.9.0', convenience: 'com.commercetools.sdk.jvm.core:commercetools-convenience:2.9.0', + http: 'com.commercetools.sdk.jvm.core:commercetools-java-client-ahc-2_12:2.9.0', version: { strictly '[1.62.0,)' prefer '2.9.0'