Skip to content

Performance

Momtchil Momtchev edited this page Nov 21, 2022 · 1 revision
  • Generally when using Python, you will get the usual Python performance, while when using Node.js, you will get the usual Node.js performance
  • Performance is significantly better with Python 3.9 or later because of the fast call protocol
  • Calling into Python from JS is more expensive than Python to Python, tests show that using Node.js with Python 3.9+ for numpy arrays:
    • of 8 elements is 4 times slower using raw access and 10 times slower using proxify
    • of 512 elements is 3 times slower using raw access and 4 times slower using proxify
    • of 8192 elements, there is no significant difference with raw access and proxify is 25% slower
    • of 32768 elements, there is no significant difference whatever the access method is
  • It is possible to mix raw access and proxify - the underlying PyObject can be accessed as the __PyObject__ from a proxy object
  • toJS() and fromJS() are the most expensive parts as they copy objects between the Python and the JavaScript heap
    • For best performance try to keep objects in Python and in JavaScript as much as possible and avoid moving them
  • The memory usage of your program will be the sum of the memory usage of a Python interpreter (not that much) and a Node.js interpreter (more significant)
  • All Python objects referenced in JavaScript have an additional 56-byte header that is a V8 object - in fact most of the performance loss when processing very small Python objects is related to the creation and the handling of this additional V8 object - that is the V8 tip of the Python iceberg
    • This means that when Python code creates a list, this list stays in the Python heap
    • When this list is seen for the first time by V8, it receives its 56-byte header
    • If the JavaScript code traverses the list accessing every element, then every element receives a 56-byte header - but these are available from immediate garbage collection
    • If every element is separately pushed into a JavaScript array as a PyObject, then all 56-byte headers must be kept
  • The two GCs should work very well in tandem