stdlib-js / google-summer-of-code

Google Summer of Code resources.
https://github.com/stdlib-js/stdlib
23 stars 5 forks source link

[RFC]:Adding Support for Visualizing Benchmark Results #40

Closed Jai0401 closed 2 months ago

Jai0401 commented 3 months ago

Full name

Jaimin Godhani

University status

Yes

University name

Rajiv Gandhi Institute of Petroleum Technology

University program

Bachelor of Technology in Computer Science

Expected graduation

2025

Short biography

I am a 3rd year B.Tech. Student in the department of Computer Science and Technology at Rajiv Gandhi Institute of Petroleum Technology. I've successfully finished several pertinent courses including Compiler Design, Computer Organization and Architecture, Theory of Computation, Operating Systems, Software Engineering, Object-Oriented Analysis, Data Structures and Algorithms, Design and Analysis of Algorithms, machine learning and Computer Networks.

Timezone

IST (UTC + 5:30)

Contact details

21cs3025@rgipt.ac.in, jaimingodhani@gmail.com

Platform

Mac

Editor

I prefer Visual Studio Code (VSCode) for its user-friendly interface, customizable extensions, built-in terminal, and robust debugging capabilities and I also frequently work with Jupyter Notebook for data analysis and interactive computing tasks.

Programming experience

I possess a strong background in a variety of programming languages including JavaScript, TypeScript, HTML/CSS, C++, C, and Python. Throughout my academic and professional journey, I have explored a diverse range of technologies and frameworks such as ReactJS, Recoil, Next.js, Node.js, Express.js, MongoDB, TailwindCSS, Material UI, PostgreSQL, OpenCV, NumPy, Pandas, TensorFlow, Matplotlib (Pyplot), and Sci-kit Learn.

Below are some of the personal projects I have worked on:

JavaScript experience

I possess a robust proficiency in JavaScript, having leveraged its capabilities extensively across various projects. My favorite attribute of JavaScript lies in its adaptability and versatility, enabling me to undertake both front-end and back-end development using frameworks such as React and Node.js. However, I must note that its loosely typed nature stands as a challenge, necessitating careful handling to avoid unforeseen behaviors. JavaScript has seen notable advancements with ES6 and beyond, introducing features like arrow functions, template literals, and enhanced object literals, improving code expressiveness and readability. The adoption of TypeScript has also been beneficial, offering static typing, enhanced code organization, and improved IDE support for more robust and maintainable codebases. Tools like JSDocs have further enhanced code documentation, providing detailed comments and type annotations within the code for better understanding and maintenance.

Node.js experience

I have substantial experience working with Node.js, primarily in developing backend services and web applications. I've utilized Node.js for building RESTful APIs, handling database operations, managing server-side logic, and integrating with various third-party services. Additionally, I've used Node.js frameworks like Express.js for creating scalable and efficient server applications. My experience with Node.js also includes setting up and managing server environments, implementing authentication and authorization mechanisms, and optimizing performance for high-traffic applications.

C/Fortran experience

My experience with C began during my early days in computer science, as it was part of my curriculum. I extensively used C for data structures and algorithms (DSA) and competitive programming tasks. Over time, I developed a strong foundation in C programming, honing my skills through various projects and coding challenges. While Fortran wasn't my primary language, I gained experience in Fortran, particularly in scientific computing and numerical analysis courses, alongside Matlab. I used Fortran for tasks such as solving differential equations, performing matrix computations, and simulating physical systems.

Interest in stdlib

I find stdlib pretty fascinating because it's like a treasure trove for developers, offering a vast collection of tools and functions that make coding life much easier. Imagine having a reliable buddy who knows all the math tricks and can effortlessly handle complex calculations for you! Whether it's computing special functions, dealing with numbers in various ways, or diving deep into statistical analysis, stdlib has got your back. It's like having a super-smart sidekick in your programming adventures, always ready to lend a hand and make your code shine brighter.

Version control

Yes, I am using Git/Github.

Contributions to stdlib

Merged Requests: https://github.com/stdlib-js/stdlib/pulls?q=is%3Amerged+is%3Apr+author%3Ajai0401+ Open PRs: https://github.com/stdlib-js/stdlib/pulls/jai0401 Issues: https://github.com/stdlib-js/stdlib/issues?q=is%3Aissue+author%3Ajai0401+

Goals

Abstract

This project proposal aims to enhance the functionality of benchmark visualization within an existing software platform by implementing a Test Anything Protocol (TAP) parser and developing a user-friendly plot frontend. The project focuses on enabling developers to run benchmarks and easily visualize and compare the benchmark results. The TAP parser will support the latest TAP specification, ensuring compatibility with different benchmark outputs and providing robust error handling. The plot frontend will consume parsed TAP results and generate interactive visualizations, including small multiple/facet layouts for comparing performance across different configurations. Seamless integration of the TAP parser and plot frontend into the software platform will be achieved, along with comprehensive documentation and user guides for utilizing the new visualization capabilities.

Objectives

  1. Implement a TAP parser that supports the latest TAP specification:

    • Description: Develop a TAP (Test Anything Protocol) parser that accurately processes benchmark results based on the latest TAP specification. This parser will handle various data formats and ensure compatibility with different benchmark outputs. Additionally, incorporate a custom parser to extract benchmark description data, including facets, from TAP results for parameterized comparison.

    • Specifics:

      • Language: We’ll use JavaScript for this implementation.
      • Package Location: The TAP parser will reside in the @stdlib/utils/* package.
      • Error Handling: Robust error handling will be essential to gracefully handle various TAP data formats.
      • TAP Version Support: The parser will adhere to TAP version 13 or later.
      • Unit Tests: We’ll implement unit tests to validate the parser’s functionality.
      • Expected Output Format: The TAP parser will produce JSON data as its output format, containing structured information extracted from the TAP benchmark results.

      Extension: Develop a custom parser within the TAP parser to extract benchmark description data into a structured format. This data, present in the TAP results, includes information about facets, parameters, and values used in benchmarking. The custom parser will ensure that this description data can be organized and utilized for parameterized comparison and visualization.

      Let's consider a scenario where your benchmarking system produces TAP results like the following:

      TAP version 13
      # Math.hypot
      ---
      iterations: 1000000
      elapsed: 0.457849215
      rate: 2184125.181911691
      ...
      ok 1 benchmark finished
      # Math.hypot
      ---
      iterations: 1000000
      elapsed: 0.454676639
      rate: 2199365.250432407
      ...
      ok 2 benchmark finished
      # Math.hypot
      ---
      iterations: 1000000
      elapsed: 0.472378014
      rate: 2116948.652059831
      ...
      ok 3 benchmark finished
      # hypot
      ---
      iterations: 1000000
      elapsed: 0.13120811
      rate: 7621480.105155086
      ...
      ok 4 benchmark finished
      # hypot
      ---
      iterations: 1000000
      elapsed: 0.129308984
      rate: 7733414.717727579
      ...
      ok 5 benchmark finished
      # hypot
      ---
      iterations: 1000000
      elapsed: 0.12404053
      rate: 8061881.064197323
      ...
      ok 6 benchmark finished
      #
      1..6
      # total 6
      # pass  6
      #
      # ok

      In this example, each section represents a benchmark result, including information such as the benchmarked method (Math.hypot, hypot), iterations, elapsed time, and rate.

      Parsing Function: Create a parsing function within the TAP parser that specifically targets benchmark description data. This function should identify lines containing benchmark results and extract the relevant information.

      function parseBenchmarkDescription(section) {
        const benchmarkDescriptionRegex = /# ([\w.]+)(::(\w+(?:,\w+)*))?(:(\w+))?((?::\w+=\w+(?:,\w+=\w+)*))?/;
        const match = section.match(benchmarkDescriptionRegex);
      
        if (match) {
            const pkg = match[1];
            const scopes = match[3] ? match[3].split(',') : [];
            const method = match[5] || '';
            const params = {};
      
            if (match[6]) {
                const paramPairs = match[6].slice(1).split(',');
                paramPairs.forEach((pair) => {
                    const [key, value] = pair.split('=');
                    params[key] = value;
                });
            }
      
            const iterations = parseInt(section.match(/iterations: (\d+)/)[1]);
            const elapsed = parseFloat(section.match(/elapsed: (\d+\.\d+)/)[1]);
            const rate = parseFloat(section.match(/rate: (\d+\.\d+)/)[1]);
      
            return { pkg, scopes, method, params, iterations, elapsed, rate };
        }
      
        return null; // Not a benchmark section
      }

      Usage in TAP Parser: Integrate the parseBenchmarkDescription function into your TAP parser to process each line of TAP results and extract benchmark description data.

      function parseTapResults(results) {
        const parsedResults = [];
        let currentSection = '';
        for (const line of results) {
            if (line.startsWith('# ')) {
                if (currentSection !== '') {
                    const parsedSection = parseBenchmarkDescription(currentSection);
                    if (parsedSection) {
                        parsedResults.push(parsedSection);
                    }
                    currentSection = '';
                }
            }
            currentSection += line + '\n';
        }
        // Parse the last section
        const parsedSection = parseBenchmarkDescription(currentSection);
        if (parsedSection) {
            parsedResults.push(parsedSection);
        }
        return parsedResults;
      }

      Structured Output: When using the TAP parser, call the parseTapResults function to obtain structured data containing benchmark description information.

      const structuredResults = parseTapResults(tapResults);
      console.log(structuredResults);

      The output will be an array of objects, each representing a benchmark result with structured data:

      [
        {
            "pkg": "@stdlib/math",
            "scopes": [],
            "method": "Math.hypot",
            "params": {},
            "iterations": 1000000,
            "elapsed": 0.457849215,
            "rate": 2184125.181911691
        },
        {
            "pkg": "@stdlib/math",
            "scopes": [],
            "method": "Math.hypot",
            "params": {},
            "iterations": 1000000,
            "elapsed": 0.454676639,
            "rate": 2199365.250432407
        },
        {
            "pkg": "@stdlib/math",
            "scopes": [],
            "method": "Math.hypot",
            "params": {},
            "iterations": 1000000,
            "elapsed": 0.472378014,
            "rate": 2116948.652059831
        },
        {
            "pkg": "@stdlib/math",
            "scopes": [],
            "method": "hypot",
            "params": {},
            "iterations": 1000000,
            "elapsed": 0.13120811,
            "rate": 7621480.105155086
        },
        {
            "pkg": "@stdlib/math",
            "scopes": [],
            "method": "hypot",
            "params": {},
            "iterations": 1000000,
            "elapsed": 0.129308984,
            "rate": 7733414.717727579
        },
        {
            "pkg": "@stdlib/math",
            "scopes": [],
            "method": "hypot",
            "params": {},
            "iterations": 1000000,
            "elapsed": 0.12404053,
            "rate": 8061881.064197323
        }
      ]

      pkg: The package name (e.g., @stdlib/math). scopes: An optional list of scopes separated by commas (e.g., native,avx). method: The method name (e.g., hypot). params: An optional list of parameter-value pairs separated by commas (e.g., arrayLength=100,dtype=float64).

      This example demonstrates how you can extend your TAP parser to extract benchmark description data into a structured format, making it easier to organize and utilize for parameterized comparison and visualization in your benchmarking system.

  2. Develop ASCII Plotter for Benchmark Visualization:

    • Description: Develop an in-house ASCII plotter specifically tailored for visualizing benchmark results by processing parsed TAP data. This plotter will utilize ASCII characters to generate clear and informative textual visualizations, facilitating quick insights and comparisons from benchmark data. The goal is to create an intuitive tool that presents benchmarking information in a concise and user-friendly format, enhancing data interpretation and analysis capabilities (Related issue).

    • Specifics:

      • Language: We'll use JavaScript to develop the ASCII plotter within the stdlib-js project.
      • Package Location: The ASCII plotter will be part of the @stdlib/plot package.
      • Functionality: The ASCII plotter should support basic plot types such as line charts, bar charts, and histograms using ASCII characters.
      • Customization: Provide options for customizing plot appearance, including axes labels, styling, and data range adjustments.
      • Integration: Ensure seamless integration with the TAP parser and other benchmarking components to enable automatic visualization of benchmark

      Handling Facets in an ASCII Plotter for Benchmark Visualization: When visualizing benchmark results in an ASCII plotter and dealing with facets or creating small multiples, certain challenges arise. Here's a structured approach to address these challenges:

      1. Spatial Layout In the terminal environment, space is limited. To accommodate small multiples, divide the available terminal area into a grid of subplots, with each subplot representing a specific combination of facets. 2. Facet Identification Identify unique combinations of facets present in the benchmark data. Iterate through the parsed TAP data to extract distinct facet combinations. 3. Subplot Generation Generate a separate subplot for each unique facet combination within the terminal grid. Adjust the aspect ratio and scaling of subplots to fit the available space while remaining legible. 4. Subplot Labeling Include labels or legends within or around subplots to identify the facets represented by each subplot. Use ASCII characters or symbols for representation. 5. Data Filtering Filter benchmark data to include only data points corresponding to specific facet combinations represented by each subplot. 6. Rendering Utilize ASCII plotting functionality to render line charts, bar charts, or histograms within each subplot's allocated area. 7. Spacing and Alignment Introduce spacing between subplots and ensure proper alignment of axes and labels for readability and aesthetics.

      Considerations:

      • Limited Resolution: ASCII plotting has limited resolution, which may affect visual clarity with complex data or many facets.
      • Overcrowding: As the number of facets and combinations increases, overcrowding within the terminal grid may occur.
      • Alternative Visualizations: Consider exporting data to more sophisticated plotting libraries for detailed or image-based plots.
      • Interactive Functionality: Implement interactive features for users to cycle through facets or zoom in on specific subplots.

      Implementing small multiples in an ASCII plotter is feasible with careful planning and consideration of space constraints and visual clarity. However, assess trade-offs between visual complexity and terminal real estate, and explore alternative visualization methods when necessary.

      Examples: (ASCII art)

      Namespace: Math +-------------------+ | ██████████████ | | ██████▒▒▒▒▒▒▒▒ | +-------------------+

      Namespace: Array +-------------------+ | ▒▒▒▒▒▒▒▒▒▒▒▒▒▒ | | ██████████████ | +-------------------+

  3. Develop a plot frontend for Benchmark Visualization:

    • Description: Create a user-friendly plot frontend that consumes the parsed TAP results and generates visualizations based on the benchmark data. Users should be able to explore and compare benchmark results easily.This could live as a separate package on the stdlib-js GitHub organization.

    • Specifics:

      • Language: We’ll use JavaScript for the frontend.
      • Libraries: Consider using observable-plot or vega for visualization. This frontend will enhance the user experience by providing interactive visualizations within the software platform.
  4. Seamless Integration into the Software Platform

    • Description: Integrate the TAP parser and plot frontend within the stdlib-js project. Ensure smooth interaction between benchmarking, parsing, and visualization components. For the pipeline for running benchmarks and visualizing results, that would likely be stitched together via make recipes, which can be found in /tools/make from the root project directory.

    • Specifics:

      • Makefile Integration: Add build rules for compiling the TAP parser and plot frontend.
      • Dependency Management: Ensure that the TAP parser is a prerequisite for generating plots.
      • CLI or Browser Integration: Decide whether the visualization will be CLI-based or browser-based (as discussed earlier).

      Makefile Example:

      # Variables
      CXX = g++
      CXXFLAGS = -Wall -O2
      
      # Targets and Prerequisites
      all: benchmark_plot
      
      benchmark_plot: main.o tap_parser.o plot_frontend.o
       $(CXX) $(CXXFLAGS) $^ -o $@
      
      main.o: main.cpp
       $(CXX) $(CXXFLAGS) -c $< -o $@
      
      tap_parser.o: @stdlib/utils/tap-parser.cpp
       $(CXX) $(CXXFLAGS) -c $< -o $@
      
      plot_frontend.o: @stdlib/plot-frontend.cpp
       $(CXX) $(CXXFLAGS) -c $< -o $@
      
      clean:
       rm -f *.o benchmark_plot
  5. Provide documentation and user guides for utilizing the new visualization capabilities:

    • Description: Create comprehensive documentation and user guides that explain how to use the new visualization capabilities for benchmark results. The documentation should cover setup instructions, usage examples, and best practices.

    • Specifics:

      • Write clear and concise documentation using Markdown or HTML format.
      • Include step-by-step tutorials, code snippets, and screenshots to illustrate the process of running benchmarks, parsing TAP results, and visualizing data.
  6. Conduct thorough testing and debugging to ensure the reliability and accuracy of benchmark visualizations:

    • Description: Perform extensive testing and debugging to validate the functionality, reliability, and accuracy of the benchmark visualizations. Identify and fix any issues or inconsistencies in the parsed data or plotted results.

    • Specifics:

      • Implement unit tests, integration tests, and end-to-end tests for the TAP parser and plot frontend.
      • Use test frameworks like Jest, Mocha, or Selenium for automated testing.
      • Conduct manual testing to validate user interactions and edge cases.
  7. Collaborate with the community for feedback and improvements to enhance user experience:

    • Description: Engage with the community of developers and users to gather feedback, suggestions, and feature requests related to benchmark visualizations. Incorporate community input to improve the user experience and address usability issues.

    • Specifics:

      • Participate in community forums, discussion groups, and feedback sessions to collect input from stakeholders.
      • Prioritize and implement feature enhancements based on community feedback.

Stretch Goals for the Project

  1. Continuous Integration (CI) Integration:

    • Set up a CI pipeline using popular CI/CD services like GitHub Actions, Travis CI, or CircleCI to automate testing, linting, and deployment processes.
    • Integrate code coverage tools to ensure sufficient test coverage and maintain code quality standards.
  2. Benchmark Comparison and Analysis:

    • Develop functionality within the TAP parser to compare benchmark results across different runs or versions, highlighting performance improvements or regressions.
    • Implement statistical analysis tools to generate insights from benchmark data, such as mean, median, standard deviation, and confidence intervals.
  3. Interactive ASCII Plotter:

    • Enhance the ASCII plotter to support interactive features, allowing users to zoom in/out, pan across plots, and dynamically adjust plot settings.
    • Integrate keyboard shortcuts or command-line options for user interactions within the ASCII plotter.
  4. Export and Sharing Capabilities:

    • Add functionality to export benchmark results and plots in various formats, such as CSV, JSON, or image files (PNG, SVG), for external analysis or sharing.
    • Implement integration with cloud storage services or version control platforms for seamless data sharing and collaboration.
  5. User Interface Improvements:

    • Improve the user interface of both the TAP parser and ASCII plotter with clear and intuitive command-line interfaces (CLIs) or graphical user interfaces (GUIs).
    • Incorporate color-coding, styling, and customization options to enhance readability and aesthetics of benchmark reports and plots.

Project Risks

  1. Data Format Compatibility:

    • Ensuring the TAP parser can handle diverse benchmark output formats accurately.
  2. Scalability Challenges:

    • Addressing potential performance bottlenecks when processing large benchmark datasets.
  3. Complexity in Facets:

    • Managing complex facet structures and avoiding clutter in visualizations.
  4. User Interface Design:

    • Designing a user-friendly interface for both the parser and ASCII plotter.

Why this project?

The proposed project excites me due to its potential to significantly enhance the usability and functionality of our software. Having previously worked on frontend projects focusing on visualization, I have gained valuable experience in designing user-friendly and effective visual representations of data. This background equips me with the necessary skills to tackle the challenges of implementing benchmark visualization features effectively.

Additionally, my ongoing learning journey in compiler design as part of my curriculum has provided me with insights into optimizing code and understanding performance metrics. This knowledge will be invaluable in designing a robust and efficient benchmark visualization tool that can handle large datasets and provide meaningful insights to developers.

Qualifications

Frontend Development Expertise

Data Visualization Skills

Compiler Design Knowledge

Prior art

In researching this project, I explored various existing solutions and resources related to benchmark visualization and similar functionalities. Here are some notable findings:

Commitment

I plan to commit approximately 30 hours per week to this project. This commitment includes both the pre-GSoC preparation phase and the 12-week program duration. Furthermore, my academic schedule aligns well with the program timeline, as my classes conclude before the coding period begins and resume after the pencils down date, ensuring that I am completely available and focused on the project for the entire duration.

Schedule

Community Bonding Period

Activities:

Week 1-2: TAP Parser Implementation

Tasks:

Week 3-4: ASCII Plotter Development

Tasks:

Week 5-6: Basic Plot Frontend

Tasks:

Week 7-8: Midterm Review and Enhancements

Tasks:

Week 9-10: Advanced Frontend Functionality

Tasks:

Week 11-12: Documentation and Finalization

Tasks:

Final Week

Tasks:

Checklist

Pranavchiku commented 3 months ago

Hey @Jai0401 , I am jotting down the points that I feel can be added to your proposal

Looking forward to look at the updates.

Jai0401 commented 3 months ago

@Pranavchiku thanks for the review, I am working on suggestions.

kgryte commented 3 months ago

@Jai0401 Thanks for filing this draft proposal. A few comments:

  1. When writing benchmarks, we use a particular benchmark description convention (e.g., <pkg>[::<scope>[,<scope>[,...]][:<method>][:<param1>=<value1>,[<param2>=<value2[,...]]) for specifying "facets". The intent behind this convention is to allow parameterized comparison. For example, when benchmarking a particular method, take the results when measuring performance for different array lengths and combine into a single plot. Or allow comparing ::native vs non-native API benchmarks. One thing you'd like want to add to your proposal is a way to extract this description data into a structured format. It is present in the TAP results, but we'd need to add a custom parser.
  2. Given (1), how would you handle the handling of facets (e.g., through the use of small multiples)? How realistic would that be for ASCII plotting in the terminal?
  3. Suppose you run ahead of schedule, what are some stretch goals for this project? E.g., PR CI integration?
  4. What risks do you see in pursuing this project which might present obstacles to its success?
Jai0401 commented 3 months ago

@kgryte Thanks for the review, I've made the necessary changes to the proposal as discussed. Please review and let me know your thoughts.

kgryte commented 3 months ago

@Jai0401 Thanks for the updates and addressing the feedback.