Track external memory usage for matrices #602
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Adds tracking of the memory used by matrices to Node's external memory count, allowing the Javascript garbage collector to make better decisions about when to run.
Without these changes, Node only knows about the memory usage of the Javascript objects, and not the associated C and C++ objects. In the case of Matrix, those associated objects are quite large. As a result, it was possible to quickly allocate a large amount of memory without triggering garbage collection, for example: by reading multiple frames from a camera. This is especially problematic on low-memory systems, such as a Raspberry Pi, where memory usage could quickly grow past the available memory, triggering out-of-memory crashes.
To resolve this, this PR adds external memory adjustment calls to the Matrix wrapper class, and every location where the size of the referenced OpenCV matrix is altered, so that Node has a reasonable estimate of the memory usage of the Matrix objects. This causes garbage collection to run more often when needed, and prevents memory growth far outside of the bounds that Node is configured to run in.
It is still possible to use
Matrix.release()
to manually free memory, as this call has also been instrumented to adjust the external memory usage correctly.Note that it is now important that every place that can change the size of the OpenCV Mat object referenced from a Matrix correctly adjusts the external memory usage (using
Nan::AdjustExternalMemory()
). If this is not done correctly, Node's external memory count could get out of sync with the library's actual memory usage, which could cause the garbage collector to run too often or not often enough.I have attempted to find all the locations where these memory sizes could change, and have updated them in the least invasive way that I could. There might be better ways to restructure the code (for example, by strengthening the encapsulation of the referenced
Mat
within theMatrix
wrapper class) to make some of this cleaner and safer, but that could be significantly more work and would probably change some of the usage patterns for theMatrix
class.In most cases, I was able to replace the code that creates a Javascript wrapped Matrix with a call to a helper method that does the same thing and correctly tracks the external memory size of the new object. A new destructor was also added to correctly reduce the tracked external memory size when the Matrix object is released.
I believe that this PR fixes #601, #411, #209, #167, and #101.