Browser hacking: Let's hack on the JIT until ai-astar.js SINGS

Andreas Kling
12 Nov 202348:48

TLDRIn this video, the presenter focuses on optimizing the JavaScript Just-In-Time (JIT) compiler to improve performance on the Kraken AI A* test from the Kraken Benchmark suite. They demonstrate a significant speedup by implementing fast paths for equality checks between objects and handling the 'length' property of arrays more efficiently. The presenter profiles the code, identifies bottlenecks, and discusses the importance of caching and avoiding unnecessary calls to C++. The result is an impressive reduction in execution time from 2.15 seconds to 870 milliseconds, showcasing the potential for further optimization in JIT compilation.

Takeaways

  • 😀 The video focuses on optimizing the JavaScript Just-In-Time (JIT) compiler to improve performance in the Kraken AI A* test.
  • 🔍 The initial test without JIT took around 7.3 seconds, while with JIT enabled, it reduced to approximately 2.3 seconds, showcasing significant progress.
  • 🚀 The goal is to further optimize the JIT to make the test run as fast as possible, aiming for all execution to occur in jitted code for optimal speed.
  • 🔧 Profiling revealed that a considerable amount of time was spent in C++ helpers, particularly in the 'Loosely equals' function, indicating a need for optimization.
  • 🛠️ The 'Loosely equals' operator was identified as a bottleneck and a candidate for a fast path in the JIT, as it's a common operation in JavaScript.
  • 🔄 After implementing a fast path for object equality checks, the test time improved from 2.35 seconds to 2.15 seconds, a 10% improvement.
  • 📈 Further profiling showed that 'get by ID' and property access on arrays were still heavy, suggesting more areas for optimization.
  • 💡 A fast path for 'array.length' was implemented, recognizing that it's a common and magical property in JavaScript that reflects the number of elements.
  • ⏱️ The addition of the 'array.length' fast path resulted in a massive speed up, reducing the test time from 2.15 seconds to 870 milliseconds.
  • 📊 The final profile showed 85.7% of the runtime spent in generated JIT code, with less than 15% in C++, indicating a successful optimization.
  • 🌟 The presenter expressed satisfaction with the progress but acknowledged that there's still room for improvement and other tests to optimize in the future.

Q & A

  • What is the main focus of the video?

    -The main focus of the video is optimizing the JavaScript Just-In-Time (JIT) compiler to improve performance, specifically targeting the Kraken AI A* test.

  • What benchmark test is being used in the video?

    -The benchmark test being used is the Kraken AI A* test from the Kraken Benchmark.

  • How much time did the test take without enabling the JIT?

    -Without enabling the JIT, the test took approximately 7.3 seconds.

  • How much time did the test take with the JIT enabled?

    -With the JIT enabled, the test time reduced to approximately 2.3 seconds.

  • What is one of the major performance bottlenecks identified in the JIT machine code?

    -One major performance bottleneck identified is the heavy use of the 'Loosely equals' operator, which is the '==' operator in JavaScript.

  • What approach is suggested to optimize the 'Loosely equals' operator?

    -The suggested approach is to create a fast path for equality checking in the JIT for common cases, especially for object comparisons.

  • What is the expected outcome after implementing the fast path for 'Loosely equals'?

    -The expected outcome is a performance improvement, reducing the test time by about 10%.

  • What additional fast path is implemented to further optimize performance?

    -An additional fast path is implemented for the 'length' property of arrays, which is a common operation in JavaScript.

  • What is the performance improvement achieved after implementing both fast paths?

    -After implementing both fast paths, the test time reduced to approximately 870 milliseconds, a significant improvement from the initial 7.3 seconds.

  • What future optimizations are suggested in the video?

    -Future optimizations include implementing fast paths for other equality-related operators and handling property additions more efficiently during setup code.

Outlines

00:00

🚀 JavaScript JIT Optimization

The script discusses enhancing the JavaScript Just-In-Time (JIT) compiler performance by revisiting the Kraken AIA* test from the Kraken Benchmark suite. The presenter demonstrates the current performance of the Bode interpreter without JIT, which takes around 7.3 seconds, and then shows a significant speed-up with JIT enabled, reducing the time to approximately 2.3 seconds. The goal is to profile the test, identify bottlenecks, and optimize the JIT to further improve performance. The A* pathfinding algorithm's grid setup and search process are highlighted, and the presenter expresses intent to explore fast paths in the JIT to optimize the test.

05:01

🔍 Profiling and Identifying Bottlenecks

In this paragraph, the focus is on profiling the JavaScript code to find performance bottlenecks. The presenter uses Callgrind to identify that about 30% of the runtime is already in JIT machine code, but there are still calls to C++ for certain operations, such as 'Loosely equals'. It's revealed that 'Loosely equals' is essentially delegating to 'strictly equals', and the presenter considers creating a fast path for equality checks, which are common in JavaScript, to improve performance.

10:05

🛠️ Implementing Fast Paths for Equality Checks

The presenter decides to implement a fast path for the 'Loosely equals' operation, which is a significant performance bottleneck. They modify the JIT to handle equality checks between objects more efficiently by doing an identity comparison when both sides are objects. After implementing this change, a performance improvement is observed, reducing the test time from 2.35 seconds to 2.15 seconds, which is a 10% improvement.

15:08

🔧 Further Optimizations and Testing

The script continues with further optimization efforts. The presenter identifies that 'get by ID' and property access on arrays are still causing performance issues. They discuss the implementation of a fast path for array access and the caching mechanism for 'get by ID'. After making these changes, they verify that the optimizations have not broken any functionality and observe a significant reduction in test time, from 2.15 seconds to 870 milliseconds.

20:09

🌐 Special Handling for Array Length

The focus shifts to optimizing access to the 'length' property of arrays, which is a common operation in JavaScript. The presenter identifies that the current implementation of getting the 'length' property is not using the fast path due to special handling in the code. They propose adding a flag to objects to indicate the presence of a 'magical length property' and modifying the JIT to check for this flag, allowing for a faster path when accessing the 'length' property of arrays.

25:10

🎯 Committing Changes and Further Profiling

After implementing the fast path for array length, the presenter commits the changes and profiles the test again. They observe a massive speed-up, reducing the test time from 2.15 seconds to 870 milliseconds. The profile shows that 85.7% of the time is spent in the generated JIT code, indicating a significant improvement. However, there are still some operations in C++ that could be optimized, such as call frame setups and property setting.

30:12

🔄 Addressing Parser Performance and Future Optimizations

The presenter notes that parser performance is now visible in the profile, suggesting that there is room for optimization in the parsing process. They also discuss the possibility of optimizing the 'splice' method and combining 'has property' checks with 'get' operations. However, they decide not to make changes at this time and consider these potential optimizations for the future.

35:13

🏁 Wrapping Up and Future Outlook

In the final paragraph, the presenter expresses satisfaction with the progress made in optimizing the JIT compiler. They highlight the simplicity and effectiveness of the changes made and suggest that there is still much work to be done, with many other tests and benchmarks to optimize. They also encourage ongoing contributions to the JIT compiler project and look forward to further improvements.

Mindmap

Keywords

💡JavaScript JIT

JavaScript JIT, or Just-In-Time compilation, is a technique used to improve the performance of JavaScript code by compiling it into machine code at runtime. In the video, the presenter is working on enhancing the JIT for faster execution, particularly on the Kraken AIA STAR test, showcasing the significant speed improvements achieved by enabling JIT.

💡Kraken Benchmark

The Kraken Benchmark is a JavaScript performance test suite that measures the speed of various operations, including AIA* pathfinding algorithms. In the script, the presenter references the Kraken AIA STAR test as a benchmark to evaluate the effectiveness of JIT improvements.

💡AIA STAR test

The AIA STAR test is a specific test within the Kraken Benchmark that involves implementing the A* pathfinding algorithm on a grid. The video discusses optimizing the JIT to improve the performance of this test, aiming to reduce its execution time.

💡Bode Interpreter

The Bode Interpreter is a JavaScript interpreter that the video compares with the JIT compiler in terms of performance. The script mentions that without JIT, the Bode Interpreter takes longer to run the AIA STAR test, highlighting the importance of JIT for performance gains.

💡Profiling

Profiling is the process of measuring the performance of a program to identify bottlenecks. In the video, the presenter uses profiling to analyze the performance of the JIT and to find areas for optimization, such as reducing calls to C++ helpers within the JITted code.

💡Loosely Equals

Loosely Equals refers to the '==' operator in JavaScript, which performs type coercion when comparing values. The script discusses the performance impact of using Loosely Equals and the optimization of creating a fast path for equality checks in the JIT.

💡C++ Helpers

C++ Helpers are functions written in C++ that are called from JITted JavaScript code. The video script mentions identifying and reducing calls to these helpers, such as 'Loosely Equals' and 'get by ID', to improve the overall performance of the JIT.

💡Fast Path

A fast path in the context of JIT compilation is a code path that handles common cases more efficiently. The video describes creating a fast path for object identity comparison in 'Loosely Equals' and for 'array.length' to speed up the execution of the AIA STAR test.

💡Array Property Access

Array property access refers to reading or writing to elements within an array. The script identifies that a significant amount of time is spent on array property access and suggests that optimizing this, such as by caching, could further improve JIT performance.

💡Internal Get Own Property

Internal Get Own Property is a mechanism used to retrieve properties from an object, specifically its own properties. The video discusses issues with caching this operation and优化 the JIT to handle 'array.length' more efficiently.

💡Optimizing Compiler

An optimizing compiler is a type of compiler that improves the performance of code by applying various optimization techniques. The video contrasts the presenter's work on the JIT with established optimizing compilers like JavaScript Core, highlighting the progress made and the potential for further optimization.

Highlights

The video focuses on optimizing JavaScript JIT (Just-In-Time) compilation for the Kraken AIA* test.

The Bode interpreter's performance without JIT is compared to the significantly faster JIT-enabled execution.

JIT has made substantial progress, but there is still room for performance improvement.

Profiling is used to identify bottlenecks in the JIT compilation process.

The A* pathfinding algorithm is the core of the Kraken AIA* test, simulating grid-based searches.

The video discusses the importance of optimizing the 'loose equals' operation in JavaScript.

A fast path for equality checking is proposed to improve the performance of common JavaScript operations.

Debug output is enhanced to better understand the comparison operations in the test.

The video demonstrates a 10% performance improvement after implementing a fast path for object identity comparison.

Further profiling reveals issues with array property access and the need for optimization.

The special handling of 'array.length' is identified as a potential caching problem.

A fast path for 'array.length' is implemented to avoid unnecessary property lookups.

The video shows a massive speedup after the 'array.length' optimization, reducing test time from 2.15s to 0.87s.

The new profile shows 85.7% of self time in generated JIT code, indicating a successful optimization.

Remaining performance issues include calls to C++ for certain operations, such as 'put by ID'.

The video concludes by acknowledging the need for further optimizations in other areas of the JIT compiler.

The presenter expresses satisfaction with the progress made and enthusiasm for continuing work on the JIT compiler.