Mostrando entradas con la etiqueta rendimiento. Mostrar todas las entradas
Mostrando entradas con la etiqueta rendimiento. Mostrar todas las entradas

jueves, 5 de diciembre de 2013

Profiling de aplicaciones

Profiling de aplicaciones

El profiling de aplicaciones es un estilo de análisis dinámico de software en el cual una herramienta llamada comunmente profiler recolecta información sobre el tiempo utilizado durante la ejecución de un programa por parte de los componentes a evaluar con el ánimo de identificar demoras o situaciones que puedan representar problemas de rendimiento de la aplicación. De manera general lo que se busca con este tipo de pruebas es identificar los tiempos o el uso de los componentes que conforman nuestra aplicación. 

El análisis realizado al utilizar la información recolectada durante la ejecución de la aplicación en cuestión estará relacionado directamente con el método utilizado para obtener los datos, por lo que el tipo de herramienta utilizada se vuelve de vital importancia para tener una buena idea de la calidad o resolución de los datos obtenidos.  Como regla podríamos decir que a medida que obtengamos mayor exactitud en los datos recolectados, mayor será el impacto en el rendimiento de la aplicación monitoreada. A continuación se describen los tipos más comunes de profilers según la forma utilizada para monitorear la ejecución y se presentan adicionalmente algunas ventajas y desventajas de los mismos.

Basados en eventos

Este tipo de herramientas permiten la verificación de la mayoría de los tipos de evento presentados durante la ejecución de la aplicación objetivo, por ejemplo, el inicio de un llamado a una función o la carga de una biblioteca dinamica.  Dado que la información se relaciona directamente los eventos producidos, este tipo de aplicaciones puede impactar el performance de la aplicación de manera general, por lo que es usual que se utilice en ambientes de desarrollo y pruebas de investigación pero no en escenarios donde afectar el rendimiento del sistema pueda representar un riesgo como en el ambiente de producción.  La resolución de este tipo de herramientas es por lo general mejor que la de otro tipo de profilers por la cantidad de datos recolectados pues no tienen pérdidas significativas de información relacionada con los eventos interceptados.

Profilers estadísticos

Los profilers estadísticos por otra parte funcionan recolectando muestras periódicas, es decir, interrumpiendo la ejecución de la aplicación analizada y verificando la tarea realizada en el momento de la interrupción.  Típicamente este tipo de profilers utilizan llamados a funciones del sistema operativo para suspender los procesos y obtener el valor del program counter o puntero a instrucción (EIP, RIP) periodicamente y realizar un recorrido llamado stackwalk en el que se identifican las funciones en la pila de llamados a partir de la navegación entre cada uno de los frames en la pila del hilo en ejecución.  Numéricamente los valores obtenidos con este tipo de herramientas son de una precisión inferior a los obtenidos con los profilers basados en eventos y esto se debe a que la información analizada corresponde únicamente a la obtenida para los puntos de ejecución muestreados, sin embargo, una cualidad de este tipo de herramientas radica en su bajo impacto en el rendimiento de la aplicación, logrando que el programa objetivo funcione más cerca de su velocidad real.

Profilers de instrumentación

Otro tipo de herramientas abordan el problema de obtención de datos modificando la aplicación que se desea analizar, al código agregado se le denomina instrumentación y dependiendo de los puntos instrumentados (por ejemplo si decidiéramos instrumentar todo el código) dentro de la aplicación puede suponer un gran impacto en el rendimiento de la aplicación medida.  Para que las pruebas sean efectivas y correctas este tipo de herramientas dependen en gran medida de lo específica que sea la instrumentación realizada y no brindan gran flexibilidad sobre el impacto en la aplicación.  Desafortunadamente para la identificación de problemas suele requerir que se tenga una idea de los componentes implicados en la situación para poder instrumentarlos, hecho que no siempre es evidente.

Salida de profilers


Según el tipo de salida generada los profiler peden clasificarse en dos categorías, la primera corresponde a aquellas herramientas que únicamente calculan el tiempo promedio por llamado sin preocuparse de diferenciar entre el tiempo propio del método o función involucrada y el tiempo consumido por los llamados a otros métodos por parte de dicha función, a este tipo de herramientas se les conoce como profilers planos o flat profilers.   La segunda categoría está asociada con las herramientas cuya salida contemplan en su análisis las diferentes rutas del código y el contexto de la ejecución y pueden diferenciar entre el tiempo própio consumido por una función del tiempo consumido por cada uno de sus llamados, a estas herramientas se les conoce como profilers de gráfos de llamadas y son más detallados y elaborados que los profilers planos.

miércoles, 4 de diciembre de 2013

Metricas y valores esperados

Métricas y valores esperados

Qué es una métrica y para qué sirve?

De manera sencilla una métrica se puede definir como una medida o un conjunto de medidas que determinan una característica de un sistema.  Por ejemplo, en un sistema de aprendizaje una métrica podría estar dada por el número de estudiantes reprobados en un curso, este valor nos dará una idea de una característica de nuestro sistema escolar por ejemplo para la metodología de los docentes.   Las métricas al igual que en el resto de disciplinas, se utiliza en el software para cuantificar aspectos de interés de modo que nos permita tener una visión clara y objetiva de lo que estamos midiendo y establecer mecanismos para mejorar dicha característica.  En esta entrada nos centraremos en las métricas de rendimiento de las aplicaciones, que como se espera nos ayudarán identificar problemas de rendimiento y poder tomar acciones sobre los mismos.  Dentro de los beneficios de proporciona la utilización de métricas en cualquier área del conocimiento y consecuentemente en el software tenemos:         
  • Análisis: Podremos analizar y comprender las capacidades del sistema en cuestión de manera objetiva.
  •  Control: Se pretende poder realizar ajustes utilizando la información de dichas métricas para mantener las características en los estados deseados.
  •   Predicción: Una vez se ha iniciado un estudio con el uso de métricas sobre una característica de un sistema se hace más fácil predecir situaciones que de otra manera serían imposibles de entender.
  •  Mejora: Las métricas nos proporcionan herramientas para mejorar las características que cuantificamos.  Si se manejan objetivamente, mejorar una métrica en la mayoría de los casos es equivalente a mejorar la característica en cuestión.


Es importante tener en cuenta que solamente aquellas características que son susceptibles de ser medidas podrán manejarse utilizando métricas, por suerte, en la evaluación del performance de las aplicaciones casi todas las características se pueden medir.  Aunque parezca extraña esta aclaración, existen aspectos de la vida que no se pueden medir, como la moral , la felicidad y muchos otros aspectos relacionados con cuestiones humanas, en términos generales lo medible está asociado a unidades físicas, como tiempo, espacio, memoria, etc.  Las métricas están basadas en conceptos medibles que son relaciones abstractas entre las características de las entidades medidas.

En la evaluación del software existen algunos objetos o entidades de interés particular en el estudio del comportamiento de las aplicaciones.  A continuación presentamos algunas:

  •          Servicios
  •          Productos
  •          Procesos
  •          Recursos


Las características o atributos según su cercanía con los usuarios pueden ser internos o externos, dependiendo de si los usuarios son conscientes de la existencia de la característica.  Dentro de las características que nos interesan medir para el performance de aplicaciones encontramos dos que suelen ser importantes.

  •          Comportamiento en el tiempo
  •          Utilización de recursos


Usualmente el comportamiento en el tiempo es afectado por la utilización de los recursos y los recursos son retenidos por problemas de lógica con un rendimiento pobre.  Por ejemplo si una aplicación web utiliza una base de datos y la aplicación tiene problemas de desempeño, dicha aplicación podría provocar bloqueos en los recursos de la base de datos, de la misma manera si los recursos no fueran suficientes en el servidor de bases de datos se podrían presentar pérdidas de rendimiento en la aplicación web que la usa.  Casi todas las métricas de performance están asociadas a cuantificar aspectos que se relacionan con el tiempo o con los recursos. 

Una métrica consta de un método de medición por ejemplo una formula y una escala para los valores obtenidos a partir de dicho método.   Las métricas pueden ser directas si solo dependen de la característica o atributo que se está midiendo o indirectas si dependen adicionalmente de otras métricas y se formalizan a partir de una función de medición.

Las métricas de rendimiento por lo general son independientes de los escenarios, de las plataformas, del hardware y de la lógica de negocio que se esté probando.

Categorización de métricas

Según la cercanía con el usuario

  •          Internas: La característica que evalúa la métrica depende únicamente de factores internos del diseño y los usuarios no tienen consciencia de su existencia.


  •          Externas: Los Usuarios son conscientes o tienen un contacto directo con la característica que evalúa la métrica en cuestión y sus valores pueden depender de aspectos específicos de la lógica de negocio de la aplicación.

Según sus valores deseables

Las métricas de performance según los valores deseados se pueden categorizar en tres tipos:

  •          Deseablemente decrecientes: Este tipo de métricas son aquellas en las cuales esperamos que un mejor comportamiento de la característica que pretende medir en el sistema esté asociado con la disminución del valor de dicha métrica, es decir, mientras menor sea el valor será mejor.  Un ejemplo de esta categoría es el tiempo de respuesta de una aplicación, se espera que mejoras en el rendimiento se reflejen en la disminución de los valores de dicha métrica.


  •          Deseablemente crecientes: A diferencia de la categoría  anterior, a este conjunto de métricas pertenecen aquellas en las que un incremento de los valores obtenidos se asocia con una mejora en el rendimiento de la aplicación.  Como ejemplo podemos ver el throughput o la productividad del sistema mientras mayor sea su valor mayor mejor será el rendimiento del sistema.


  •          Valores nominales deseables: En ocasiones existen características de nuestras aplicaciones cuyos indicadores o métricas asociadas no convienen que sean demasiado bajas o demasiado altas sino que se encuentren en lo que llamamos un valor nominal, el cual es el valor óptimo o deseado para la característica analizada.  Un ejemplo de este tipo de métricas es la utilización de la CPU, si el valor es muy bajo para un gran volumen de transacciones, puede deberse a problemas de rendimiento de la aplicación en cuestión desperdiciando el recurso específico y si el uso de CPU es muy alto, la aplicación podría estar impactando otros aspectos del servidor como la estabilidad del propio sistema operativo haciendo que todo fluya de manera más lenta y riesgosa.  Podríamos decidir de manera arbitraria que el valor nominal fuera un 50%.

Según el marco de referencia

Dependiendo de si una característica se evalúa en un solo contexto o si existen valores de referencia con los cuales se contrastan las mediciones, las métricas se pueden clasificar en las siguientes categorías:

  •           Absolutas: Son aquellas métricas que dependen únicamente de mediciones realizadas en la aplicación que se está midiendo, por lo cual únicamente reflejan el comportamiento de la característica evaluada de manera individual o aislada. Un ejemplo de este tipo de métricas sería el tiempo de respuesta de un método en una clase.


  •           Relativas: Las métricas pertenecientes a este grupo definen el comportamiento de la característica evaluada en relación a un comportamiento base que en muchos casos corresponde a una segunda aplicación de referencia, por ejemplo, la diferencia entre los tiempos de respuesta de dos aplicaciones.  Las métricas pueden ser relativas a otras métricas o a valores nominales.

Según la naturaleza de la medición

  •          De recursos: La característica medida se relacionada con recursos del sistema, por ejemplo, el número de escrituras en disco debido a un evento dado.


  •          De tiempo: La característica evaluada es una duración o un valora asociado al tiempo como el periodo o la frecuencia de un evento.


  •          De complejidad: Este tipo de métricas pretende cuantificar la complejidad computacional del sistema, por ejemplo, para el número de ciclos en el código para una operación particular.  Aunque puede que estas no midan directamente temas de desempeño, puede que perdidas en el desempeño estén relacionadas directas o indirectamente con los aspectos medidos por las mismas.



  •          De calidad: Encontramos en algunas ocasiones métricas que no miden ni recursos, ni tiempos, ni temas de complejidad, sin embargo, el mejoramiento de las mismas puede representar un mejoramiento en el rendimiento del sistema. Un ejemplo podría ser la tendencia en un comportamiento de la aplicación como la estabilidad o cualquier aspecto del diseño.

sábado, 30 de noviembre de 2013

Pruebas de performance

¿Qué son las pruebas de rendimiento?

De manera sencilla podemos definir las pruebas de rendimiento como un conjunto de pruebas que son realizadas a una aplicación para determinar el comportamiento del performance de la misma, identificar puntos potenciales de mejora o garantizar los niveles de servicios esperados por los clientes del sistema.  Actualmente este tipo de pruebas son realizadas en la mayoría de los proyectos de tecnología únicamente a aquellas aplicaciones de ejecución crítica que puedan afectar la operación del negocio, aunque cada vez más se evidencia la necesidad de realizar este tipo de pruebas para los diferentes aspectos del código producido y consecuentemente los proyectos de tecnología hacen cada vez un mayor uso de pruebas de stress y de carga en un mayor número de compontes de sus sistemas.   
Cabe recordar que las pruebas de rendimiento pueden realizarse en diferentes niveles del desarrollo, pueden planearse y ejecutarse mucho antes de que se haya finalizado el desarrollo en su totalidad, por ejemplo, podríamos realizar pruebas de rendimiento a cada uno de los componentes que integran el desarrollo en conjunto con las pruebas unitarias de los mismos y a medida que se vayan integrando podríamos realizar otras pruebas de integración entre componentes que aseguren que no existan problemas de rendimiento en la forma en la cual interactúan a partir del diseño del sistema.  Realizar pruebas de rendimiento de manera temprana es una buena forma de establecer garantías parciales en el mediano plazo que nos permitan avanzar hacia los objetivos de performance definidos con una incertidumbre menor.

¿Por qué son necesarias?

Podría pensarse que las pruebas de rendimiento pueden ser ejecutadas de manera posterior al despliegue de nuestras aplicaciones, sin embargo, debemos tener claro que las pruebas de rendimiento tienen como objetivo fundamental anticipar los problemas de performance que puedan ocurrir una vez la aplicación esté en producción.  Una vez que se haya llevado a cabo la entrega de un desarrollo, será mucho más difícil encontrar formas de sobrellevar problemas de desempeño detectados en la operación ya que en esta etapa contaremos con un menor control sobre las características que podremos cambiar para cumplir los nuevos objetivos.
Las pruebas de rendimiento adicionalmente nos ayudan a visualizar tiempos muertos de las aplicaciones que de otra manera no hubieran podido detectarse, redundando en un mayor conocimiento las tareas que consumen mayor tiempo, de los límites del código producido y adicionalmente en la identificación de los puntos más frágiles de la aplicación.  Cada uno de estos aspectos es de vital importancia si deseamos descubrir mejores formas de realizar las operaciones pertinentes. 

¿Cómo pueden ayudarnos?

Las pruebas de rendimiento pueden hacernos la vida más fácil o más difícil dependiendo de la forma en la que se gestione la ejecución de dichas pruebas, si no se tienen claros temas del proyecto relacionados con costos, tiempos de entrega y parámetros específicos de las pruebas realizadas podemos entrar en un ciclo infinito de pruebas rechazadas. 
Es importante entender los conceptos o las características que se están midiendo y como se alinearán dichas mediciones con los objetivos del proyecto antes de iniciar un plan de pruebas que probablemente arrojen resultados de poco valor que no nos permitan mejorar nuestros productos. 
Otra forma en la que las pruebas de performance pueden ayudarnos está relacionada con la capacidad de predecir comportamientos a partir de los volúmenes de datos u operaciones de manera tal que podamos ser capaces de entregar guidelines o documentación clara sobre el rendimiento que debe ser esperado por parte de los usuarios del sistema, por ejemplo, si hemos construido una aplicación para construir pantallas de captura de datos en la web y entregamos una documentación que establezca que el tiempo promedio de procesamiento para un control en una página tiene un tiempo promedio de 1 ms bajo ciertas condiciones, con seguridad podremos establecer los requisitos de hardware mínimos para que dicha premisa se cumpla y adicionalmente podremos evitar mediante políticas de desarrollo que los usuarios del sistema intenten construir páginas con 3000 controles que demorarían en promedio 3 segundos en cargar lo que podría ocasionar otro tipo de problemas en el desempeño general de la aplicación.

Etapas generales de una prueba

Una prueba de rendimiento por lo general se encuentra divida en tres fases.  A continuación se presenta una breve descripción de cada una de ellas.
Construcción: En esta etapa de la prueba se identifican los casos que serán susceptibles de ser probados, se define la manera en la cual se realizará la prueba y se construyen scripts o artefactos que permitirán su ejecución. 
Ejecución:  El objetivo en esta fase es el de utilizar los artefactos construidos para la ejecución de la prueba con el fin de obtener información sobre las métricas, los casos y/o características definidas durante la construcción.
Análisis: Una vez que se haya recolectado la información que se ha obtenido durante las ejecuciones de las pruebas de rendimiento se deberá proceder a analizar la información según para poder tomar acciones los resultados encontrados.
A pesar de que puede parecer sencillo, la obtención de los datos de una prueba con un nivel de confianza relativamente bueno puede suponer algunos retos a la hora de poner en marcha el plan.  Temas como el aislamiento de los ambientes, el estados de los recursos, temas de configuración de la aplicación y los errores humanos pueden repercutir en la invalidez de las pruebas realizadas, derivando en la necesidad de repetir la prueba una y otra vez hasta que se logue la confianza suficiente en los datos y los procedimientos utilizados.



Validez de pruebas

Como se mencionó anteriormente las pruebas pueden invalidarse por un gran número de razones de diferente naturaleza, por esta razón sería una buena idea tener claros los escenarios más comunes que puedan presentarse para que una prueba pierda su validez.  En esta sección presentaremos algunos de estos escenarios e intentaremos detallar ejemplos asociados con los mismos.

Aislamiento del ambiente de pruebas

Un caso común en las áreas de tecnología de las empresas hoy en día corresponde al reúso de recursos para los ambientes de IT, ser reutiliza la infraestructura con el objetivo de reducir costos, por esta razón, encontramos ambientes virtualizados que comparten hardware entre sí con el fin de optimizar las operaciones, estas situaciones pueden representar un riesgo al momento de realizar pruebas de rendimiento, ya que si el ambiente que ha sido destinado para pruebas también se utiliza en otro tipo de tareas como por ejemplo como ambiente de desarrollo, los resultados de nuestras pruebas podrían no ser del todo confiables. 
Teniendo como base el planteamiento anterior podemos inferir que para que la validez de nuestras pruebas no se vean afectadas por operaciones sobre el ambiente externas a los escenarios probados es fundamental que el ambiente de pruebas esté físicamente aislado de otros ambientes.  Esto no quiere decir que el ambiente deba estar totalmente desconectado, por ejemplo, de la red de nuestra compañía o que deba ser privado de cualquier servicio de comunicación con otros elementos de la infraestructura, lo que realmente nos dice es que los recursos destinados para pruebas deben estar lo suficientemente disponibles para garantizar que la aplicación probada no presentará pérdidas de rendimiento debido a elementos externos a la misma prueba y a las condiciones naturales de la plataforma sobre la que opera. 

 

Disponibilidad de recursos suficientes

Aún cuando el ambiente se encuentre físicamente aislado durante la realización de las pruebas de rendimiento, es posible que existan elementos locales dentro de las máquinas utilizadas, por ejemplo, componentes ajenos a la prueba que puedan consumir intensivamente recursos computacionales como podrían ser instalaciones imprevistas de aplicativos, ejecución de análisis de antivirus o condiciones específicas del sistema operativo pueden provocar una disminución en los tiempos obtenidos en la prueba de manera, hecho que podría confundirse con mejoras o disminución del rendimiento al ser comparados con pruebas que hayan sido realizadas en ausencia de la ejecución de dichos componentes.  Entonces podemos decir que se debe verificar que los recursos locales no están siendo afectados de manera intensiva por aplicaciones externas a la prueba.  De igual manera otras tareas en ejecución como la descarga de grandes volúmenes de información de internet durante el tiempo de la prueba puede afectar  recursos utilizados por la aplicación probada como el acceso a la red.

Invariabilidad del hardware y software

Una vez que se ha garantizado que las condiciones físicas y locales del ambiente de pruebas se perciben como estables podemos comenzar a realizar nuestras pruebas, pero en caso de utilizar diferentes ambientes para realizar las mismas debemos garantizar que las mediciones de tiempos se realicen utilizando recursos de hardware equivalentes, es decir, asegurar que a pesar de que las pruebas se hayan realizado en diferentes máquinas, las especificaciones del hardware utilizado sean exactamente iguales o muy similares, en caso de ser diferentes las pruebas son incomparables a menos que los resultados de las pruebas se evalúen en términos relativos, como porcentaje del tiempo consumido. 
Si una aplicación se prueba dos veces en ambientes con especificaciones de software diferentes, como por ejemplo, máquinas con sistemas operativos diferentes o con diferencias en parches instalados del sistema, es posible que las operaciones realizadas en ambas pruebas no se realicen de la misma manera, por lo cual nuevamente las pruebas no son comparables entre sí.  Lo más cómodo en términos generales al momento de ejecutar un conjunto de pruebas es seleccionar un único ambiente, aislado y controlado para ejecutar todas las pruebas pertinentes, de esta manera no deberemos preocuparnos por las diferencias de hardware o software pues el ambiente será igual para todas las muestras recolectadas haciendo que los resultados entre pruebas puedan se comparables entre si y tengamos una mayor confianza en los datos obtenidos.

Representatividad del tamaño de muestras

Aún cuando el ambiente esté aislado, las condiciones locales del sistema sean uniformes y no existan diferencias de hardware o software entre las pruebas realizadas, debemos entender que el estado de las máquinas en la que se hospedan nuestras aplicaciones está sujeto a variaciones no predecibles, como por ejemplo el uso de la memoria virtual, caídas repentinas de la disponibilidad de ciertos servicios como la red o tecnologías asociadas con la reducción del consumo energético de los equipos y procesadores. 
Por el motivo anteriormente expresado, es necesario tener un tamaño de muestreo representativo, con el fin de descartar los casos atípicos y poder establecer un comportamiento promedio o general de las características que deseamos cuantificar.  Mientras mayor sea el número de muestras recolectadas tendremos una visión más completa del comportamiento medido.  Determinar el número de pruebas a realizar para obtener un nivel de confianza aceptable puede llevarnos a un análisis más formal y estadístico, aunque usualmente este tipo de métodos no son utilizados con frecuencia por lo que se trata de realizar las pruebas con el mayor número posible de iteraciones o usuarios, por ejemplo por encima del número promedio real.  Tener un número muy bajo de pruebas puede invalidar los resultados obtenidos a partir de las mismas.

Repetitividad o repetibilidad de Casos

Otro factor que suele ser determinante para identificar la validez de una prueba puede estar relacionado con la capacidad que tiene la prueba de ser "repetible", para exponer la importancia de este concepto, plantearemos un escenario en el cual una aplicaciones realiza un conjunto de tareas diferentes de manera aleatoria, si realizamos las pruebas de dicha aplicación ¿cómo podemos asegurar que todas las pruebas miden los mismos aspectos?, de hecho, no lo hacen, por lo que se evidencia la necesidad de que los casos probados sean perfectamente reproducibles de modo que podamos establecer comparaciones sobre los resultados obtenidos.  En algunas ocasiones la repetibilidad puede estar asociada a los diferentes caminos lógicos que una aplicación puede tomar durante su ejecución y en otras ocasiones dichos cambios dependerán de los datos suministrados como entrada de los algoritmos implementados. 
Algunas veces es casi imposible lograr que el número de llamados a todas las funciones sean exactamente igual entre pruebas, sobre todo si lo que intentamos comparar está relacionado con mejoras debido a modificaciones sobre los algoritmos codificados.  En estos casos es posible realizar las comparaciones normalizando los datos, por ejemplo  si una aplicación ejecutó diez veces el método A() en la prueba 1 y 30 veces el mismo método en la prueba 2 podremos comparar los resultados dividiendo el tiempo T1(A) entre 10 lo que nos dará el tiempo promedio de A durante la prueba 1 y podemos hacer lo mismo para la prueba número 2 obteniendo el tiempo promedio de A durante la prueba 2 al restar T2(A) - T1(A) podremos establecer la diferencia entre los tiempos promedio aún cuando las dos pruebas no coincidan en el número de llamados. 
Analizar tiempos de funcionalidades entre pruebas con diferente número de llamados y sin normalizar los tiempos puede ser un factor para invalidar las conclusiones obtenidas en las pruebas realizadas.

Confiabilidad de herramientas y mediciones


Bueno, como último aspecto a considerar para evitar que nuestra prueba sea confiable tenemos la confiabilidad de las herramientas que son utilizadas para realizar las mediciones de las características que deseamos evaluar.  Obtener datos a partir de herramientas que puedan retrasar en demasía los tiempos de la aplicación a probar puede llevarnos a conclusiones erróneas sobre el comportamiento de la misma.  En los posible las herramientas utilizadas deben estar certificadas o ser reconocidas como herramientas que arrojan resultados confiables y que tienen el menor efecto posible en la prueba.