2012-09-01 17 views
8

Jestem w trakcie przenoszenia na pewien algorytm przetwarzania danych z Java do C++. Powodem ponownego napisania kodu jest przenośność, musi działać w środowiskach, w których Java nie jest dostępna. Jednak jako korzyść uboczna oczekiwano poprawy wydajności.Jak droga jest .getClass() w Javie?

Zasadniczo algorytm odczytuje dane z wykresu złożonego z obiektów ze wskaźnikami, a następnie oblicza wynik. Podczas obliczeń dokonywane są liczne alokacje obiektów, więc być może jest to odpowiedzialne za spowolnienie. Chodzi o to, że kod C++ działa obecnie około 10 razy szybciej niż stary kod Java. To było naprawdę nieoczekiwane. Pomyślałem tylko, że widzę poprawę na poziomie 50-60%.

Niestety, nie mam prawa publikować tutaj kodu do analizy. To kilka tysięcy linii, więc nie jestem pewien, jak by to było wygodnie.

Chodzi o to, że algorytm jest prawie taki sam. Jedyną istotną różnicą, o której mogę myśleć jest to, że w Javie istnieje wiele klas potomnych pojedynczej super klasy i jeśli (object.getClass() == daughterx.class) jest wywoływana wiele razy podczas obliczeń, podczas gdy w kodzie C++ tylko jeden ogólny używana jest klasa (ponieważ istnieje niewiele różnic w kodzie między klasami potomnymi) i używane jest proste porównanie liczb całkowitych, np. if (object-> type == 15)

Jak droga jest metoda Object.getClass() w Javie? Co dokładnie dzieje się na niskim poziomie, gdy ta metoda jest przywoływana?

+5

@ xlc0212 Ani są którykolwiek z pozostałych osób, które nie rozumieją języka Java ! ;) – cheeken

+0

@cheeken to zależy od JVM, bez JIT, pamiętam, czytałem skądś, że Java jest nawet wolniejsza niż python –

+3

Szczerze mówiąc brzmi to jak nie problem. Czy warto poświęcić swój czas na testowanie i profilowanie wycofanego kodu? Dopóki tego nie zrobisz, nie ma sposobu by wiedzieć, że '.getClass()' jest wąskim gardłem. Odgadywanie nie jest dobrym sposobem na rozwiązanie problemów z wydajnością, chyba że można znacznie zmniejszyć ogólną złożoność algorytmu (tj. Przejście z operacji N-kwadratowej do operacji log-N), a zestaw danych jest bardzo duży. –

Odpowiedz

7

Najbardziej prawdopodobnym przypadkiem dla 10-krotnej różnicy jest to, że JVM nie została całkowicie rozgrzana. Jeśli tego nie zrobisz, możesz zauważyć ponad 10-krotną różnicę wydajności nawet w Javie. Spróbowałbym biegać w partiach po 10 000 i zignorować kilka pierwszych przebiegów.

public static void main(String... args) throws IOException { 
    timeObjectGraph("First run", 1); 
    timeObjectGraph("Second run", 2); 
    timeObjectGraph("Next thousand", 1000); 
    for (int i = 0; i < 5; i++) 
     timeObjectGraph("Next ten thousand", 10000); 
} 

static int dontOptimiseAway = 0; 

public static void timeObjectGraph(String desc, int runs) throws IOException { 
    long start = System.nanoTime(); 
    for (int i = 0; i < runs; i++) { 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     ObjectOutputStream oos = new ObjectOutputStream(out); 
     oos.writeObject(Calendar.getInstance()); 
     oos.close(); 
     dontOptimiseAway = out.toByteArray().length; 
    } 
    long time = System.nanoTime() - start; 
    System.out.printf("%s took an avg time of %,d ns%n", desc, time/runs); 
} 

drukuje

First run took an avg time of 37,509,488 ns 
Second run took an avg time of 439,054 ns 
Next thousand took an avg time of 185,242 ns 
Next ten thousand took an avg time of 41,698 ns 
Next ten thousand took an avg time of 19,981 ns 
Next ten thousand took an avg time of 11,541 ns 
Next ten thousand took an avg time of 13,451 ns 
Next ten thousand took an avg time of 11,289 ns 

Od pierwszego do ostatniego biegu, wydajność poprawiła się o współczynnik 3000x

+0

Dlaczego używasz Calendar.getInstance()? Najpierw pytanie dotyczy metody getClass. Drugi kalendarz jest ** ciężki ** klasa do stworzenia, więc Calendar.getInstance() ** drogie sam **, nie dlatego, że getClass jest wywoływany w środku. Myślę, że ten przykład nie jest poprawny lub powinieneś podać bardziej przejrzysty komentarz. – Cherry

+2

@Cherry Użyłem Kalendarza i ObjectOutputStream, ponieważ są one drogie dla krótkiego fragmentu kodu, co daje realistyczny przykład tego, jak wiele zmian może spowodować znaczna ilość kodu. –

5

To nie jest jedyny czynnik różnicy w wydajności. Niestety, bez pełniejszego obrazu tego, co robi twój kod, naprawdę trudno będzie ci powiedzieć, co się dzieje.

Z mojego doświadczenia wynika, że ​​Java nie powinna być 10 razy wolniejsza od C++. Najprawdopodobniej zacznę od profilera i zobaczę, gdzie wskazuje na zrozumienie problemu, zamiast zgadywać.

11

Jak droga jest metoda Object.getClass() w Javie?

Na podstawie mojej wiedzy o tym, jak to jest realizowane w JVMs spoza głównego nurtu, to jest tanie

Co dokładnie dzieje się na niskim poziomie, gdy ta metoda jest wywoływana?

Zazwyczaj ...

  1. Ekstrakt wskaźnik klasy z nagłówka obiektu (2 lub 3) instrukcji
  2. odnośnika deskryptora klasy z indeksu klasy (2 lub 3) instrukcji
  3. Pobierz i zwróć odwołanie do obiektu obiektu Class z deskryptora klasy (instrukcje 2 lub 3)

Chodzi o to, że kod C++ działa obecnie około 10 razy szybciej niż stary kod Java.

Spodziewam się, że wąskie gardło wydajności jest gdzie indziej. Powinieneś wypróbować profilowanie kodu Java, zanim przejdziesz do jakichkolwiek wniosków, dlaczego był wolniejszy.

+6

+1 Podczas gdy samo wyszukiwanie jest tanie, oznacza to znaczący problem z projektowaniem i wydajnością, jeśli posiadasz sekwencje 'if (getClass() == SomeClass.class)' Sugeruje to, że potrzebujesz więcej OO Design lub jak to zrobił OP, połącz te klasy, aby można było użyć przełącznika lub czegoś podobnego do tej funkcji. –

Powiązane problemy