Simple Science

Ciencia de vanguardia explicada de forma sencilla

# Informática# Ingeniería del software

Evaluando herramientas de análisis estático para gráficos de llamadas en JavaScript

Un estudio sobre el rendimiento de cinco herramientas de análisis estático de JavaScript.

― 8 minilectura


Analizando herramientasAnalizando herramientasde código JavaScriptJavaScript.análisis estático para la eficiencia deEl estudio compara herramientas de
Tabla de contenidos

JavaScript es un lenguaje de programación popular que se usa tanto en el lado del cliente como en el del servidor. Debido a su uso generalizado, analizar el código de JavaScript se ha vuelto cada vez más importante. Muchos métodos para encontrar vulnerabilidades, problemas de codificación o problemas de tipos dependen de entender el grafo de llamadas de un programa. Un grafo de llamadas es un mapa que muestra cómo las Funciones en un programa se llaman entre sí.

Aunque el análisis dinámico, que implica ejecutar el programa, tiene sus beneficios, el Análisis Estático es valioso porque no requiere ejecutar el programa. Los métodos estáticos para crear grafos de llamadas pueden ahorrar tiempo y recursos. En este estudio, analizamos cinco métodos de análisis estático populares que crean grafos de llamadas para JavaScript. Probamos estos métodos en un conjunto de programas de referencia y módulos reales de Node.js para ver cómo se desempeñan en términos de velocidad, uso de memoria y precisión.

¿Qué es un grafo de llamadas?

Un grafo de llamadas muestra las funciones en un programa como nodos y las llamadas entre esas funciones como aristas. Si una función llama a otra, habrá una arista dirigida desde la función que llama a la función llamada. Al analizar este grafo, podemos descubrir varios problemas, como funciones que nunca son llamadas o errores en cuántos argumentos se pasan a una función.

Esta representación es crítica para las verificaciones de calidad y seguridad en JavaScript. Por ejemplo, ayuda a construir análisis más complejos, como los grafos de flujo de control, que proporcionan una visión más profunda de cómo opera un programa.

La importancia del análisis estático de código

Con el aumento de proyectos de JavaScript, el análisis estático de código ha ganado importancia. El análisis estático se refiere a examinar el código sin ejecutarlo. Esto significa que los desarrolladores pueden encontrar problemas potenciales antes de ejecutar el código, ahorrando tiempo y evitando errores.

Existen muchas herramientas para realizar análisis estático, y la mayoría de ellas dependen de grafos de llamadas para ofrecer información sobre el programa. Un grafo de llamadas preciso puede afectar directamente la efectividad de estas herramientas de análisis.

Sin embargo, JavaScript es un lenguaje dinámico y flexible, lo que hace que sea un desafío crear grafos de llamadas precisos. Las técnicas que funcionan bien con otros lenguajes pueden no ser efectivas con JavaScript debido a sus características únicas, como permitir pasar funciones como argumentos o crearlas en tiempo de ejecución.

Herramientas de análisis estático

En nuestro estudio, analizamos cinco herramientas que crean grafos de llamadas para JavaScript. Estas herramientas son:

  1. grafo de llamadas de npm
  2. IBM WALA
  3. Google Closure Compiler
  4. Grafo de Llamadas Aproximado (ACG)
  5. Analizador de Tipos para JavaScript (TAJS)

Estas herramientas fueron elegidas por su popularidad y practicidad. Cada herramienta opera de manera diferente, pero todas buscan analizar el código de JavaScript y producir grafos de llamadas.

Metodología

Para comparar estas herramientas, las analizamos usando varios programas de prueba. Seleccionamos 26 programas de referencia del conjunto de pruebas de SunSpider, que se usa ampliamente para medir el rendimiento de JavaScript. Además, incluimos seis módulos reales de Node.js conocidos por su complejidad.

Ejecutamos cada herramienta con estas entradas, recopilando datos sobre cuántas funciones y llamadas encontró cada herramienta. Los resultados fueron compilados y comparados para un análisis adicional.

Entradas de prueba

Agrupamos nuestras entradas de prueba en tres categorías:

  1. Ejemplos de un solo archivo: Estos son programas simples de JavaScript que contienen todo su código en un solo archivo. Son relativamente pequeños y fáciles de analizar.

  2. Ejemplos de Node.js de múltiples archivos: Estos son programas típicos de Node.js que usan múltiples archivos. A menudo involucran estructuras complejas y dependencias externas.

  3. Ejemplos generados: Para probar las herramientas con programas más grandes y complejos, generamos código JavaScript basado en patrones específicos. Esto nos permite realizar pruebas de estrés a las herramientas.

Análisis de rendimiento

Al analizar el rendimiento de las herramientas, consideramos dos factores principales: velocidad y consumo de memoria.

  1. Velocidad: Medimos cuánto tiempo tomó cada herramienta analizar los programas de entrada y producir un grafo de llamadas.

  2. Consumo de memoria: Observamos cuánta memoria utilizó cada herramienta durante el proceso de análisis.

Comparando estos factores, podemos determinar qué herramientas son más eficientes o capaces de manejar entradas más grandes.

Resultados de los programas de referencia

Calculemos diversas estadísticas de nuestras pruebas de los programas de referencia de SunSpider. Cada herramienta mostró diferentes resultados en cuanto al número de funciones y llamadas identificadas. En algunos casos, las herramientas produjeron resultados similares, especialmente para programas más pequeños donde había menos funciones.

Sin embargo, para programas más grandes o complejos, los resultados variaron significativamente entre las herramientas, ilustrando que cada herramienta tiene sus fortalezas y debilidades. Algunas herramientas eran mejores para identificar ciertos tipos de llamadas, mientras que otras las pasaron por alto por completo.

Análisis de módulos de Node.js

Cuando analizamos los módulos de Node.js, descubrimos que no todas las herramientas eran capaces de analizarlos completamente. Algunas herramientas lucharon con la estructura de múltiples archivos y no pudieron resolver llamadas entre diferentes archivos. Solo dos herramientas, Closure Compiler y ACG, pudieron analizar efectivamente estas entradas más complejas.

Recopilamos estadísticas sobre las funciones y llamadas encontradas por ambas herramientas en los módulos de Node.js. La superposición de llamadas encontradas por ambas herramientas fue sustancial, mostrando que podían identificar correctamente muchas de las mismas conexiones, pero todavía existían diferencias.

Análisis cualitativo

Además de medir el rendimiento, también realizamos un análisis cualitativo. Esto implicó examinar las llamadas identificadas por las herramientas y determinar cuáles eran verdaderos positivos basándonos en nuestras evaluaciones manuales.

A través de este análisis, pudimos ver cuántas de las llamadas identificadas eran precisas y cómo se comparaban las herramientas en términos de precisión y exhaustividad. La precisión se refiere a la proporción de llamadas verdaderas positivas entre todas las llamadas identificadas, mientras que la exhaustividad indica cuántas llamadas verdaderas positivas fueron realmente encontradas por la herramienta.

Observaciones y comparación de herramientas

Cada herramienta tenía sus ventajas y desventajas:

  • Closure Compiler: Esta herramienta mostró un buen rendimiento en la identificación de llamadas recursivas y tenía un equilibrio decente entre velocidad y uso de memoria. Sin embargo, su precisión se vio afectada por su dependencia en el simple emparejamiento de nombres.

  • ACG: Esta herramienta tuvo una excelente precisión y pudo rastrear flujos de control complejos de manera efectiva. Sin embargo, pasó por alto algunas llamadas de funciones de orden superior, que son comunes en JavaScript.

  • WALA: WALA pudo identificar llamadas a funciones más complejas, pero sufrió de una menor exhaustividad y mayor uso de memoria en comparación con otras herramientas.

  • grafo de llamadas de npm: Esta herramienta tuvo una alta precisión, pero no identificó ninguna llamada única que fuera verdadera.

  • TAJS: Aunque TAJS produjo resultados con una precisión casi perfecta, tuvo una baja exhaustividad.

Rendimiento combinado de las herramientas

Al combinar las fortalezas de diferentes herramientas, encontramos que usar múltiples herramientas juntas a menudo conducía a mejores resultados. Por ejemplo, ACG y TAJS se complementaron bien, proporcionando un equilibrio casi perfecto de precisión y exhaustividad cuando se combinaron.

Esto sugiere que un enfoque ideal para el análisis estático podría ser desarrollar algoritmos que integren las mejores características de las herramientas existentes.

Discusión sobre los hallazgos

Los hallazgos de nuestra investigación indican que ninguna herramienta es superior en todas las situaciones. La naturaleza dinámica de JavaScript significa que ciertos tipos de llamadas a funciones son inherentemente más difíciles de rastrear. Diferentes herramientas se enfocan en diferentes aspectos del código, lo que lleva a variaciones en sus salidas.

Las futuras mejoras en el análisis estático pueden beneficiarse de aprovechar las fortalezas de múltiples herramientas, con el objetivo de crear un marco de análisis más completo que pueda manejar las complejidades del código de JavaScript de manera más efectiva.

Conclusión

En resumen, el análisis estático de JavaScript es crucial en el proceso de desarrollo, dado su uso creciente en diversas aplicaciones. Las cinco herramientas que examinamos ofrecen capacidades únicas cuando se trata de construir grafos de llamadas. Al entender sus fortalezas y debilidades, los desarrolladores pueden elegir la herramienta adecuada para sus necesidades específicas y mejorar la calidad general de su código JavaScript.

A medida que la tecnología sigue evolucionando, es esencial seguir mejorando estas herramientas y desarrollar mejores métodos para analizar la naturaleza dinámica y compleja de los programas en JavaScript. Los conocimientos obtenidos de este estudio pueden guiar futuros esfuerzos de investigación y desarrollo en el análisis estático de código.

Fuente original

Título: Static JavaScript Call Graphs: A Comparative Study

Resumen: The popularity and wide adoption of JavaScript both at the client and server side makes its code analysis more important than ever before. Most of the algorithms for vulnerability analysis, coding issue detection, or type inference rely on the call graph representation of the underlying program. Despite some obvious advantages of dynamic analysis, static algorithms should also be considered for call graph construction as they do not require extensive test beds for programs and their costly execution and tracing. In this paper, we systematically compare five widely adopted static algorithms - implemented by the npm call graph, IBM WALA, Google Closure Compiler, Approximate Call Graph, and Type Analyzer for JavaScript tools - for building JavaScript call graphs on 26 WebKit SunSpider benchmark programs and 6 real-world Node.js modules. We provide a performance analysis as well as a quantitative and qualitative evaluation of the results. We found that there was a relatively large intersection of the found call edges among the algorithms, which proved to be 100 precise. However, most of the tools found edges that were missed by all others. ACG had the highest precision followed immediately by TAJS, but ACG found significantly more call edges. As for the combination of tools, ACG and TAJS together covered 99% of the found true edges by all algorithms, while maintaining a precision as high as 98%. Only two of the tools were able to analyze up-to-date multi-file Node.js modules due to incomplete language features support. They agreed on almost 60% of the call edges, but each of them found valid edges that the other missed.

Autores: Gábor Antal, Péter Hegedűs, Zoltán Tóth, Rudolf Ferenc, Tibor Gyimóthy

Última actualización: 2024-05-12 00:00:00

Idioma: English

Fuente URL: https://arxiv.org/abs/2405.07206

Fuente PDF: https://arxiv.org/pdf/2405.07206

Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/

Cambios: Este resumen se ha elaborado con la ayuda de AI y puede contener imprecisiones. Para obtener información precisa, consulte los documentos originales enlazados aquí.

Gracias a arxiv por el uso de su interoperabilidad de acceso abierto.

Más de autores

Artículos similares