@Wielki Lew po kolei bo mieszasz wiele różnych wątków.
Java / .NET ma JIT wiec może optymalizować kod w trakcie wykonania. Faktycznie może to zrobić jakieś optymalizacje względem aktualnego CPU, ale efekt będzie taki sam jak skompilowanie programu pod konkretną architekturę. Siłą JITa jest raczej fakt, że maszyna wirtualna może "zauważyć" optymalizacje których nie widać w trakcie kompilacji. Krótki przykład:
Wyobraź sobie że masz w kodzie gdzieś dzielenie. Wykonujesz je miliony razy w jakiejś wielkiej pętli. Nie da sie tego specjalnie optymalizować bo dzielnik nie jest znany na etapie kompilacji. Ale po uruchomieniu okazuje się, że dzielnik zwykle ustawia sie na 2. W przypadku języka natywnego niewiele można zrobic, bo kod maszynowy ma gołe dzielenie i tyle. Ale JIT może zauważyć że dzielnikiem jest 2 i zamiast dzielenia można sobie tą instrukcję zamienić na przesunięcie bitowe sprawiając że kod zaczyna śmigać wielokrotnie szybciej.
Jeśli chodzi o optymalizacje na poziomie kodu to dotyczą zwykle takich rzeczy jak rozmiary rejestrów procesora i cpu cache. Chodzi o to, żeby tak ustawiać dostęp do danych w pamięci żeby cały czas korzystać z cache, unikać cache-miss, unikać wielu zmian w jednej linii cache, unikać przełączania wątków między procesorami, żeby nie tracić cache, unikać false-sharing itd. To wymaga wiedzy o tym jakie cache ma rozmiary i czasem np. wpływa na to, że dodajesz wyrównanie do struktur danych żeby idealnie mieściły się w liniach cache. Tego właściwie nie da sie zrobić "automatycznie".