Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: optimize Error object creation in promise.js functions #3169

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Sunghak
Copy link

@Sunghak Sunghak commented Oct 30, 2024

Summary

This merge request optimizes several functions in promise.js, including ping(), execute(), query(), and other similar methods, by moving the creation of Error objects inside their respective error handling blocks. This change ensures that Error objects are instantiated only when actual errors occur, reducing unnecessary overhead during successful operations.

Background and Motivation

  • Performance Issue:

    • Previously, Error objects were being created every time these functions were called, regardless of whether an error occurred.
    • In high-throughput applications where these functions are invoked frequently (e.g., 280,000 times), this leads to significant CPU and memory overhead.
  • Performance Analysis:

    • Used Clinic Flame Graph to analyze performance over 280,000 function calls.
    • Found that creating Error objects only when needed reduces CPU usage and execution time.
    • Observed improved performance and reduced CPU time when the Error object instantiation is deferred until an actual error occurs.

Changes Made

  • Modified Functions:

    • ping()
    • execute()
    • query()
    • Other functions in promise.js exhibiting the same pattern.
  • Optimization Details:

    • Moved the instantiation of Error objects inside the if (err) blocks within each function.

    • Ensured that Error objects are only created when an error is present.

    • Example change:

      // Before
      someFunction() {
        const c = this.connection;
        const localErr = new Error(); // Error created here regardless of error occurrence
        return new this.Promise((resolve, reject) => {
          c.someOperation((err, result) => {
            if (err) {
              localErr.message = err.message;
              // ... copy other properties
              reject(localErr);
            } else {
              resolve(result);
            }
          });
        });
      }
      
      // After
      someFunction() {
        const c = this.connection;
        return new this.Promise((resolve, reject) => {
          c.someOperation((err, result) => {
            if (err) {
              const localErr = new Error(); // Error created here only when an error occurs
              localErr.message = err.message;
              // ... copy other properties
              reject(localErr);
            } else {
              resolve(result);
            }
          });
        });
      }

Benefits

  • Performance Improvement:

    • Reduces CPU and memory usage by avoiding unnecessary creation of Error objects during successful operations.
    • Decreases pressure on the garbage collector, leading to smoother runtime performance.
  • Scalability:

    • Enhances the efficiency and scalability of applications that frequently use these functions.
    • Particularly beneficial in high-load scenarios where small optimizations have a significant impact.
  • Best Practices Compliance:

    • Aligns with modern JavaScript best practices by limiting variable scope and using lazy instantiation.
    • Improves code readability and maintainability by keeping variable declarations close to where they are used.

Testing

  • Performance Testing:
    • Conducted benchmarks to compare CPU usage before and after the changes.
    • Confirmed a measurable decrease in CPU time and improved performance in high-throughput tests.

Compatibility

  • Backward Compatibility:
    • Changes are fully backward-compatible with the existing API.
    • No alterations to function signatures or expected inputs/outputs.

Additional Notes

  • User Impact:
    • Users should experience improved performance without any changes required on their part.
    • The optimization is internal and does not affect how the library is used externally.

Conclusion

By optimizing the creation of Error objects in ping(), execute(), query(), and other functions within promise.js, this change enhances the performance and scalability of the mysql2 library. Avoiding unnecessary instantiation of Error objects reduces CPU and memory overhead, leading to more efficient resource utilization, especially in applications with high transaction volumes.

@wellwelwel wellwelwel changed the title Optimize Error Object Creation in promise.js Functions to Improve Performance perf: optimize Error object creation in promise.js functions Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants