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

Memory<byte> from Pointer ... for a possible MemoryMappedViewAccessor extension method #55881

Closed
hopperpl opened this issue Jul 18, 2021 · 8 comments

Comments

@hopperpl
Copy link

Is there a way to implement/generate a Memory<byte> from a pointer? Or is, by definition, Memory<byte> always GC managed memory?

I'm asking the question here, because here are the high-performance code experts.


Here is the scenario: I have a 128 GiB memory mapped file, which so far I expose with Span<byte> in ranges (as Span is limited to 2 GiB, but that is fine). I'm not using MemoryMappedViewAccessor, it's not a very useful class, I directly bind to windows API MapViewOfFile() and receive a pointer which I only expose as Span<byte> from a helper class, so this code is as safe and reliable as class MemoryMappedViewAccessor.

This gives a lot of performance advantages, especially as many net core functions accept Span<byte> as input parameter. But there are also some issues with it, as Task cannot uses Span<byte> due to stack location. So far, I use a helper class that transfers a Span by extracting the pointer, and then regenerating that Span inside the Task function. It's hacky, but it works great and the performance gain is extreme. And yes, the Span<byte> originator is pinned correctly as well if needed. And the lifetime of the memory object is ensured as well. None of that is an issue.

But I would prefer if I could use a Memory<byte> instead with valid memory ownership. But I'm not sure if that is even possible. And it would explain why MemoryMappedViewAccessor has no Memory<byte> accessor out of the box.

@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Memory untriaged New issue has not been triaged by the area owner labels Jul 18, 2021
@ghost
Copy link

ghost commented Jul 18, 2021

Tagging subscribers to this area: @GrabYourPitchforks, @dotnet/area-system-memory
See info in area-owners.md if you want to be subscribed.

Issue Details

Is there a way to implement/generate a Memory<byte> from a pointer? Or is, by definition, Memory<byte> always GC managed memory?

I'm asking the question here, because here are the high-performance code experts.


Here is the scenario: I have a 128 GiB memory mapped file, which so far I expose with Span<byte> in ranges (as Span is limited to 2 GiB, but that is fine). I'm not using MemoryMappedViewAccessor, it's not a very useful class, I directly bind to windows API MapViewOfFile() and receive a pointer which I only expose as Span<byte> from a helper class, so this code is as safe and reliable as class MemoryMappedViewAccessor.

This gives a lot of performance advantages, especially as many net core functions accept Span<byte> as input parameter. But there are also some issues with it, as Task cannot uses Span<byte> due to stack location. So far, I use a helper class that transfers a Span by extracting the pointer, and then regenerating that Span inside the Task function. It's hacky, but it works great and the performance gain is extreme. And yes, the Span<byte> originator is pinned correctly as well if needed. And the lifetime of the memory object is ensured as well. None of that is an issue.

But I would prefer if I could use a Memory<byte> instead with valid memory ownership. But I'm not sure if that is even possible. And it would explain why MemoryMappedViewAccessor has no Memory<byte> accessor out of the box.

Author: hopperpl
Assignees: -
Labels:

area-System.Memory, untriaged

Milestone: -

@huoyaoyuan
Copy link
Member

You can create your own MemoryManager<T> for wrapping native memory. However, there is still int32 limitation of it.

@hopperpl
Copy link
Author

Oh, now I get it.

MemoryManager<T>.CreateMemory does not allocate memory, it returns a Memory<T> object with that length property only. That helps.

The limitation of 2 GiB is not an issue. All Span<T>, Memory<T>, Range, Index are limited that way. The memory mapped file is segmented anyway with each segment below 64 MiB.

If all works out, I will expand MemoryMappedViewAccessor (actually UnmanagedMemoryAccessor) with a "Memory<T> UnmanagedMemoryAccessor.GetMemory(Int64)" function.

@huoyaoyuan
Copy link
Member

Related: #37227

@fbrosseau
Copy link

Just a detail, but

I'm not using MemoryMappedViewAccessor, it's not a very useful class, I directly bind to windows API MapViewOfFile() and receive a pointer

Unless I am missing something, you are redoing MemoryMappedViewAccessor.SafeMemoryMappedViewHandle.AcquirePointer(ref byte*)

@hopperpl
Copy link
Author

Oh, I did not know about that pointer access ability. And I actually didn't expect SafeHandle to expose the base address pointer. Good to know.

@GrabYourPitchforks
Copy link
Member

As @huoyaoyuan mentioned, I think the API aspect of this issue is a dupe of #37227. @hopperpl, is there anything else to address from a question perspective, or can we resolve the issue?

@hopperpl
Copy link
Author

I have it now working with a Memory accessor.

Thanks to all.

@ghost ghost locked as resolved and limited conversation to collaborators Aug 17, 2021
@tannergooding tannergooding removed the untriaged New issue has not been triaged by the area owner label Jun 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants