使用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
文章评论