java-generator-experiment:基于Java虚拟线程求和测试


这是小小的试验性库包,建立在 "Java coroutines"(又称虚拟线程)之上的生成器:
一个将0到1000000的数字相加的生成器,java实现的运行时间大约是python实现的100倍

package io.avery.util.concurrent;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        // Try changing this to Executors.newSingleThreadExecutor()
        try (var exec = Executors.newVirtualThreadPerTaskExecutor();
             var gen = new Generator<>(exec, (Channel<Void, Integer> chan) -> {
                 for (int i = 0; i < 1000000; i++) chan.yield(i);
             })
        ) {
            Instant start = Instant.now();
        
            long sum = 0;
            for (Integer n; (n = gen.next(null)) != null;) {
                sum += n;
            }
        
            Instant end = Instant.now();
            System.out.printf("Sum: %d, Elapsed: %s%n", sum, Duration.between(start, end));
        }
    }
}

不幸的是,粗略的性能测试表明,上下文切换的开销是不可接受的。
我尝试了几个替代java实现的方法,以确认缓慢的来源。将PingPong的实现替换为自旋环路的实现(_unusedSpinPingPong),结果是性能与python的实现相当,但当然是浪费了CPU。用另一个黑客实现(_unusedNosyncPingPong)替换PingPong实现,试图剥离大部分同步开销,但保留了上下文切换开销,并没有明显改善性能。

其他:Vert.x 虚拟线程孵化器