springboot中启用虚拟线程&单机压测记录

2024-03-05 336点热度 1人点赞 0条评论

使用Spring Boot的Virtual Threads(虚拟线程)功能,可显著提高应用程序的性能。
今天实践一波,看看性能到底如何?走起~

环境

  • jdk21
  • springboot 3.2.2

测试代码

ThreadConfig

@Configuration
@ConditionalOnProperty(prefix = "spring", name = "virtual-thread", havingValue = "true")
public class ThreadConfig {

    @Bean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)
    public AsyncTaskExecutor applicationTaskExecutor() {
        return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor());
    }

    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerCustomizer() {
        return protocolHandler -> {
            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
        };
    }
}

SyncServiceTest

@Component
public class SyncServiceTest {

    @Async
    public void execute(CountDownLatch countDownLatch){
        try {
            TimeUnit.MILLISECONDS.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        countDownLatch.countDown();
    }
}

Jdk21VirtualThreadTest

@RestController
public class Jdk21VirtualThreadTest {

    @GetMapping("/what")
    public String what() {
        System.out.println(Thread.currentThread());
        return "what";
    }

    @GetMapping("/sleep")
    public String sleep() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(50);
        return "ok";
    }

    @Resource
    private SyncServiceTest syncServiceTest;

    /**
     * 测试异步性能 虚拟线程 vs 平台线程.
     * 注意: 异步方法 execute 不能和调用者在同一个类中
     * 注意: 启动类需要有 @EnableAsync
     *
     * @return
     * @throws InterruptedException
     */
    @GetMapping("/async")
    public long async() throws InterruptedException {
        long start = System.currentTimeMillis();
        int size = 100;
        final CountDownLatch latch = new CountDownLatch(size);
        for (int i = 0; i < size; i++) {
            syncServiceTest.execute(latch);
        }
        latch.await();
        return System.currentTimeMillis() - start;
    }

    @Resource
    private DemoRpc demoRpc;

    @RequestMapping("/grpc")
    public Object grpc() {
        DemoReq req = new DemoReq();
        req.setUid(123L);
        return demoRpc.hello(req);
    }

}

机器配置

硬件概览:
  芯片:   Apple M2
  核总数:  8(4性能和4能效)
  内存:   16 GB

使用 wrk 压测

预热5次之后,测得的平均结果

sleep 50ms

wrk -t8 -c100 -d 10s --latency http://127.0.0.1:8080/sleep
  • VirtualThread(QPS) : 1750
  • PlatformThread(QPS) : 1760
wrk -t8 -c200 -d 10s --latency http://127.0.0.1:8080/sleep
  • VirtualThread(QPS) : 16000
  • PlatformThread(QPS) : 3720
wrk -t8 -c400 -d 10s --latency http://127.0.0.1:8080/sleep
  • VirtualThread(QPS) : 4470
  • PlatformThread(QPS) : 3720
wrk -t8 -c800 -d 10s --latency http://127.0.0.1:8080/sleep
  • VirtualThread(QPS) : 4469
  • PlatformThread(QPS) : 3720
wrk本次压测结论
  • 在低负载的场景下 性能差距不大,甚至不开启虚拟线程性能更佳。
  • 在高负载的场景下 开启虚拟线程性能更佳。

grpc

wrk -t8 -c100 -d10s --latency http://127.0.0.1:8080/grpc
  • VirtualThread(QPS) - 6000
  • PlatformThread(QPS) - 1463
wrk -t8 -c200 -d10s --latency http://127.0.0.1:8080/grpc
  • VirtualThread(QPS) - 13000
  • PlatformThread(QPS) - 1465
wrk -t8 -c400 -d10s --latency http://127.0.0.1:8080/grpc
  • VirtualThread(QPS) - 16500
  • PlatformThread(QPS) - 1465
wrk -t8 -c800 -d10s --latency http://127.0.0.1:8080/grpc
  • VirtualThread(QPS) - 16457
  • PlatformThread(QPS) - 1460
wrk本次压测结论
  • 在低负载/高负载的场景下 虚拟线程拥有绝对优势

引用

压测代码地址: https://gitee.com/Mylomen/simple-java-grpc.git
压测工具地址: https://github.com/wg/wrk.git

mylomen

本人从事 JAVA 开发10多年,将之前整理的笔记分享出来,希望能够帮助到努力的你。

文章评论