C
C#2y ago
RumTery

❔ Any reasons to use System.Memory<T> instead Array<T>

Just read docs about System.Memory<T>, tried it... I there any use cases where array can't do same work?
42 Replies
RumTery
RumTeryOP2y ago
Also. Is there any way to get memory from MemoryPool.Shared.Rent of exact same size as minimal size in method parameters?
Thinker
Thinker2y ago
Memory<T>, similarly to Span<T>, is just a view of memory, it's not an array in itself.
RumTery
RumTeryOP2y ago
Anyway, is there any use cases showing difference between their usage? The same idea is applied to array. I can use AsSpan() and modify array's data, or send it somewhere if there's no async/await/threading
cap5lut
cap5lut2y ago
but with Memory<T> u can do it, as its just a struct and not a ref struct like Span<T>
RumTery
RumTeryOP2y ago
Same for array, except that it's class
cap5lut
cap5lut2y ago
also u can throw a Memory<T> on native allocated memory (eg. from P/Invokes) without copying anything. with an array u would have to make a copy
RumTery
RumTeryOP2y ago
Well, this is useful case
cap5lut
cap5lut2y ago
which means a heap allocation for sure, and if u just want to provide access to the first X elements with an array u would have to create a new array, so new allocations, more stuff for the GC to care about and u have to copy data. not to mention the ReadOnly variants ;p
RumTery
RumTeryOP2y ago
Ok. I got the idea And what about memory size from MemoryPool.Shared.Rent?
cap5lut
cap5lut2y ago
if its too big for what ya want, just slice it shorter ;p eg
var rented = MemoryPool<byte>.Shared.Rent(1024);
try {
var buffer = rented[..1024];
// do stuff
} finally {
MemoryPool<byte>.Shared.Return(rented);
}
var rented = MemoryPool<byte>.Shared.Rent(1024);
try {
var buffer = rented[..1024];
// do stuff
} finally {
MemoryPool<byte>.Shared.Return(rented);
}
RumTery
RumTeryOP2y ago
Thanks a lot
cap5lut
cap5lut2y ago
didnt use the memory pool yet, but i guess its similar to the array pool stuff
RumTery
RumTeryOP2y ago
There's no way to slice memoryPool owner... And no Return of rented, only Dispose 🥲 Ok. but I understood all
Aaron
Aaron2y ago
yeah it's slightly different than how they showed
using var rent = MemoryPool<byte>.Shared.Rent(1024);
var memory = rent.Memory[..1024];
// use the memory
using var rent = MemoryPool<byte>.Shared.Rent(1024);
var memory = rent.Memory[..1024];
// use the memory
cap5lut
cap5lut2y ago
well, if i need to use a pool, i usually just use an array pool.
byte[] rented = MemoryPool<byte>.Shared.Rent(1024);
try {
var buffer = rented.AsMemory()[..1024];
// do stuff
} finally {
ArrayPool<byte>.Shared.Return(rented);
}
byte[] rented = MemoryPool<byte>.Shared.Rent(1024);
try {
var buffer = rented.AsMemory()[..1024];
// do stuff
} finally {
ArrayPool<byte>.Shared.Return(rented);
}
Aaron
Aaron2y ago
MemoryPool returns a IMemoryOwner not an array/Memory directly
cap5lut
cap5lut2y ago
good to know, i should probably rewrite some of my stuff ;p
Aaron
Aaron2y ago
ArrayPool just returns a normal array though
cap5lut
cap5lut2y ago
yeah, i assume the memory pool variant is better cuz less instancing oh, btw a real life example would probably be text parsing and alike
RumTery
RumTeryOP2y ago
Why Pools designed to return a bit more... awkward behaviour that forces to save size Already using it while learning OpenGL
cap5lut
cap5lut2y ago
well, for array pools its probably, if they have a "free" 40 sized array and u request a 32 sized array, they wouldnt need to allocate one
RumTery
RumTeryOP2y ago
If memory is just start and size... They could just give slice of free memory
cap5lut
cap5lut2y ago
maybe its because of memory alignment (i dunno too much about it, but in the end there must be a reason for it)
RumTery
RumTeryOP2y ago
especially if it can be moved by GC that size offset could be also moved and used as free in pool... Will try to find something about it
cap5lut
cap5lut2y ago
maybe its also, that they simply work with "constant" chunk sizes and simply get x chunks back, so they dont have to deal with too much fragmentation
RumTery
RumTeryOP2y ago
Magic 4095 🙂
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;

namespace System.Buffers
{
internal sealed partial class ArrayMemoryPool<T> : MemoryPool<T>
{
public sealed override int MaxBufferSize => Array.MaxLength;

public sealed override unsafe IMemoryOwner<T> Rent(int minimumBufferSize = -1)
{
#pragma warning disable 8500 // sizeof of managed types
if (minimumBufferSize == -1)
minimumBufferSize = 1 + (4095 / sizeof(T));
else if (((uint)minimumBufferSize) > Array.MaxLength)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumBufferSize);
#pragma warning restore 8500

return new ArrayMemoryPoolBuffer(minimumBufferSize);
}

protected sealed override void Dispose(bool disposing) { } // ArrayMemoryPool is a shared pool so Dispose() would be a nop even if there were native resources to dispose.
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;

namespace System.Buffers
{
internal sealed partial class ArrayMemoryPool<T> : MemoryPool<T>
{
public sealed override int MaxBufferSize => Array.MaxLength;

public sealed override unsafe IMemoryOwner<T> Rent(int minimumBufferSize = -1)
{
#pragma warning disable 8500 // sizeof of managed types
if (minimumBufferSize == -1)
minimumBufferSize = 1 + (4095 / sizeof(T));
else if (((uint)minimumBufferSize) > Array.MaxLength)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.minimumBufferSize);
#pragma warning restore 8500

return new ArrayMemoryPoolBuffer(minimumBufferSize);
}

protected sealed override void Dispose(bool disposing) { } // ArrayMemoryPool is a shared pool so Dispose() would be a nop even if there were native resources to dispose.
}
}
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
RumTery
RumTeryOP2y ago
It was Unsafe.SizeOf<T> before That this 4095 not commented any way or not set to variable/const with human-written name )
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
RumTery
RumTeryOP2y ago
That makes sense. But it works only minSize set to -1
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
RumTery
RumTeryOP2y ago
Yeah, also found code
cap5lut
cap5lut2y ago
and here i am using mainly stackalloc ;p
RumTery
RumTeryOP2y ago
I think i'll just use array 🤣 and somehow convert it to memory
cap5lut
cap5lut2y ago
new double[1024].AsMemory() and u r done ;p
cap5lut
cap5lut2y ago
MemoryOwner - .NET Community Toolkit
A buffer type implementing IMemoryOwner that rents memory from a shared pool
RumTery
RumTeryOP2y ago
Wow, will try
RumTery
RumTeryOP2y ago
All I needed 🤣
RumTery
RumTeryOP2y ago
Thank you very much ✌️
cap5lut
cap5lut2y ago
dont forget to $close the thread if ur questions are answered
MODiX
MODiX2y ago
Use the /close command to mark a forum thread as answered
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server