public void Pin_throw_ArgumentOutOfRangeException() { using (var mgr = new UnmanagedMemoryManager <byte>(1)) { Assert.Throws <ArgumentOutOfRangeException>(() => mgr.Pin(-1)); } }
public void Disposed_throw_ObjectDisposedException() { var mgr = new UnmanagedMemoryManager <char>(1); ((IDisposable)mgr).Dispose(); Assert.Throws <ObjectDisposedException>(() => mgr.Pin()); Assert.Throws <ObjectDisposedException>(() => mgr.Unpin()); Assert.Throws <ObjectDisposedException>(() => mgr.GetSpan()); }
static void Main(string[] args) { while (true) { UnmanagedMemoryManager m = new UnmanagedMemoryManager(); m = null; GC.Collect(); // GC로 인해 소멸자가 호출되므로 비관리 메모리도 해제됨. Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64); } }
static void Main(string[] args) { while (true) { using (UnmanagedMemoryManager m = new UnmanagedMemoryManager()) { } Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64); } }
public void ToBase64_Stackalloc() { byte[] data = Encoding.UTF8.GetBytes("Hello world"); Span <byte> s = stackalloc byte[data.Length]; data.CopyTo(s); using var manager = new UnmanagedMemoryManager <byte>(s); ByteString bs = ByteString.AttachBytes(manager.Memory); Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64()); }
static void Main(string[] args) { while (true) { UnmanagedMemoryManager m = new UnmanagedMemoryManager(); m = null; GC.Collect(); // GC를 강제로 수행 // 현재 프로세스가 사용하는 메모리 크기 출력 Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64); } }
public void ToString_Stackalloc() { byte[] data = Encoding.UTF8.GetBytes("Hello world"); Span <byte> s = stackalloc byte[data.Length]; data.CopyTo(s); using (UnmanagedMemoryManager <byte> manager = new UnmanagedMemoryManager <byte>(s)) { ByteString bs = ByteString.AttachBytes(manager.Memory); Assert.AreEqual("Hello world", bs.ToString(Encoding.UTF8)); } }
void TestM <T>() { const int length = 100; UnmanagedMemoryManager <T> manager = new UnmanagedMemoryManager <T>(length); var span = manager.GetSpan(); Assert.AreEqual(length, manager.Length); Assert.AreEqual(length, span.Length); dynamic value = default; if (typeof(T) == typeof(byte)) { value = byte.MaxValue; } if (typeof(T) == typeof(short)) { value = short.MaxValue; } if (typeof(T) == typeof(int)) { value = int.MaxValue; } if (typeof(T) == typeof(long)) { value = long.MaxValue; } span[0] = value; var span2 = manager.GetSpan(); Assert.AreEqual(span2[0], span[0]); if (manager is IDisposable disposable) { disposable.Dispose(); try { var span3 = manager.GetSpan(); } catch (ObjectDisposedException) { } Assert.AreEqual(-1, manager.Length); } }
static void Main(string[] args) { while (true) // 무한으로 { UnmanagedMemoryManager m = new UnmanagedMemoryManager(); // GC에 관리되지 않는 메모리를 생성한다. m = null; // m을 null로 해서 생성된 메모리에 접근할 수 없게 한다. GC.Collect(); // 이미 종료 큐에 생성된 레퍼런스를 제거했으므로 가비지 컬렉션을 하면 별도의 작업없이 객체를 삭제할 수 있다. // Process는 자원에 대한 측정기능을 제공한다. // 현재 사용하는 자원 중에 // 메모리 사이즈를 측정한다. Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64); } }
static void Main(string[] args) { while (true) // 무한으로 { UnmanagedMemoryManager m = new UnmanagedMemoryManager(); // GC에 관리되지 않는 메모리를 생성한다. m = null; // m을 null로 해서 생성된 메모리에 접근할 수 없게 한다. GC.Collect(); // 가비지 컬렉션을 강제로 수행 // Process는 자원에 대한 측정기능을 제공한다. // 현재 사용하는 자원 중에 // 메모리 사이즈를 측정한다. Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64); } // 무한으로 돌리고, GC가 메모리를 관리해주지도 않으므로 OutOfMemoryException이 발생한다. }
static void Main(string[] args) { while (true) // 무한으로 { UnmanagedMemoryManager m = new UnmanagedMemoryManager(); // GC에 관리되지 않는 메모리를 생성한다. m = null; // m을 null로 해서 생성된 메모리에 접근할 수 없게 한다. GC.Collect(); // 객체의 소멸자를 정의해주었으므로 가비지컬렉션을 할 때 소멸자가 호출되어서 Dispose가 호출된다. // 따라서 비관리 메모리도 해제된다. // Process는 자원에 대한 측정기능을 제공한다. // 현재 사용하는 자원 중에 // 메모리 사이즈를 측정한다. Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64); // OutOfMemoryException은 발생하지 않지만 // 성능문제가 있다. } }
/// <summary> /// <para> /// Wraps an existing contiguous memory area of 'width' x 'height' pixels allowing viewing/manipulation as /// an <see cref="Image{TPixel}"/> instance. /// </para> /// <para> /// Please note: this method relies on callers to carefully manage the target memory area being referenced by the /// pointer and that the lifetime of such a memory area is at least equal to that of the returned /// <see cref="Image{TPixel}"/> instance. For example, if the input pointer references an unmanaged memory area, /// callers must ensure that the memory area is not freed as long as the returned <see cref="Image{TPixel}"/> is /// in use and not disposed. The same applies if the input memory area points to a pinned managed object, as callers /// must ensure that objects will remain pinned as long as the <see cref="Image{TPixel}"/> instance is in use. /// Failing to do so constitutes undefined behavior and will likely lead to memory corruption and runtime crashes. /// </para> /// <para> /// Note also that if you have a <see cref="Memory{T}"/> or an array (which can be cast to <see cref="Memory{T}"/>) of /// either <see cref="byte"/> or <typeparamref name="TPixel"/> values, it is highly recommended to use one of the other /// available overloads of this method instead (such as <see cref="WrapMemory{TPixel}(Configuration, Memory{byte}, int, int)"/> /// or <see cref="WrapMemory{TPixel}(Configuration, Memory{TPixel}, int, int)"/>, to make the resulting code less error /// prone and avoid having to pin the underlying memory buffer in use. This method is primarily meant to be used when /// doing interop or working with buffers that are located in unmanaged memory. /// </para> /// </summary> /// <typeparam name="TPixel">The pixel type</typeparam> /// <param name="configuration">The <see cref="Configuration"/></param> /// <param name="pointer">The pointer to the target memory buffer to wrap.</param> /// <param name="width">The width of the memory image.</param> /// <param name="height">The height of the memory image.</param> /// <param name="metadata">The <see cref="ImageMetadata"/>.</param> /// <exception cref="ArgumentNullException">The configuration is null.</exception> /// <exception cref="ArgumentNullException">The metadata is null.</exception> /// <returns>An <see cref="Image{TPixel}"/> instance</returns> public static unsafe Image <TPixel> WrapMemory <TPixel>( Configuration configuration, void *pointer, int width, int height, ImageMetadata metadata) where TPixel : unmanaged, IPixel <TPixel> { Guard.IsFalse(pointer == null, nameof(pointer), "Pointer must be not null"); Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(metadata, nameof(metadata)); var memoryManager = new UnmanagedMemoryManager <TPixel>(pointer, width * height); var memorySource = MemoryGroup <TPixel> .Wrap(memoryManager.Memory); return(new Image <TPixel>(configuration, memorySource, width, height, metadata)); }
public void WriteToStream_Stackalloc() { byte[] data = Encoding.UTF8.GetBytes("Hello world"); Span <byte> s = stackalloc byte[data.Length]; data.CopyTo(s); MemoryStream ms = new MemoryStream(); using (UnmanagedMemoryManager <byte> manager = new UnmanagedMemoryManager <byte>(s)) { ByteString bs = ByteString.AttachBytes(manager.Memory); bs.WriteTo(ms); } CollectionAssert.AreEqual(data, ms.ToArray()); }
public async Task WriteAsync() { using (var stream = new MemoryStream()) { await IOBackports.WriteAsync(stream, _data.AsMemory()); Assert.Equal(_data.Length, stream.Length); Assert.True(_data.SequenceEqual(stream.ToArray())); } using (var stream = new MemoryStream()) { using var m = new UnmanagedMemoryManager <byte>(_data.Length); _data.AsSpan().CopyTo(m.Memory.Span); await IOBackports.WriteAsync(stream, m.Memory); Assert.Equal(_data.Length, stream.Length); Assert.True(_data.SequenceEqual(stream.ToArray())); } }
public void Pin() { using (var mgr = new UnmanagedMemoryManager <char>(3)) { var expected = mgr.Memory.Span; expected[0] = 'a'; expected[1] = 'b'; expected[2] = 'c'; using (var second = mgr.Pin(0)) { var actual00 = *(char *)second.Pointer; var actual01 = *((char *)second.Pointer + 1); var actual02 = *((char *)second.Pointer + 2); Assert.Equal(expected[0], actual00); Assert.Equal(expected[1], actual01); Assert.Equal(expected[2], actual02); } } }
public async Task ReadAsync() { using (var stream = new MemoryStream(_data, false)) { var buffer = new byte[_data.Length]; var size = await IOBackports.ReadAsync(stream, buffer.AsMemory()); Assert.Equal(_data.Length, size); Assert.True(_data.SequenceEqual(buffer)); } using (var stream = new MemoryStream(_data, false)) { var buffer = new byte[_data.Length + 1]; var size = await IOBackports.ReadAsync(stream, buffer.AsMemory()); Assert.Equal(_data.Length, size); Assert.True(_data.SequenceEqual(buffer.Take(size))); } using (var stream = new MemoryStream(_data, false)) { using var m = new UnmanagedMemoryManager <byte>(_data.Length); var size = await IOBackports.ReadAsync(stream, m.Memory); Assert.Equal(_data.Length, size); Assert.True(_data.AsSpan().IsSame(m.Memory.Span)); } using (var stream = new MemoryStream(_data, false)) { using var m = new UnmanagedMemoryManager <byte>(_data.Length + 1); var size = await IOBackports.ReadAsync(stream, m.Memory); Assert.Equal(_data.Length, size); Assert.True(_data.AsSpan().IsSame(m.Memory.Span.Slice(0, size))); } }