Skip to content

Commit d9e547d

Browse files
committed
Moved logic for array pooling to a separate class.
1 parent 336613a commit d9e547d

File tree

6 files changed

+94
-55
lines changed

6 files changed

+94
-55
lines changed

src/Magick.NET.Core/Magick.NET.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<Compile Include="../Shared/FileHelper.cs" Link="Helpers/FileHelper.cs" />
2121
<Compile Include="../Shared/MemberNotNullAttribute.cs" Link="Helpers/MemberNotNullAttribute.cs" />
2222
<Compile Include="../Shared/NotNullAttribute.cs" Link="Helpers/NotNullAttribute.cs" />
23+
<Compile Include="../Shared/PooledByteArray.cs" Link="Helpers/PooledByteArray.cs" />
2324
<Compile Include="../Shared/Throw.cs" Link="Helpers/Throw.cs" />
2425
<Compile Include="../Shared/CallerArgumentExpressionAttribute.cs" Link="Helpers/CallerArgumentExpressionAttribute.cs" />
2526
<Compile Include="../Shared/TypeHelper.cs" Link="Helpers/TypeHelper.cs" />

src/Magick.NET/Helpers/ByteArrayWrapper.cs

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,21 @@
33

44
using System;
55
using System.IO;
6-
#if !NETSTANDARD2_0
7-
using System.Buffers;
8-
#endif
96

107
namespace ImageMagick;
118

129
internal sealed unsafe class ByteArrayWrapper : IDisposable
1310
{
14-
#if !NETSTANDARD2_0
15-
private static readonly ArrayPool<byte> _pool = ArrayPool<byte>.Create(1024 * 1024 * 64, 128);
16-
17-
private byte[] _bytes = _pool.Rent(8192);
18-
#else
19-
private byte[] _bytes = new byte[8192];
20-
#endif
11+
private readonly PooledByteArray _bytes = new PooledByteArray(8192);
2112
private int _offset = 0;
22-
2313
private int _length = 0;
2414

25-
#if !NETSTANDARD2_0
2615
public void Dispose()
27-
=> _pool.Return(_bytes);
16+
=> _bytes.Dispose();
2817

2918
public byte[] GetBytes()
30-
{
31-
var result = new byte[_length];
32-
Array.Copy(_bytes, result, _length);
33-
return result;
34-
}
35-
36-
#else
37-
public void Dispose()
38-
{
39-
}
19+
=> _bytes.ToUnpooledArray(_length);
4020

41-
public byte[] GetBytes()
42-
{
43-
ResizeBytes(_length);
44-
return _bytes;
45-
}
46-
47-
#endif
4821
public long Read(IntPtr data, UIntPtr count, IntPtr user_data)
4922
{
5023
if (data == IntPtr.Zero)
@@ -58,7 +31,7 @@ public long Read(IntPtr data, UIntPtr count, IntPtr user_data)
5831
if (length != 0)
5932
{
6033
var destination = (byte*)data.ToPointer();
61-
fixed (byte* source = _bytes)
34+
fixed (byte* source = _bytes.Data)
6235
{
6336
NativeMemory.Copy(source + _offset, destination, length);
6437
}
@@ -108,7 +81,7 @@ public long Write(IntPtr data, UIntPtr count, IntPtr user_data)
10881
EnsureLength(newOffset);
10982

11083
var source = (byte*)data.ToPointer();
111-
fixed (byte* destination = _bytes)
84+
fixed (byte* destination = _bytes.Data)
11285
{
11386
NativeMemory.Copy(source, destination + _offset, total);
11487
}
@@ -132,16 +105,6 @@ private void EnsureLength(int length)
132105
ResizeBytes(newLength);
133106
}
134107

135-
#if !NETSTANDARD2_0
136-
private void ResizeBytes(int length)
137-
{
138-
var newBytes = _pool.Rent(length);
139-
Array.Copy(_bytes, newBytes, _bytes.Length);
140-
_pool.Return(_bytes);
141-
_bytes = newBytes;
142-
}
143-
#else
144108
private void ResizeBytes(int length)
145-
=> Array.Resize(ref _bytes, length);
146-
#endif
109+
=> _bytes.Resize(length);
147110
}

src/Magick.NET/Helpers/StreamWrapper.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ internal sealed unsafe class StreamWrapper : IDisposable
1111
{
1212
private const int BufferSize = 8192;
1313

14-
private readonly byte[] _buffer;
14+
private readonly PooledByteArray _buffer;
1515
private readonly byte* _bufferStart;
1616
private readonly long _streamStart;
1717
private readonly GCHandle _handle;
@@ -20,8 +20,8 @@ internal sealed unsafe class StreamWrapper : IDisposable
2020
private StreamWrapper(Stream stream)
2121
{
2222
_stream = stream;
23-
_buffer = new byte[BufferSize];
24-
_handle = GCHandle.Alloc(_buffer, GCHandleType.Pinned);
23+
_buffer = new PooledByteArray(BufferSize);
24+
_handle = GCHandle.Alloc(_buffer.Data, GCHandleType.Pinned);
2525
_bufferStart = (byte*)_handle.AddrOfPinnedObject().ToPointer();
2626

2727
try
@@ -49,7 +49,10 @@ public static StreamWrapper CreateForWriting(Stream stream)
4949
}
5050

5151
public void Dispose()
52-
=> _handle.Free();
52+
{
53+
_handle.Free();
54+
_buffer.Dispose();
55+
}
5356

5457
public long Read(IntPtr data, UIntPtr count, IntPtr user_data)
5558
{
@@ -69,7 +72,7 @@ public long Read(IntPtr data, UIntPtr count, IntPtr user_data)
6972

7073
try
7174
{
72-
length = _stream.Read(_buffer, 0, (int)length);
75+
length = _stream.Read(_buffer.Data, 0, (int)length);
7376
}
7477
catch
7578
{
@@ -138,7 +141,7 @@ public long Write(IntPtr data, UIntPtr count, IntPtr user_data)
138141

139142
try
140143
{
141-
_stream.Write(_buffer, 0, (int)length);
144+
_stream.Write(_buffer.Data, 0, (int)length);
142145
}
143146
catch
144147
{

src/Magick.NET/Magick.NET.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
<Compile Include="../Shared/FileHelper.cs" Link="Helpers/FileHelper.cs" />
7676
<Compile Include="../Shared/MemberNotNullAttribute.cs" Link="Helpers/MemberNotNullAttribute.cs" />
7777
<Compile Include="../Shared/NotNullAttribute.cs" Link="Helpers/NotNullAttribute.cs" />
78+
<Compile Include="../Shared/PooledByteArray.cs" Link="Helpers/PooledByteArray.cs" />
7879
<Compile Include="../Shared/Throw.cs" Link="Helpers/Throw.cs" />
7980
<Compile Include="../Shared/CallerArgumentExpressionAttribute.cs" Link="Helpers/CallerArgumentExpressionAttribute.cs" />
8081
<Compile Include="../Shared/TypeHelper.cs" Link="Helpers/TypeHelper.cs" />

src/Shared/Bytes.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ private static byte[] GetData(Stream stream, out int length)
6969
return GetDataWithSeekableStream(stream, out length);
7070

7171
int count;
72-
var buffer = new byte[BufferSize];
72+
using var buffer = new PooledByteArray(BufferSize);
7373
using var tempStream = new MemoryStream();
74-
while ((count = stream.Read(buffer, 0, BufferSize)) != 0)
74+
while ((count = stream.Read(buffer.Data, 0, BufferSize)) != 0)
7575
{
7676
CheckLength(tempStream.Length + count);
7777

78-
tempStream.Write(buffer, 0, count);
78+
tempStream.Write(buffer.Data, 0, count);
7979
}
8080

8181
return GetDataFromMemoryStream(tempStream, out length);
@@ -98,13 +98,13 @@ private static byte[] GetData(Stream stream, out int length)
9898
return await GetDataWithSeekableStreamAsync(stream, cancellationToken).ConfigureAwait(false);
9999

100100
int count;
101-
var buffer = new byte[BufferSize];
101+
using var buffer = new PooledByteArray(BufferSize);
102102
using var tempStream = new MemoryStream();
103-
while ((count = await stream.ReadAsync(buffer, 0, BufferSize, cancellationToken).ConfigureAwait(false)) != 0)
103+
while ((count = await stream.ReadAsync(buffer.Data, 0, BufferSize, cancellationToken).ConfigureAwait(false)) != 0)
104104
{
105105
CheckLength(tempStream.Length + count);
106106

107-
tempStream.Write(buffer, 0, count);
107+
tempStream.Write(buffer.Data, 0, count);
108108
}
109109

110110
bytes = GetDataFromMemoryStream(tempStream, out length);

src/Shared/PooledByteArray.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright Dirk Lemstra https://github.com/dlemstra/Magick.NET.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using System;
5+
#if !NETSTANDARD2_0
6+
using System.Buffers;
7+
#endif
8+
9+
namespace ImageMagick;
10+
11+
internal sealed class PooledByteArray : IDisposable
12+
{
13+
#if !NETSTANDARD2_0
14+
private static readonly ArrayPool<byte> _pool = ArrayPool<byte>.Create(1024 * 1024 * 64, 128);
15+
private byte[] _bytes;
16+
17+
public PooledByteArray(int length)
18+
=> _bytes = _pool.Rent(length);
19+
20+
public byte[] Data
21+
=> _bytes;
22+
23+
public int Length
24+
=> _bytes.Length;
25+
26+
public void Dispose()
27+
=> _pool.Return(_bytes);
28+
29+
public void Resize(int length)
30+
{
31+
if (length <= _bytes.Length)
32+
return;
33+
34+
var newBytes = _pool.Rent(length);
35+
Buffer.BlockCopy(_bytes, 0, newBytes, 0, _bytes.Length);
36+
_pool.Return(_bytes);
37+
}
38+
39+
public byte[] ToUnpooledArray(int length)
40+
{
41+
var result = new byte[length];
42+
Buffer.BlockCopy(_bytes, 0, result, 0, length);
43+
return result;
44+
}
45+
46+
#else
47+
private byte[] _bytes;
48+
49+
public PooledByteArray(int length)
50+
=> _bytes = new byte[length];
51+
52+
public byte[] Data
53+
=> _bytes;
54+
55+
public int Length
56+
=> _bytes.Length;
57+
58+
public void Dispose()
59+
{
60+
}
61+
62+
public void Resize(int length)
63+
=> Array.Resize(ref _bytes, length);
64+
65+
public byte[] ToUnpooledArray(int length)
66+
{
67+
Array.Resize(ref _bytes, length);
68+
return _bytes;
69+
}
70+
#endif
71+
}

0 commit comments

Comments
 (0)