rendimiento optimizar memoria mejorar maximo liberar como acelerar java spring spring-mvc classpath bootstrapping

java - optimizar - Problemas de rendimiento de inicio de primavera



optimizar windows 10 2018 (6)

Intento integrar Spring en una aplicación bastante grande con miles de clases, y estoy experimentando grandes retrasos al iniciar mi contenedor debido al escaneo de componentes.

Ya reduje el número de directorios especificados en el "paquete base" al mínimo para reducir el tiempo perdido en el escaneo de directorios irrelevantes, pero la parte de inicialización de escaneo de ruta de clase todavía demora unos 1-2 minutos.

Entonces, ¿hay alguna forma de optimizar el proceso de escaneo? He pensado en almacenar la ruta de las clases candidatas en un archivo y hacer que el contenedor las obtenga del archivo en lugar de escanear la ruta de clase con cada inicio, pero realmente no sé por dónde empezar o si eso es posible. .

Cualquier consejo es muy apreciado. Gracias por adelantado.

Editar : la carga de definiciones de bean forman un archivo xml generado automáticamente, redujo el tiempo de arranque Spring a 9 ~ 10 segundos, lo que confirma que la API de reflexión utilizada por Spring para el escaneo class-path de los componentes es la principal fuente de retrasos en el arranque.
En cuanto a generar el archivo xml aquí está el código, ya que podría ser útil para alguien con los mismos problemas.

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>"); } }


Pregunta: ¿Cuántas (en%) de las clases en los directorios son Spring Beans?

Respuesta: No estoy muy seguro (es un proyecto realmente grande), pero por lo que vi, creo que está entre el 90 y el 100%, ya que los archivos xml y de propiedades están aislados en ubicaciones separadas.

Si el problema es realmente el escaneo del componente y no el proceso de inicialización del mismo (y lo dudo mucho), entonces la única solución que puedo imaginar es usar la configuración Spring XML en lugar del escaneo de componentes. - (Puede crear el archivo XML automáticamente).

Pero si tiene muchas clases y el 90%, el 100% de ellas son frijoles, la reducción de los archivos escaneados tendrá una mejora máxima del 10% -0%.

Debería probar otras formas de acelerar su inicialización, puede usar carga lenta o cualquier técnica relacionada con la carga lenta, o (y eso no es una broma) usar hardware más rápido (si no es una aplicación independiente).

Una forma fácil de generar Spring XML es escribir una aplicación de resorte simple que utiliza el escaneo de rutas de clase como su aplicación original. Después de que todos los beans se inicialicen, iterará a través de los beans en el contexto de Spring, verificará si el bean pertenece al paquete importante y escribirá la configuración XML para este bean en un archivo.


El descubrimiento automático de clases anotadas actualmente requiere escanear todas las clases en los paquetes especificados y puede llevar mucho tiempo, un problema conocido del mecanismo de carga de clases actual.

Java 9 va a ayudar aquí con Jigsaw.

De los requisitos del Sistema de Módulo de Plataforma Java de Mark Reinold, http://openjdk.java.net/projects/jigsaw/spec/reqs/ :

Detección de anotación eficiente: debe ser posible identificar todos los archivos de clase en un artefacto de módulo en el que esté presente una anotación particular sin leer realmente todos los archivos de clase. En tiempo de ejecución, debe ser posible identificar todas las clases en un módulo cargado en el que está presente una anotación particular sin enumerar todas las clases en el módulo, siempre que la anotación se haya conservado para el tiempo de ejecución. Para mayor eficiencia, puede ser necesario especificar que solo ciertas anotaciones deben ser detectables de esta manera. Un posible enfoque es aumentar la definición de un módulo con un índice de las anotaciones que están presentes en el módulo, junto con una indicación de los elementos a los que se aplica cada anotación. Para limitar el tamaño del índice, solo se incluirán las anotaciones que se anoten con una nueva metaanotación, por ejemplo, @Indexed.


Lo único que se me viene a la mente, además de reducir los directorios a escanear, es el uso de la inicialización de bean perezoso . Que esto podría ayudar si tienes muchos frijoles


No hay mucho que pueda hacer sobre el rendimiento allí, supongo que no está preocupado por el inicio en el entorno de producción, sino por el tiempo de inicio de sus pruebas *. Dos consejos:

  • Revise que su contexto de aplicación de prueba solo utilice los componentes mínimamente necesarios de su aplicación
  • en lugar de tener una lista de directivas de escaneo de componentes, use una, con un valor separado por comas como este: base-package = "com.package.one, com.package.two ..."

Puede usar la configuración de contenedor basada en Java de Spring en lugar de la exploración de componentes.

En comparación con la configuración basada en XML, la configuración del contenedor basado en Java es segura para el tipo.

Pero antes que nada debe verificar si las rutas de exploración de sus componentes son lo suficientemente específicas para que no incluyan clases de bibliotecas de terceros.


Sé que es una vieja pregunta, y como verán, la situación era diferente en ese momento, pero espero que pueda ayudar a otros a investigar este problema como yo lo hice.

De acuerdo con esta respuesta a una pregunta diferente, la anotación @ComponentScan ahora admite un indicador lazyInit , que debería ayudar a reducir el tiempo de inicio.

https://.com/a/29832836/4266381

Nota: Tu edición hizo que pareciera que cambiar a XML por sí solo era la magia. Sin embargo, mirando más de cerca el código, tenías default-lazy-init="true" . Me pregunto si esa fue la verdadera razón.