A Good Day to Play Ping-Pong
Implementing the ping-pong program in Erlang, C++ and Java.
§Erlang
1 | -module(pingpong). |
Running using a single CPU or two logical CPUs belonging to the same core. (Had to specify +S
; otherwise it creates
too many scheduler threads.)
1 | erlc pingpong.erl && taskset -c 0 erl +S 1 -eval "pingpong:main(1), halt()." -noshell |
§C++
1 |
|
1 | clang++ -O -std=c++20 pingpong.cpp && taskset -c 0 ./a.out |
§Java
1 | import java.util.concurrent.Semaphore; |
Using OS threads:
1 | taskset -c 0 java --enable-preview --source 19 pingpong.java |
Using virtual (green) threads:
1 | taskset -c 0 java --enable-preview --source 19 pingpong.java |
§Conclusion
Grouping all results in a table:
Lang/Runtime | Elapsed time on single CPU | Elapsed time on 2 CPUs (same core) |
---|---|---|
Erlang | 21.66 | 21.071 |
C++ | 69.05 | 6.558 |
Java | 64.085 | 114.891 |
Java (vthread) | 18.058 | 66.210 |
- C++ and Java have on-par peak performance on a single core: 69ms vs 64ms
- JVM has poor support for SMP: using more CPU has detrimental effect, 64ms -> 114ms and 18 -> 66ms
- Java Virtual Threads and Erlang show that user-mode context switching is much cheaper: 18ms/21ms vs 64ms/69ms
- C++ thread context switching has better scalability: 69ms -> 6ms; using
getrusage
one can see the #context switches drops significantly.
§ENV
1 | Erlang : 25 |