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

investigate avoiding to copy binary data when marshaling byte[] to Buffer #34

Open
tjanczuk opened this issue Mar 30, 2013 · 4 comments

Comments

@tjanczuk
Copy link
Owner

See #4 (comment)

@tjanczuk
Copy link
Owner Author

This looks interesting: http://msdn.microsoft.com/en-us/magazine/cc163910.aspx#S2

Can the CLR buffer be pinned for the lifetime of the node.js Buffer instance created around it? That is, can the CLR buffer only be unpinned when the node.js Buffer is garbage collected? Does the JS Buffer assume it owns the memory? Can CLR byte[] be garbage collected while the underlying memory is pinned? To be or not to be?

@ghost
Copy link

ghost commented Aug 23, 2014

I'd look at it the other way around. Allocate a chunk of native memory and provide it to the CLR as the pointer to the managed byte array. You can then also share the same native memory with a nodeJs Buffer instance.

Regarding GC and pinning, the entire idea behind pinning is that the GC no longer touches that memory. There is a design reason behind why the fixed statement is infact a control flow statement and not just a keyword, it guarantees that the code will ALWAYS leave the block and that the memory will ALWAYS be unpinned and that the GC will be able to touch it again. Whilst the managed reference is "pinned" the GC won't touch that memory, it won't reallocate it, it won't deallocate it, it won't move it. It acts as if it is a pointer to native memory (which it really is in fact). I don't think it would be wise to maintain a pinned pointer (if its even possible) due to the fact that they went to great lengths to make sure pinned references were always used inside a scope that would always be "left".

I would be looking at the internal code behind GCHandle.Alloc as it provides almost exactly what you want to do.

See ves_icall_System_GCHandle_GetTargetHandle and mono_gchandle_new

@ghost
Copy link

ghost commented Aug 23, 2014

A few more interesting things: pin_ptr<>.
pin_ptr will allow you to pass a native pointer into a CLR environment without the CLR GC messing with the pointer. This is what you want I think. So long as the pin_ptr is in scope in the CLR context, then it will still remain "pinned" as far as the GC is concerned

Example from Mono:

#include <vcclr.h>

using namespace System;
using namespace System::Runtime::InteropServices;

void WriteStringManaged (const wchar_t* str)
{
    Console::WriteLine (Marshal::PtrToStringUni ((IntPtr) (void*) str));
}

int main (array<System::String^> ^args)
{
    Console::WriteLine (L"Pure MSVCRT console application");
    pin_ptr<const wchar_t> str = PtrToStringChars (L"WriteStringManaged");
    WriteStringManaged (str);
    return 0;
}

@TDiazT
Copy link

TDiazT commented Oct 30, 2017

Is there any information on this? I'm having some memory leak issues due to byte[] being copied when passing it back. For now I'm directly calling the GC to cleanup but I was wondering if there's any good solution for this.

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