¿Por qué la reflexión de Java es un orden de magnitud más lenta que las llamadas directas?
No hay duda al respecto. No estoy escribiendo este artículo para demostrar cuán eficiente es la reflexión.
La entrega urgente es muy popular ahora. Tomemos como ejemplo la entrega urgente. Si el mensajero está cerca de donde usted vive, entonces informe una dirección: No. xx, Edificio xx, entonces el mensajero puede saber inmediatamente dónde se encuentra y entregarlo directamente en su puerta; sin embargo, si el mensajero viene a usted por primera vez; tiempo aquí, ¿debería primero consultar el mapa de Baidu para ver cómo conducir hasta allí y luego, cuando llegue a la comunidad, debería preguntar primero al personal administrativo del edificio xx cómo encontrarlo y luego, si es posible caminar abajo? ?
Observando el escenario anterior, si el mensajero no está familiarizado con su comunidad y la velocidad no es lenta, dedicará su tiempo principalmente a buscar mapas de Baidu y preguntar a la administración de la propiedad. "Está bien, lo mismo ocurre con la reflexión, porque no sé nada de antemano, por lo que tengo que dedicar tiempo a buscar otra información antes de poder encontrarte. Si estás interesado, puedes comprobar cómo se implementa la reflexión y Cómo se relacionan los metadatos Concepto.
¿Cuánto más lenta es la reflexión que la llamada directa?
Bien, sabemos que la reflexión es definitivamente lenta, entonces, ¿eso significa que es inutilizable cuando algunas personas la escuchan? , uno llegaría a la conclusión de que la reflexión tal y tal no funciona, tal y tal no se puede utilizar, pero ¿cuánto más lenta es la reflexión que una llamada directa? Mucha gente sólo tiene una vaga idea del rendimiento. ?, pero no hay soporte numérico. Encontré una biblioteca de clases para el análisis de expresiones dinámicas para mi colega, y no le resultó muy fácil de usar. Era muy inteligente y pronto descubrió que se podía lograr el análisis dinámico de fórmulas. DataTale.Compute. Le pregunté cuál es la diferencia de rendimiento entre este método y la biblioteca que le proporcioné. Me dijo que es muy rápido y que el tiempo de ejecución es inferior a 1 segundo. , tu pensamiento todavía está en segundos. ¿De qué rendimiento estás hablando?
¿Cómo juzgar el rendimiento de una función? Debido a que la velocidad de ejecución de la función es demasiado rápida, necesitas un reductor de velocidad para capturarla. su ejecución. Sólo se puede comprender verdaderamente el rendimiento de una función después de que se haya utilizado un millón o diez millones de veces. En otras palabras, si se quiere juzgar el rendimiento, no se puede permanecer en el concepto de segundos y milisegundos, se debe reemplazar. Con otro concepto, para conocer el rendimiento real. Como resultado, mi colega ejecutó estos dos métodos 100w veces. De hecho, la biblioteca de clases que proporcioné fue 8 segundos más rápida que la suya.
Bien, ahora probemos el método de fábrica que proporcioné hace dos días. Para la implementación de CodeTimer, puede consultar el artículo de Zhao Ge "Un contador de rendimiento simple":
La prueba. El método es el siguiente:
El código es el siguiente
Copiar código
[Prueba]
public void TestReflector() p>
{
CodeTimer.Time("Directo", 100 * 10000,
() =>
{
var instancia = new ConnectionTest();
});
CodeTimer.Time("Reflect", 100 * 10000,
() =>
{
this.GetType().Assembly.CreateInstance("TestPropertyGrid.ConnectionTest");
});
}
}
Los resultados de la prueba son los siguientes:
Directo
Consumo de tiempo: 25 ms
Ciclos de CPU: 57.582.163
Generación 0: 14
Generación 1: 0
Reflexión
Tiempo empleado: 3.231 ms
Ciclos de CPU: 8.001.720.795
Generación 0: 269
Generación 1: 1
Mira, nuestra lupa está funcionando, y ahora probablemente podamos concluir que cuando se ejecute 1.000.000 de veces, el reflejo reducirá la velocidad de las llamadas directas entre 50 y 100 veces. A primera vista, 100x es una gran diferencia, pero como dije antes, no saque conclusiones precipitadas, primero debe observar los requisitos previos. Desde la antigüedad, nos ha gustado sacar citas de contexto, como el dicho "pagar el mal con bondad". Parece que los antiguos decían que cuando nos encontramos con algo malo, no hay que estar resentido, sino ser amable con él. otros, si alguien te da una bofetada en la mejilla izquierda, debes darte una palmada en la mejilla derecha. Ella acercó su rostro y le pidió que me golpeara más. Pero, ¿cómo es el idioma real?
O dijo: "¿Qué tal si pagamos el mal con bondad?"
Confucio dijo: "¿Qué tal si pagamos el mal con bondad? Pagamos el mal con rectitud, pagamos la bondad con bondad".
Viejo Lo que Kong realmente quiere decir es que si los demás son buenos contigo, tú debes ser bueno con ellos. Si él te provoca o te ofende, ¡debes matarlo! Mira, es una tontería, ¿verdad?
¿Con qué frecuencia hay que considerar los efectos del condicionamiento?
Creo que es muy raro y en la mayoría de los casos no necesitamos pensar en ello en absoluto. En cuanto a las fábricas que mencioné en mi post anterior, ¿cuántas entidades tiene su programa, un millón? Si estás haciendo NUEVO cuando aparece la ventana, ¿te importa esa diezmillonésima de segundo?
Además, algunas personas dicen que si realmente tengo esa necesidad, tengo que NUEVO objeto un millón de veces, ¿no es todavía muy lento? ¿Es este el caso? Digamos que tengo 100.000 registros y necesito sacarlos mediante reflexión y asignarlos a una clase de modelo.
Pero en este caso, si realmente lo crees, solo puedo decir que tu cerebro está oxidado después de estar sentado en la oficina durante mucho tiempo, y es hora de ir de excursión y ligar chicas. Si necesita reflexionar sobre un objeto innumerables veces, debe almacenarlo en caché. Tome nuestro ejemplo anterior, si el mensajero entrega paquetes a la comunidad innumerables veces pero no puede reconocer el camino, y cada vez que tiene que preguntarle a Baidu Maps y luego le pregunta a la administración de la propiedad, usted aún no lo ha expulsado, entonces tu cabeza ¿Es esto un alarde o es simplemente un caso de gente rica que es obstinada?
Si el código anterior se almacena en caché y se ejecuta millones de veces, ¿en qué se diferencia de llamarlo directamente? No publicaré el código aquí, en caso de que no esté interesado en ver los resultados directamente, será mucho más impresionante si elabora el código usted mismo.
Entonces, ¿existe una manera más rápida? Por ejemplo, si tu mensajero acaba de empezar a utilizar un IPHONE 4, ahora puedes considerar cambiarlo por un teléfono 6+. En .net, se proporcionan métodos relacionados con Emit para que pueda reflexionar más rápido. Hay una rueda llamada "Dapper" que te brinda una manera rápida de asignar valores a un modelo mediante reflexión para que puedas ir a casa y construirlo tú mismo.
¿Debo utilizar la reflexión en la programación?
En realidad, después de leer lo anterior, creo que ha hecho un juicio preliminar y mi punto es que puede utilizar la reflexión en la mayoría de los casos.
Si cree que la reflexión está provocando que el programa se ejecute más lento, primero verifique cuidadosamente el programa con un reductor de velocidad para ver si el problema es causado por la reflexión. Si se determina que el problema es la reflexión, entonces debe considerar si se utiliza una reflexión incorrecta, al igual que el mensajero que no conoce el camino. Finalmente, si cree que el rendimiento aún no es suficiente, le sugiero que actualice su hardware. Es mejor aumentar el rendimiento del hardware en un 3% que contratar a un ingeniero excelente para realizar este tipo de optimización extrema. Eso creo que es correcto: "Los ingenieros son mejores que los servidores, son caros". Si todavía quieres competir conmigo, no hay forma de que los requisitos de rendimiento de tu programa estén más allá del alcance de este artículo. Si realmente tienes esas necesidades, creo que no es necesario que leas este artículo porque ya eres lo suficientemente bueno. tener un conocimiento profundo del lenguaje del sistema.
La mayoría de las veces atribuimos el rendimiento de un programa al uso de lenguajes de programación o tecnologías como la reflexión, y rara vez nos preocupamos por nuestro propio código. Esta mentalidad hará que tus habilidades se desarrollen más lentamente. y más lento, porque has perdido las ganas de aprender y el corazón por el progreso tecnológico. Recuerde, a menudo es la forma en que piensa acerca de la programación y la forma en que codifica lo que afecta el rendimiento del programa.
Resumen
Está bien, después de haber dicho tanto, supongo que muchas personas simplemente lo arrastraron hasta el final del artículo y luego les gustó en silencio porque el artículo tiene muchas palabras. , Permítame presentarle la esencia de este artículo al final:
La velocidad de reflexión es aproximadamente 50 ~ 100 veces más lenta que la llamada directa, pero debe ejecutarla un millón de veces antes de puedo sentirlo
Para juzgar el desempeño de una función, necesitas ejecutar la función un millón o incluso diez millones de veces
Si solo llamas a la reflexión ocasionalmente, olvídate del impacto de reflexión sobre el rendimiento
Si necesita llamar a la reflexión con frecuencia, considere el almacenamiento en caché.
El factor más importante que limita el rendimiento del programa es tu forma de pensar en programación
.