Wiosenne problemy z wydajnością startową

Próbuję zintegrować Spring w dość dużej aplikacji z tysiącami klas i doświadczam ogromnych opóźnień w uruchamianiu kontenera z powodu skanowania komponentów.

Zawęziłem już liczbę katalogów podanych w "pakiecie bazowym" do minimum, aby zredukować czas marnowany na skanowanie nieistotnych katalogów, ale część inicjalizacji skanowania ścieżek klas trwa nadal około 1-2 minut.

Czy istnieje sposób na optymalizację skanowania proces ? Myślałem o zapisaniu ścieżki klas kandydujących w pliku i stworzeniu kontenera, a następnie pobraniu ich z pliku zamiast skanowania ścieżki klas przy każdym uruchomieniu, ale tak naprawdę Nie wiem, od czego zacząć lub czy jest to w ogóle możliwe.

Każda rada jest bardzo mile widziana. Z góry dzięki.

Edit: wczytywanie definicji bean tworzy automatycznie wygenerowany plik xml, skróciło czas rozruchu Springa do 9~10 sekund, co potwierdza, że API reflection używane przez Springa w przypadku komponentów skanowanie ścieżek klas jest głównym źródłem opóźnień uruchamiania.
Co do generowania pliku xml tutaj jest kod, ponieważ może być pomocny dla kogoś z tymi samymi problemami.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;


public class ConfigurationWriter {

    public ArrayList<String> beanDefinitions = new ArrayList<String>();

    public ConfigurationWriter() {

        // the context loaded with old fashioned way (classpath scanning)
        ApplicationContext context = SpringContainerServiceImpl.getInstance().getContext();
        String[] tab = context.getBeanDefinitionNames();
        for (int i = 0; i < tab.length - 6; i++) {
            Class clazz = context.getType(tab[i]);
            String scope = context.isPrototype(tab[i]) ? "prototype" : "singleton";
            String s = "<bean id=\"" + tab[i] + "\" class=\"" + clazz.getName() + "\" scope=\"" + scope + "\"/>";
            beanDefinitions.add(s);
        }
        // Collections.addAll(beanDefinitions, tab);

    }

    @SuppressWarnings("restriction")
    public void generateConfiguration() throws FileNotFoundException {
        File xmlConfig = new File("D:\\dev\\svn\\...\\...\\src\\test\\resources\\springBoost.xml");
        PrintWriter printer = new PrintWriter(xmlConfig);

        generateHeader(printer);

        generateCorpse(printer);

        generateTail(printer);

        printer.checkError();

    }

    @SuppressWarnings("restriction")
    private void generateCorpse(PrintWriter printer) {

        for (String beanPath : beanDefinitions) {
            printer.println(beanPath);
        }

    }

    @SuppressWarnings("restriction")
    private void generateHeader(PrintWriter printer) {
        printer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        printer.println("<beans xmlns=\"http://www.springframework.org/schema/beans\"");
        printer.println("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
        printer.println("xmlns:context=\"http://www.springframework.org/schema/context\"");
        printer.println("xsi:schemaLocation=\"");
        printer.println("http://www.springframework.org/schema/mvc");
        printer.println("http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd");
        printer.println("http://www.springframework.org/schema/beans");
        printer.println("http://www.springframework.org/schema/beans/spring-beans-3.0.xsd");
        printer.println("http://www.springframework.org/schema/context");
        printer.println("http://www.springframework.org/schema/context/spring-context-3.0.xsd\"");
        printer.println("default-lazy-init=\"true\">");
    }

    @SuppressWarnings("restriction")
    private void generateTail(PrintWriter printer) {
        // printer.println("<bean class=\"com.xxx.frmwrk.spring.processors.xxxBeanFactoryPostProcessor\"/>");
        printer.println("<bean class=\"com.xxx.frmwrk.spring.processors.xxxPostProcessor\"/>");
        printer.println("</beans>");
    }

}
Author: Mehdi, 2011-05-10

6 answers

Pytanie: ile (w %) klas w katalogach to fasolki wiosenne?

ODPOWIEDŹ: nie jestem pewien (to naprawdę duży projekt), ale z tego, co widziałem, uważam, że jest to około 90 do 100%, Ponieważ pliki XML i właściwości są izolowane w oddzielnych lokalizacjach)

Jeśli problemem jest naprawdę skanowanie komponentów, a nie sam proces inicjalizacji bean( i bardzo w to wątpię), to jedynym rozwiązaniem, jakie mogę sobie wyobrazić, jest użycie konfiguracji Spring XML zamiast skanowania komponentów. - (Można utworzyć plik XML automatycznie).

Ale jeśli masz wiele klas i 90% - 100% z nich to fasolki, to redukcja zeskanowanych plików będzie miała maksymalną poprawę o 10% -0%.

Powinieneś spróbować innych sposobów, aby przyspieszyć inicjalizację, może za pomocą leniwego ładowania lub jakichkolwiek leniwych technik związanych z ładowaniem, lub (i to nie jest żart) używać szybszego sprzętu (jeśli nie jest to samodzielna aplikacja).


Prosty sposób na wygenerowanie Spring XML służy do napisania prostej aplikacji spring, która korzysta ze skanowania ścieżek klas, tak jak oryginalna aplikacja. Po zainicjowaniu wszystkich fasolek, iteracja odbywa się poprzez fasolki w kontekście wiosennym, sprawdź, czy fasolka należy do ważnego pakietu i zapisz konfigurację XML dla tej fasolki w pliku.

 9
Author: Ralph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-10 10:23:17

Automatyczne wykrywanie klas adnotowanych wymaga obecnie skanowania wszystkich klas w podanych pakietach i może zająć dużo czasu, co jest znanym problemem obecnego mechanizmu ładowania klas.

Java 9 pomoże w układaniu puzzli.

From the Java Platform Module System requirements by Mark Reinold, http://openjdk.java.net/projects/jigsaw/spec/reqs/ :

Skuteczne wykrywanie adnotacji - Musi być możliwe zidentyfikowanie wszystkich plików klas w module Artefakt, w którym dana adnotacja jest obecna bez odczytu wszystkich plików klas. W czasie wykonywania musi być możliwe zidentyfikowanie wszystkich klas w załadowanym module, w którym dana adnotacja jest obecna, bez wyliczania wszystkich klas w module, o ile adnotacja była zachowana przez czas wykonywania. Dla skuteczności może być konieczne określenie, że tylko niektóre adnotacje muszą być wykrywalne w ten sposób. Jednym z potencjalnych sposobów jest rozszerzenie modułu definicja z indeksem adnotacji, które są obecne w module, wraz ze wskazaniem elementów, do których odnosi się każda adnotacja. Aby ograniczyć rozmiar indeksu, dodawane będą tylko adnotacje, które same w sobie są opatrzone nową meta-adnotacją, powiedzmy @Indexed.

 4
Author: Jeroen Borgers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-25 10:39:13

Niewiele można zrobić o wydajności tam, myślę, że nie jesteś zaniepokojony uruchomieniem w środowisku produkcyjnym, ale czas uruchamiania testów*. Dwie wskazówki:

  • Sprawdź, czy twój test-appcontext używa tylko minimalnie wymaganych komponentów Twojej aplikacji
  • zamiast listy dyrektyw component-scan, użyj jednej z nich, z rozdzieloną przecinkami wartością, taką jak ta: base-package= " com.paczka.jeden, com.paczka.dwa..."
 4
Author: abalogh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-26 21:51:06

Jedyną rzeczą, która przychodzi mi do głowy, oprócz zmniejszenia katalogów do skanowania, jest użycie Lazy bean initialization . Może to może pomóc, jeśli masz dużo fasoli

 2
Author: Hons,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-10 09:09:16

wiem, że to stare pytanie, i jak widać sytuacja była inna w tym czasie, ale mam nadzieję, że może pomóc innym badającym ten problem, jak ja.

Zgodnie z tą odpowiedzią na inne pytanie, adnotacja @ComponentScan obsługuje teraz flagę lazyInit, która powinna pomóc w skróceniu czasu uruchamiania.

Https://stackoverflow.com/a/29832836/4266381

Uwaga: twoja edycja sprawiła, że brzmiało to tak, jakby samo przejście na XML było magią. A jednak, patrząc bliżej kodu, miałeś default-lazy-init="true". Zastanawiam się, czy to był prawdziwy powód.

 2
Author: Xiangming Hu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-17 21:31:25

Zamiast skanowania komponentów można użyć konfiguracji kontenera Springa opartej na Javie.

W porównaniu z konfiguracją opartą na XML, konfiguracja kontenerów opartych na Javie jest bezpieczna dla typu.

Ale przede wszystkim należy sprawdzić, czy ścieżki skanowania komponentów są wystarczająco specyficzne, aby nie zawierały klas bibliotek stron trzecich.

 1
Author: rwitzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-19 10:33:50