- inefficient design around data dependencies and their identification
- redundant work performed around said dependencies
- excessive reliance on APIs for uses they’re not intended, which frequently causes…
- …excessive VM deoptimizations and excessive GC
Granted this is one application and I certainly don’t think it’s representative of anything. But it’s definitely a counterpoint to inefficient concurrency (where this app generally performs quite well).
As for timeouts, IO and deadlocks, those problems can also be a case of poor up front optimization (before codigng).
The things you list are the low-hanging fruit, after which most engineering teams throw their arms up and say "I guess we've gone as far as we can on this!"
Consider a piece of code that grabs a set of records and then loops over them to get an association for each one. I've seen this kind of code in code reviews from juniors. its a good starting point where I start showing them how to rewrite their sql call to get the associated record via join so it goes from O(n) network calls to O(1)
I think I've actually seen performance decreases by people trying to decrease BigO. BigO only starts to really dominate time when N reaches higher levels. At lower levels of N your performance on your constant operations matter more, and by implementing more complex algorithms actually decreased real time performance. Obviously a lot of nuance in this. But first you need to measure.