Triple协议性能调优——降低eventloop线程压力篇
- Dominant language
- Java
- Stars
- 41.6k
- Forks
- 26.4k
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 4
Description
# Triple协议性能调优——降低eventloop线程压力篇
## 前言
通过jvisualvm查看发现,eventloop的cpu时间里提交任务到业务线程池的耗时占比较大,那么优化的目标则是:降低eventloop非io任务的压力,让eventloop有更多的时间处理io任务。
## 方案思路
单独使用另外一个线程提交任务到业务线程池,将eventloop的耗时转嫁到该线程上。
## 结论
如图所示,该方案可以大幅度降低eventloop的压力,时间占比约为之前的`十分之一`。


````
优化前:
Benchmark Mode Cnt Score Error Units
ClientPb.createUser thrpt 3 27574.401 ± 8976.203 ops/s
优化后(只改了Server的情况):
Benchmark Mode Cnt Score Error Units
ClientPb.createUser thrpt 3 37377.205 ± 13052.171 ops/s
````
## 实施分析
通过查看`SerializingExecutor`的源码中的`run`方法得知,复用该类可以非常容易实现`降低eventloop提交任务耗时`的这个需求。源码如下:
````java
public void run() {
Runnable r;
try {
while ((r = runQueue.poll()) != null) {
try {
InternalThreadLocal.removeAll();
r.run();
} catch (RuntimeException e) {
LOGGER.error("Exception while executing runnable " + r, e);
} finally {
InternalThreadLocal.removeAll();
}
}
} finally {
atomicBoolean.set(false);
}
if (!runQueue.isEmpty()) {
// we didn't enqueue anything but someone else did.
schedule(null);
}
}
````
提交任务到`SerializingExecutor`线程池后实际上是把任务暂存到一个非阻塞的`ConcurrentLinkedQueue`队列上,然后在`run`时不断的从队列中取出任务并串行处理。而提交到该队列的耗时相比于阻塞队列是非常短的,当处于高并发状态时,会减少重调度的机会,更充分的利用单线程提交任务,从而将`eventloop`的提交耗时给剥离出来。
Contributor guide
Research direction
Start by tracing the Triple server path that submits work to the business thread pool, then read the SerializingExecutor run method shown in the issue. Reproduce the ClientPb.createUser benchmark before and after the change. Done means eventloop task-submission time is reduced while the reported throughput improvement remains reproducible.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- distributed-systems
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100