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

Node v0.10 support and API remarks #2

Open
JohannesRudolph opened this issue Nov 15, 2014 · 3 comments
Open

Node v0.10 support and API remarks #2

JohannesRudolph opened this issue Nov 15, 2014 · 3 comments

Comments

@JohannesRudolph
Copy link

Hi Trevor,

I found this project while researching gc issues in our current project that uses lot's of buffer objects. At some point, all the garbage collections we see using --trace_gc are full mark&sweeps due to reaching v8's "external memory allocation limit".

The buffer-dispose you have here seems like a viable solution. Though I wonder whether v0.10 is affected by this just as much as v0.11?

Personally, I would vouch for something like this to make it into node core at some point. Any GC system has to make a tradeof at some point between consistency and performance. In this case, calling free on a buffer remains entirely optional and an optimization.

e.g. .NET gives you the IDisposable pattern to early-release native resources that would else require expensive finalization during garbage collection. This is a similar scenario. Nothing bad happens if you don't free a buffer but if you want more performance you can dispose it. In any case, a disposed buffer should throw exceptions anytime it's beeing accessed (in .NET disposed objects throw ObjectDisposedException), and you need to be careful about disposing elements at the right time (e.g. when working with async callbacks like in node). With a node.js buffer, the native resource is the external memory held.

So, from my point of view, this is nothing out of the ordinary and "dangerous" stuff, it's one of the core things a GC'd platform needs to provide to its developers to allow writing performant code. At it's current state, the buffer handling and gc characteristics make node.js unusable for us (long gc pauses, soft realtime requirements, loads of buffer handling and weak/embedded hardware)

Regards,
Johannes

@trevnorris
Copy link
Owner

@JohannesRudolph The problem is we aren't in control of the GC. Only the API exposed by V8. Apropos, V8 has a native ArrayBuffer::Neuter() that allows zero-ing out any TypedArray that's pointing to that given ArrayBuffer instance. They can do that because they implemented it at the GC level.

Generally speaking, Node tries to not allow developers to shoot themselves at this level. i.e. do something in JS that causes a corrupt memory error. We try to constrain the problem area to things that can be thrown as an exception, caught, etc.

Thanks for your words. There's even more that could be done (e.g. not tell V8 about the amount of memory you have externally allocated, go GC doesn't spin up w/ a lot of Buffers. though it requires you to manage how much external memory you have allocated yourself), but generally speaking very few people would use this type of functionality so I haven't put the effort into making them.

@JohannesRudolph
Copy link
Author

@trevnorris thanks for your reply. I think it's sensible to tell the v8 GC about externally allocated memory as we ne need to ensure the whole node process is well behaved wrt memory usage.

Using TypedArrays is out of the question for my scenario unfortunately because I am consuming an infinite stream via fs. I could probably get rid of buffer allocs with some effort (e.g. using fs.read instead of fs.createReadStream and some other Apis.

With regards to not allowing developers to shoot themselves in the foot. I agree that you should never be able to create a corrupt memory error using a JS Api. Hence, the JS Buffer object would need to guard and throw something akin to ObjectDisposedException on all its methods once it has been disposed. Would that be possible?

Also, could you elaborate on the portability of buffer-dispose to v0.10 as I had originally asked?

@JohannesRudolph
Copy link
Author

Addendum: The fs API supports a close method as well which allows us to free the underlying native resource (file handle) early from JS. I'd argue we need a similar API for buffers, where the native resource is a chunk of unmanaged memory. In the stream case it would be unacceptable to leave file handles open until the GC decides to collect the object, why would it be different for a buffer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants