It's most likely just reference counting and the way abstractions work in Swift (dynamic dispatch?). In particular, it still loses to C# even if you use AOT for the latter, especially in multi-threaded scenarios.
HotSpot C2 and .NET Dynamic PGO-optimized compilations first and foremost help to devirtualize heavy abstractions and inline methods that are unprofitable to inline unconditionally under JIT constraints, with C2 probably doing more heavy lifting because JVM defaults to virtual calls and .NET defaults to non-virtual.
With that said, I am not aware of any comprehensive benchmarking suites that would explore in-depth differences between these languages/platforms for writing a sample yet complex application and my feedback stems mostly from microbenchmark-ish workloads e.g. [0][1].
Performance aside, I do want to compliment Swift for being a pleasant language to program in if you have C# and Rust experience.
On the case of Java, it isn't only HotSpot, there are several other options, and in the case of OpenJ9 and Azul, cloud JIT also plays a role for cloud workloads.
I also like Swift, if anything it helped to bring back the pressure that AOT compilation also matters.
HotSpot C2 and .NET Dynamic PGO-optimized compilations first and foremost help to devirtualize heavy abstractions and inline methods that are unprofitable to inline unconditionally under JIT constraints, with C2 probably doing more heavy lifting because JVM defaults to virtual calls and .NET defaults to non-virtual.
With that said, I am not aware of any comprehensive benchmarking suites that would explore in-depth differences between these languages/platforms for writing a sample yet complex application and my feedback stems mostly from microbenchmark-ish workloads e.g. [0][1].
Performance aside, I do want to compliment Swift for being a pleasant language to program in if you have C# and Rust experience.
[0] https://github.com/ixy-languages/ixy-languages (2019)
[1] https://github.com/jinyus/related_post_gen (2023)