“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”

How well does Quarkus perform when connecting to a database based on Insert performance?

Server Configuration

CentOS Linux release 7.6.1810 (Core)

Intel(R) Xeon(R) Gold 6278C CPU @ 2.60GHz

4C8G
Copy the code

The performance test

The database is PG, if you like Mysql, same thing.

The test sample

The data model

CREATE TABLE "public"."dynamic_info" (
    "id" int8 NOT NULL,
    "dynamic_type" int2,
    "dynamic_desc" varchar,
    "creator" varchar,
    "created_time" timestamp.PRIMARY KEY ("id")
);
Copy the code

Map the entity DynamicInfo

package org.mxx.pg.domain;

import com.google.common.collect.Lists;
import io.vertx.mutiny.sqlclient.Row;
import io.vertx.mutiny.sqlclient.RowSet;
import java.time.LocalDateTime;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;

<br> * <p>Created Time: 2021/7/8 PM 2:20 </p> **@author<a href="mail to: [email protected]" rel="nofollow"> </a> */
@Entity(name = "dynamic_info")
public class DynamicInfo {

    @Id
    private Long id;
    private Integer dynamicType;
    private String dynamicDesc;
    private String creator;
    private LocalDateTime createdTime;

    public static DynamicInfo from(Row row) {
        return new DynamicInfo(
            row.getLong("id"),
            row.getInteger("dynamic_type"),
            row.getString("dynamic_desc"),
            row.getString("creator"),
            row.getLocalDateTime("created_time")); }public static List<DynamicInfo> froms(RowSet<Row> rows) {
        List<DynamicInfo> result = Lists.newArrayList();
        rows.forEach(row -> {
            result.add(from(row));
        });
        return result;
    }

    public DynamicInfo(a) {}public DynamicInfo(Long id, Integer dynamicType, String dynamicDesc, String creator, LocalDateTime createdTime) {
        this.id = id;
        this.dynamicType = dynamicType;
        this.dynamicDesc = dynamicDesc;
        this.creator = creator;
        this.createdTime = createdTime;
    }

    public Long getId(a) {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getDynamicType(a) {
        return dynamicType;
    }

    public void setDynamicType(Integer dynamicType) {
        this.dynamicType = dynamicType;
    }

    public String getDynamicDesc(a) {
        return dynamicDesc;
    }

    public void setDynamicDesc(String dynamicDesc) {
        this.dynamicDesc = dynamicDesc;
    }

    public String getCreator(a) {
        return creator;
    }

    public void setCreator(String creator) {
        this.creator = creator;
    }

    public LocalDateTime getCreatedTime(a) {
        return createdTime;
    }

    public void setCreatedTime(LocalDateTime createdTime) {
        this.createdTime = createdTime; }}Copy the code

Create BaseRepository

package org.mxx.config.base;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import io.quarkus.reactive.datasource.ReactiveDataSource;
import io.vertx.mutiny.pgclient.PgPool;
import javax.inject.Inject;

/**
 * Description: Pg .<br>
 * <p>Created Time: 2021/6/8 δΈ‹εˆ4:40 </p>
 *
 * @author<a href="mail to: [email protected]" rel="nofollow"> </a> */
public class BasePgRepository {
    @Inject
    @ReactiveDataSource("pg")
    protected PgPool pgPool;

    protected Snowflake snowflake = IdUtil.getSnowflake(1.1);
}

Copy the code

Create a Repository for entities

package org.mxx.pg.repository;

import io.smallrye.mutiny.Uni;
import io.vertx.mutiny.sqlclient.Tuple;
import java.time.LocalDateTime;
import java.util.Date;
import javax.inject.Singleton;
import org.mxx.config.base.BasePgRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

<br> * <p>Created Time: 2021/7/8 PM 2:27 </p> **@author<a href="mail to: [email protected]" rel="nofollow"> </a> */
@Singleton
public class DynamicInfoRepository extends BasePgRepository {
    private static final Logger LOGGER = LoggerFactory.getLogger(DynamicInfoRepository.class);

    public Uni<Long> addDynamicInfo(a) {
        return pgPool.preparedQuery(
            "insert into dynamic_info (id,dynamic_type,dynamic_desc,creator,created_time) values ($1,$2,$3,$4,$5) RETURNING id")
            .execute(Tuple.of(
                snowflake.nextId(),
                1."Admin added dynamic"."admin",
                LocalDateTime.now()))
            .onItem()
            .transform(pgRowSet -> pgRowSet.iterator().next().getLong("id")); }}Copy the code

To create the Resource

package org.mxx.pg.resource;

import io.quarkus.vertx.web.Route;
import io.smallrye.mutiny.Uni;
import io.vertx.core.http.HttpMethod;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.mxx.pg.repository.DynamicInfoRepository;

<br> * <p>Created Time: 2021/7/8 PM 2:19 </p> **@author<a href="mail to: [email protected]" rel="nofollow"> </a> */
@Singleton
@Tag(name = "dynamic")
public class DynamicResource {
    @Inject
    DynamicInfoRepository dynamicInfoRepository;

    @Route(path = "/addDynamic", methods = HttpMethod.GET)
    Uni<Long> addDynamic(a) {
        returndynamicInfoRepository.addDynamicInfo(); }}Copy the code

Deployment way

First of all, you pack it

./mvnw package
Copy the code

Then drop the Quarkus-app folder in target into the server to start

nohup java -jar quarkus-app/quarkus-run.jar &
Copy the code

Unit testing

The curl http://127.0.0.1:8080/addDynamicCopy the code

Have normal accessDatabase persistence into

Performance testing (Insert)

[root@ecs-1b4c-0002 k6]# WRK c50 - d20s' http://127.0.0.1:8080/addDynamic '- latency
Running 20s test50 connections @ http://127.0.0.1:8080/addDynamic 2 threads and Thread Stats Avg Stdev Max + / - Stdev Latency 3.56 ms 12.06ms 214.33ms 98.54% Req/Sec 10.83k 1.47k 13.73k 75.88% Latency Distribution 50% 2.02ms 75% 2.65ms 90% 4.05ms 99% 29.37 ms 428896 requestsin20.01 s, 42.54 MBread
Requests/sec:  21438.03
Transfer/sec:      2.13MB
Copy the code

The database wrote 428936 pieces of data in 20 seconds.

Performance Test (Select)

At this point, 430,000 pieces of data already exist in the database

[root@ecs-1b4c-0002 k6]# wrk -c50 -d20s 'http://127.0.0.1:8080/findDynamicById?id=1413054691109113856'  --latency
Running 20s test@ http://127.0.0.1:8080/findDynamicById? Id =1413054691109113856 2 threads and 50 connections Thread Stats Avg Stdev Max +/ -stdev Latency 1.16ms 1.07ms 48.74ms 97.63% Req/Sec 23.06k 1.26k 40.17k 95.51% Latency Distribution 50% 1.05ms 75% 1.28ms 90% 1.56ms 99% 3.88ms 920108 requestsin20.10 s, 194.80 MBread
Requests/sec:  45776.45
Transfer/sec:      9.69MB
Copy the code

In 20 seconds, 920,000 searches were performed, with a QPS of 45,000.

Process information in the pressure test

Top-16:51:39 up 247 days, 20:00, 2 users, load average: 0.77, 0.28, 0.26 Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie %Cpu(s): 35.7 US, 26.3 sy, 0.0Ni, 20.3 ID, 0.0WA, 0.0Hi, 17.8 Si, 0.0st KiB Mem: 8008324 total, 1016916 free, 4775628 used, 2215780 buff/cache KiB Swap: 0 total, 0 free, 0 used. 2645436 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 5222 root 20 0 5246408 439708 13716 S 265.0 5.5 understood. 46 JavaCopy the code

Process information after pressure testing

[root@ecs-1b4c-0002 k6]# jmap -J-d64 -heap 5222
Attaching to process ID 5222, please wait. Server Compiler detected. JVM version is 25.171-B11 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 2051014656 (1956.0MB) NewSize = 42991616 (41.0MB) MaxNewSize = 683671552 (652.0MB) OldSize = 87031808 (83.0MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young Generation Eden Space: Capacity = 136314880 (130.0MB) Used = 4515344 (4.3061676025390625MB) Free = 131799536 (125.69383239746094MB) capacity = 136314880 (130.0MB) Used = 4515344 (4.3061676025390625MB) Free = 131799536 (125.69383239746094MB) 3.3124366173377404%, informs the From Space: Capacity = 524288 (0.5MB) Used = 131072 (0.125MB) Free = 393216 (0.375MB) 25.0% used To Space: Capacity = 524288 (0.5MB) Used = 0 (0.0MB) Free = 524288 (0.5MB) 0.0% Used PS Old Generation Capacity = 100139008 (95.5MB) Used = 21208464 (20.225967407226562MB) Free = 78930544 (75.27403259277344MB) 21.179023463064464% used 11297 interned Strings occupying 1320912 bytes.Copy the code

gossip

Quarkus has advantages in Rest services, but obviously the performance of the database determines the performance upper limit of API services, so its performance advantage can be better reflected when calling Redis or memory.

The connection to the database uses the Reactive Client of vert. x, which makes more use of resources than the synchronous blocking JDBC.