Krolik napisał(a)
No, żeby być uczciwym - to nie cały narzut tylko niewielka jego część. Chociażby odpada parsowanie wysokopoziomowego kodu i sprawdzanie poprawności programu. W runtime jest wykonywana jedynie kompilacja i optymalizacja niektórych części programu, wykonywanych najczęściej (HotSpot), zgodnie z zasadą, że 20% kodu wykonuje się przez 80% czasu. Te mechanizmy są stale dopracowywane i z kolejnymi wersjami można spodziewać się jeszcze znacznej poprawy.
Ale jednak narzut jest, nie zaprzeczysz. Co do wymagających największej optymalizacji miejsc w programie - moim skromnym zdaniem gdzieś w ich okolicy zawsze powinny się znaleźć trzy literki - 'a', 's' i 'm' ;)
Toż mówię, że w C++ też da się tego dokonać - alokujesz pamięć blokami i dopiero potem przydzielasz obiektom, mając nad tym przy okazji znacznie większą kontrolę niż w Javie.
Owszem da się. I po paru latach kodowania okazuje się, że masz nieformalnie zdefiniowaną, pełną błędów i powolną maszynę wirtualną Javy :p Strzel jeden drobny błąd we własnym alokatorze i życzę powodzenia w debugowaniu losowych segfaultów.</quote>
Jak kto woli - można do tego celu budować własną wirtualną maszynę, można zadowolić się prostszym rozwiązaniem. Najprostszy kod produkujący void*y do przekazania new'om można napisać wręcz z ręki, np:
template<unsigned int size, unsigned int num = 10>
class MemoryManager
{
public:
MemoryManager()
{
for(int i=0; i<num; i++) used[i] = false;
}
void* allocate();
void deallocate(void*);
private:
char block[size*num];
bool used[num];
};
template<unsigned int size, unsigned int num>
void* MemoryManager<size, num>::allocate()
{
char* ptr = block;
for(int i=0; i<num; i+=size)
{
if(!(used[i/size]))
{
used[i/size] = true;
return (void*)ptr;
}
ptr += size;
}
// Houston, mamy problem ;)
return 0;
}
template<unsigned int size, unsigned int num>
void MemoryManager<size, num>::deallocate(void* ptr)
{
used[(ptr-block)/size] = false;
}
Oczywiście kod wręcz błaga o jakiś system kontroli błędów i optymalizację wyszukiwania wolnego miejsca, ale na przykład wystarczy ;)
Ostatnio widziałem strzelankę 3D na telefonie komórkowym napisaną w... Javie. Nic się nie cięło. Na wydajność w grach mają w 99% wpływ dobre algorytmy i efektywne wykorzystywanie dobrodziejstw akceleracji sprzętowej dawanej przez kartę. W Javie jedno i drugie jest możliwe (łącznie z programowaniem shaderów). Jak zrobisz zły algorytm detekcji kolizji, to i zakodowanie go w sprzęcie / asmie niewiele da. A mniejszy czas produkcji kodu, to więcej czasu na optymalizację algorytmów.
Już pomijając fakt, że gry wymagania stawiane przed grami na komórki znacząco różnią się od wymagań stawianych przed grami pctowymi czy konsolowymi (ważna jest np. znacznie mniejsza rozdzielczość - co oprócz oczywistego wpływu na mniejszą ilość pixeli generowaną przez rasteryzator ma również pośredni wpływ na ogólną wymaganą przez użytkownika jakość grafiki - rozdzielczość tekstur, stopień skompilowania modeli - jak i świat gry - np. ilość obiektów pojawiających się na raz na ekranie) to zgadzam się, że kiepsko zaimplementowany dobry algorytm jest zawsze wydajniejszy od dobrze zaimplementowanego kiepskiego algorytmu. Jednak uważam, że o prawdziwie dobrym programie można mówić dopiero, gdy się połączy zalety obu podejść ;)
A wracając do tematu - ostatnimi czasy pojawiło się na tym forum sporo bardzo pochlebnych opinii o LISPie - więc pomyślałem, że to grzech choćby nie przetestować ;) Po pierwszym zetknięciu z językiem (przejrzeniu tutoriala + sprawdzeniu, czy moja ulubiona biblioteka (a właściwie dwie ;)) są w nim dostępne) uznałem, że rzeczywiście warto by go dołączyć do listy ulubionych języków. Prawdę mówiąc, jeśli prawdą jest, co mówi się o jego wydajności, to prawdopodobnie zepchnie C++ z pierwszego miejsca na mojej liście - tylko muszę go wpierw lepiej poznać ;)