Si usamos Dynamic Invoke
, ¿hay alguna mejora en el rendimiento de la aplicación? Si no, ¿cuál es su ventaja?Función de invocación dinámica en java
Respuesta
puede consultar este enlace. http://www.infoq.com/news/2010/09/jdk7-slip Hope esto le ayudará a
http: //meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers –
Creo que te refieres a la reflexión por invocación dinámica. El costo de la reflexión es un poco más alto que la invocación al método normal.
reflexión tiene muchos usos, por ejemplo, lo uso extensivamente para la unión ui-datos ..
supongo OP significa InvokeDynamic como se ha mencionado aquí http://java.sun.com/developer/technicalArticles/DynTypeLang/index.html para la invocación del método. Nunca he usado pero this post looks very descriptive cotizaciones
"La diferencia de rendimiento puede no importar para una biblioteca que hace algunas llamadas reflejadas, especialmente si esas llamadas son principalmente para establecer dinámicamente una estructura estática en la memoria contra la que puede hacer normal llamadas. Pero en un lenguaje dinámico, donde cada llamada debe usar estos mecanismos, es un golpe de rendimiento severo ".
Así que la respuesta final es la siguiente:
invocación dinámica con callsites es más rápido que las llamadas a métodos tradicionales.
Lo único más rápido para el acceso de campo es acceder directamente al campo sin realizar ninguna llamada a métodos ni utilizar inseguros.
La respuesta es no invocar La dinámica no es lenta. Es rápido. Es muy rápido.
actualización más reciente:
Otra actualización (más tarde ese mismo domingo) me cambió el código para utilizar un callsite de invocación dinámica y que cambió el tiempo un poco.
(Todo funciona con JDK 1.8 construir 94)
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b94)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b36, mixed mode)
1,000 carreras
description duration in nanoseconds
regular method call time 2095
invoke dynamic method call time 1098
reflection method call time 3104
field method invoke dynamic call time 1165
field method invoke reflection call time 689
unsafe field access time 94
direct field access (baseline) 92
10.000 carreras
description duration in nanoseconds
regular method call time 68
invoke dynamic method call time 43
reflection method call time 202
field method invoke dynamic call time 42
field method invoke reflection call time 45
unsafe field access time 87
direct 86
100.000 carreras
description duration in nanoseconds
regular method call time 70
invoke dynamic method call time 44
reflection method call time 249
field method invoke dynamic call time 45
field method invoke reflection call time 47
unsafe field access time 88
direct 36
1.000.000 carreras
description duration in nanoseconds
regular method call time 11
invoke dynamic method call time 6
reflection method call time 12
field method invoke dynamic call time 6
field method invoke reflection call time 4
unsafe field access time 1
direct 0
10.000.000 carreras
description duration in nanoseconds
regular method call time 9
invoke dynamic method call time 6
reflection method call time 25
field method invoke dynamic call time 6
field method invoke reflection call time 4
unsafe field access time 1
direct 0
100.000.000 carreras
description duration in nanoseconds
regular method call time 9
invoke dynamic method call time 6
reflection method call time 12
field method invoke dynamic call time 6
field method invoke reflection call time 4
unsafe field access time 1
direct 0
código actualizado que utiliza la llamada-s ite con invocación dinámica
//fieldName is the reflection field (example below how to look it up and change its access)
MethodHandle methodHandleFieldDirect = lookup.unreflectGetter(fieldName);
CallSite callSiteField = new ConstantCallSite(methodHandleFieldDirect);
methodHandleFieldDirect = callSiteField.dynamicInvoker();
name = (String) methodHandleFieldDirect.invokeExact(new Employee());
//Lookup invoke dynamic
methodType = MethodType.methodType(String.class);
methodHandle = lookup.findVirtual(Employee.class, "getName", methodType);
CallSite callSiteMethod = new ConstantCallSite(methodHandleFieldDirect);
methodHandle = callSiteMethod.dynamicInvoker();
Para ver el resto, debes ver la entrada del blog. Hay ejemplos de uso inseguro, reflexión, llamadas, dinámica de invocación y el resto. :)
Los sitios de llamadas son importantes para acelerar la dinámica de invocación.
http://rick-hightower.blogspot.com/2013/10/java-invoke-dynamic-examples-java-7.html
Update (actualización anterior):
Saqué el código hash y el recuento de código, que añadí porque la reflexión fue tan rápido que pensé que los bucles se estaban compilados JIT por completo de alguna manera:
de 10 millones de carreras con recuento/código hash removidos employee.getName()- de llamada método regular de tiempo = 25 nanosegundos
- invocar tiempo de llamada método dinámico = 18 nanosegundos **
- reflexión de llamada método de tiempo = 36 nanosegundos método
- campo invocar llamada dinámica en tiempo = 8 nanosegundos método
- campo de llamada reflexión tiempo = 6 nanosegundos
- de llamada método regular de tiempo = 70 nanosegundos **
- invocar tiempo de llamada método dinámico = 84 nanosegundos tiempo método
- reflexión llamada = 211 nanosegundos método
- campo invocar tiempo llamada dinámica = 153 nanosegundos
- campo método de llamada reflexión tiempo = 40 nanosegundos
Hay una mejora en el rendimiento sobre la reflexión, pero es Complicado. Depende de cuántas veces hagas las llamadas. Probablemente solo le importe si el código está en un círculo cerrado.
Los puntos de referencia que he visto recientemente muestran una mejora de 15 veces sobre la reflexión simple, y solo 2,5 veces más lenta que invocar un método de la manera normal. Pero ya conoces el viejo dicho, no creas nada y solo 1/2 de lo que lees.
Creo que lo probaría.
He estado bromeando con la reflexión e invocado la dinámica por un momento. see A short write up on invoke dynamic.
Éstos son los resultados que consigo que utilizan JDK 1.8 build 94.
un millón de llamadas (resultados están en nano segundos):
10.000 miles de llamadas
regular method call time = 103
invoke dynamic method call time = 116
reflection method call time = 252
100.000 llamadas (después del calentamiento).
regular method call time = 46
invoke dynamic method call time = 112
reflection method call time = 171
1.000.000 llamadas
regular method call time = 23
invoke dynamic method call time = 35
reflection method call time = 30
reflexión es más rápido en 1 M de invocar dinámico. Ummm ... Odd.
10.000.000 llamadas
regular method call time = 34
invoke dynamic method call time = 24
reflection method call time = 43
Ahora invocan dinámica es más rápido que una llamada a un método regular!
Ahora 100.000.000
regular method call time = 22
invoke dynamic method call time = 24
reflection method call time = 28
En este punto, el compilador JIT lleva todo el dolor de distancia. Si no puede dedicarle un extra de 2 a 6 nano segundos, entonces necesita tener algunas habilidades de afrontamiento.
Este es el código para recrear las pruebas (también siga el siguiente enlace):
MethodHandles.Lookup lookup = MethodHandles.lookup();
Class thisClass = lookup.lookupClass(); // (who am I?)
MethodType methodType;
MethodHandle methodHandle;
crear un objeto empleado.
Employee employee = new Employee();
Busque getName con invoke dynamic (consulte el blog para obtener más ejemplos, enlace más arriba).
//Lookup invoke dynamic
methodType = MethodType.methodType(String.class);
methodHandle = lookup.findVirtual(Employee.class, "getName", methodType);
name = (String) methodHandle.invokeExact(new Employee());
System.out.println("invoke dynamic " + name);
Busque Employee.getName with reflection.
//Lookup reflection
Method method = Employee.class.getMethod("getName", new Class<?>[]{});
name = (String) method.invoke(new Employee());
System.out.println("reflection " + name);
Hora de inicio, hora de finalización, número de iteraciones (tiempos), tiempos calculados, los sospechosos habituales.
long start = 0;
long end = 0;
long times = 100_000_000;
long regularTime;
long invokeDynamicTime;
long reflectionTime;
long count=0;
Ahora vamos a calentar la JVM.
//warm up
for (int index =0 ; index < times; index++) {
employee.getName();
name = (String) methodHandle.invokeExact(employee);
name = (String) method.invoke(employee);
}
Calculemos la invocación de método regular.
start = System.nanoTime();
for (int index =0 ; index < times; index++) {
name = employee.getName();
count += name.hashCode();
}
count=0;
end = System.nanoTime();
regularTime = end - start;
System.out.printf("regular method call time = %d\n", regularTime/times);
P.S. Añadí el conteo, por lo que mi código no sería borrado de alguna manera.
Ahora calculemos invokeDyanmic time.
start = System.nanoTime();
for (int index =0 ; index < times; index++) {
name = (String) methodHandle.invokeExact(employee);
count += name.hashCode();
}
count=0;
end = System.nanoTime();
invokeDynamicTime = end - start;
System.out.printf("invoke dynamic method call time = %d\n", invokeDynamicTime/times);
Ahora calculemos el tiempo de reflexión.
start = System.nanoTime();
for (int index =0 ; index < times; index++) {
name = (String) method.invoke(employee);
count += name.hashCode();
}
count=0;
end = System.nanoTime();
reflectionTime = end - start;
System.out.printf("reflection method call time = %d\n", reflectionTime/times);
He decidido agregar uno más a la mezcla. Si realmente quiere la propiedad, ¿qué ocurre si accede al campo directamente?
10.000
regular method call time = 109
invoke dynamic method call time = 115
reflection method call time = 236
field method invoke dynamic call time = 178
field method reflection call time = 709
100_000
regular method call time = 49
invoke dynamic method call time = 118
reflection method call time = 312
field method invoke dynamic call time = 75
field method reflection call time = 158
1_000_000
regular method call time = 28
invoke dynamic method call time = 41
reflection method call time = 30
field method invoke dynamic call time = 11
field method reflection call time = 18
10_000_000
regular method call time = 28
invoke dynamic method call time = 41
reflection method call time = 30
field method invoke dynamic call time = 11
field method reflection call time = 18
100_000_000
regular method call time = 40
invoke dynamic method call time = 25
reflection method call time = 44
field method invoke dynamic call time = 10
field method reflection call time = 9
Ok, aquí está el código para el acceso de campo que es 4 veces más rápido que el uso de employee.getName().
long start = 0;
long end = 0;
long times = 10_000_000;
long regularTime;
long invokeDynamicTime;
long reflectionTime;
long invokeDynamicTimeUsingField;
long fieldDirect;
long count=0;
//warm up
for (int index =0 ; index < times; index++) {
employee.getName();
name = (String) methodHandle.invokeExact(employee);
name = (String) method.invoke(employee);
name = (String) methodHandleFieldDirect.invokeExact(employee);
}
start = System.nanoTime();
for (int index =0 ; index < times; index++) {
name = employee.getName();
count += name.hashCode();
}
count=0;
end = System.nanoTime();
regularTime = end - start;
System.out.printf(" regular method call time = %d\n", regularTime/times);
start = System.nanoTime();
for (int index =0 ; index < times; index++) {
name = (String) methodHandle.invokeExact(employee);
count += name.hashCode();
}
count=0;
end = System.nanoTime();
invokeDynamicTime = end - start;
System.out.printf(" invoke dynamic method call time = %d\n", invokeDynamicTime/times);
start = System.nanoTime();
for (int index =0 ; index < times; index++) {
name = (String) method.invoke(employee);
count += name.hashCode();
}
count=0;
end = System.nanoTime();
reflectionTime = end - start;
System.out.printf(" reflection method call time = %d\n", reflectionTime/times);
start = System.nanoTime();
for (int index =0 ; index < times; index++) {
name = (String) methodHandleFieldDirect.invokeExact(employee);
count += name.hashCode();
}
count=0;
end = System.nanoTime();
invokeDynamicTimeUsingField = end - start;
System.out.printf(" field method invoke dynamic call time = %d\n", invokeDynamicTimeUsingField/times);
//
start = System.nanoTime();
for (int index =0 ; index < times; index++) {
name = (String) fieldName.get(employee);
count += name.hashCode();
}
count=0;
end = System.nanoTime();
fieldDirect = end - start;
System.out.printf(" field method reflection call time = %d\n", fieldDirect/times);
}
Ahora el campo de la reflexión real/invocar código dinámico:
Employee employee = new Employee();
fieldName = null;
for (Field field : Employee.class.getDeclaredFields()) {
if (field.getName().equals("name")) {
fieldName = field;
fieldName.setAccessible(true);
break;
}
}
MethodHandle methodHandleFieldDirect = lookup.unreflectGetter(fieldName);
name = (String) methodHandleFieldDirect.invokeExact(new Employee());
System.out.println("method handle for field direct " + name);
//Lookup invoke dynamic
methodType = MethodType.methodType(String.class);
methodHandle = lookup.findVirtual(Employee.class, "getName", methodType);
name = (String) methodHandle.invokeExact(new Employee());
System.out.println("invoke dynamic " + name);
//Lookup reflection
Method method = Employee.class.getMethod("getName", new Class<?>[]{});
name = (String) method.invoke(new Employee());
System.out.println("reflection " + name);
- 1. Java función dinámica llamando
- 2. Invocación de método de clase dinámica en PHP
- 3. Función inmediata sintaxis de invocación
- 4. Invocación encadenada en Java 7?
- 5. invocación de Java desde C++
- 6. Función de auto invocación con nombre
- 7. Función dinámica docstring
- 8. función dinámica argumentos
- 9. Método de invocación Java desde PHP5
- 10. Java - Invocación y ejecución de métodos
- 11. Java anotación tipografía dinámica
- 12. declaración de matriz dinámica en java
- 13. Arrays de longitud variable (dinámica) en Java
- 14. Carga dinámica de módulos en Java
- 15. Javascript nuevo objeto (función) vs invocación en línea
- 16. nombres de función dinámica de Python
- 17. tipo de retorno de una función dinámica
- 18. clases creación dinámica con Java
- 19. setTimeout() en función recursiva dentro de una función de invocación automática
- 20. P/Función de invocación que toma el puntero a struct
- 21. Invocación simplificada del método Varargs en Java 7
- 22. Funciones de invocación automática en JavaScript
- 23. consulta de django en función de la propiedad dinámica()
- 24. Cómo combinar objetos Java de forma dinámica
- 25. C++ asignación de memoria dinámica en una función - pregunta novato
- 26. Anotación personalizada de Java y carga dinámica
- 27. Función dentro de una función en Java
- 28. ¿Para qué sirve la invocación de un método virtual Java?
- 29. ¿Cómo expongo la función de la función de auto invocación anónima?
- 30. document.write Invocación()
es con respecto característica dinámica de invocación en el JDK 7. – user556913
@ T. J. Crowder: Creo que se está refiriendo a la nueva instrucción 'bytecode' invookedynamic en Java 7. http://java.sun.com/developer/technicalArticles/DynTypeLang/index.html – coobird
@coobird, @user: Gracias. –