2013-03-17 12 views
6

Korzystając z JProfiler, zidentyfikowałem hot spot w moim kodzie Java, którego nie mogę zrozumieć. JProfiler wyjaśnia, że ​​ta metoda zajmuje średnio 150 μ s (674 s bez rozgrzewki), nie wliczając czasu potrzebnego na wywołanie metod potomnych. 150 μ s może nie wydawać się wiele, ale w tej aplikacji sumuje się (i jest doświadczany przez moich użytkowników), a także wydaje się dużo w porównaniu do innych metod, które wydają mi się bardziej skomplikowane niż ten. Dlatego to dla mnie ważne.Metoda Java zajmuje pozornie dużo czasu, którego nie mogę obliczyć na

private boolean assertReadAuthorizationForFields(Object entity, Object[] state, 
     String[] propertyNames) { 
    boolean changed = false; 
    final List<Field> fields = FieldUtil.getAppropriatePropertyFields(entity, propertyNames); 
    // average of 14 fields to iterate over 
    for (final Field field : fields) { 
     // manager.getAuthorization returns an enum type 
     // manager is a field referencing another component 
     if (manager.getAuthorization(READ, field).isDenied()) { 
      FieldUtil.resetField(field.getName(), state, propertyNames); 
      changed = true; 
     } 
    } 
    return changed; 
} 

Ja sam zminimalizowałem tę metodę w różnych kierunkach, ale nigdy nie uczyłem się zbyt użytecznego. Nie mogę wystarczająco podkreślić, że raportowany przez JProfiler czas trwania (150 μ s) dotyczy jedynie kodu w tej metodzie i nie zawiera czasu potrzebnego na wykonanie getAuthorization, isDenied, resetField i innych. Właśnie dlatego zaczynam od opublikowania tego fragmentu, bez większego kontekstu, ponieważ wydaje się, że problem dotyczy tego kodu, a nie jego kolejnych wywołań metod potomnych.

Może możesz argumentować, dlaczego – jeśli czujesz, że widzę duchy :) W każdym razie dziękuję za poświęcony czas!

+1

Profilowanie wymaga okresu rozgrzewania (w przypadku JIT). Rozgrzewasz? Czy JIT jest wyłączony? – Java42

+0

To jest dobra uwaga. Chociaż wiedziałem o tym, być może upuściłem piłkę. Będę aktualizował mój post, a wraz z ilością czasu potrzebnego na rozgrzewkę podzielę się tym, czy nadal uważam, że jest zbyt duży ... może powinienem usunąć pytanie ... może nie :) –

+2

Czy używasz próbkowania CPU lub dynamicznego oprzyrządowania z JProfiler? –

Odpowiedz

0

Proponuję, abyś sam pomógł sobie, ponieważ profiler nie zawsze podaje dokładny czas.

Stwórz mikro-benchmark z tym kodem i czas to przez co najmniej 2 sekundy. Aby ustalić, ile wywołają metody różnicowania, skomentuj je i sztywno koduj zwracane wartości.

+1

Dwa powody niekiedy niedokładnych czasów raportowanych przez profilery próbkowania: 1) Jeśli JIT zdecyduje się wstawić metoda ta nigdy nie zostanie zgłoszona niezależnie. Czy wywoływane metody są również raportowane niezależnie (nawet po rozgrzewce)? Jeśli nie, mogą zostać wstawione, w którym to przypadku ich czas zostanie niedokładnie przypisany do assertReadAuthorizationForFields(). 2) Zanim próbkowanie ustabilizuje się, może upłynąć trochę czasu, aby raportować stabilny czas. Czy czasy, które widzisz z JProfiler są stabilne od 1 uruchomienia do następnego? – AaronD

1

zachowanie Kandydat, który może spowolnić:

  • Główne efekt: Oczywiście iteracji. Jeśli masz dużo pól ... Mówisz średnio 14, co jest dość znaczące
  • Znaczący efekt: Inlineing hotspot oznaczałby, że w twoich czasach są włączone metody zwane - i to może być zauważalne, ponieważ twoje wywołania metody wykorzystują odbicie. getAppappropriatePropertyFields introspects na metadanych definicji pola klasy; Funkcja resetField dynamicznie wywołuje metody ustawiające (możliwe użycie metody Method.invoke() ??). Jeśli chcesz uzyskać wydajność, możesz użyć pamięci podręcznej za pomocą HashSet (odwzorowanie ElementClass-> FieldMetadataAndMethodHandle) Może to zawierać metadane pól i metody Method Set metod ustawiających (zamiast używać metody method.invoke, która jest wolna). Wtedy zastanawiałbyś się tylko podczas uruchamiania aplikacji i korzystałbyś z szybkiej obsługi dynamicznej inwokacji JVM.
  • Drobny efekt - ale pomnożony przez liczbę iteracji: jeśli masz bardzo duże tablice dla nazw stanów i właściwości, a używają one pól pierwotnych, to wymagałoby to pewnego stopnia kopiowania podczas wywołań metod (parametry metody pass-by- ' wartość "w rzeczywistości oznacza przechodzenie przez referencję/przekazywanie według kopii pierwotnych)
0

Myślę, że problem polega na tym, że FieldUtil używa Reflection i nie buforuje pól, z których korzysta.

Powiązane problemy