Skip to content

Commit 32656db

Browse files
committed
Minor memory usage improvement
1 parent ff64983 commit 32656db

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

Microsoft.Toolkit.Mvvm/Messaging/WeakReferenceMessenger.cs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Buffers;
77
using System.Collections.Generic;
8+
using System.Diagnostics.Contracts;
89
using System.Runtime.CompilerServices;
910
using Microsoft.Collections.Extensions;
1011
using Microsoft.Toolkit.Mvvm.Messaging.Internals;
@@ -181,8 +182,8 @@ public TMessage Send<TMessage, TToken>(TMessage message, TToken token)
181182
return message;
182183
}
183184

184-
recipients = new ArrayPoolBufferWriter<object>();
185-
handlers = new ArrayPoolBufferWriter<object>();
185+
recipients = ArrayPoolBufferWriter<object>.Create();
186+
handlers = ArrayPoolBufferWriter<object>.Create();
186187

187188
// We need a local, temporary copy of all the pending recipients and handlers to
188189
// invoke, to avoid issues with handlers unregistering from messages while we're
@@ -232,8 +233,8 @@ public void Cleanup()
232233
{
233234
lock (this.recipientsMap)
234235
{
235-
using ArrayPoolBufferWriter<Type2> type2s = new ArrayPoolBufferWriter<Type2>();
236-
using ArrayPoolBufferWriter<object> emptyRecipients = new ArrayPoolBufferWriter<object>();
236+
using ArrayPoolBufferWriter<Type2> type2s = ArrayPoolBufferWriter<Type2>.Create();
237+
using ArrayPoolBufferWriter<object> emptyRecipients = ArrayPoolBufferWriter<object>.Create();
237238

238239
var enumerator = this.recipientsMap.GetEnumerator();
239240

@@ -385,7 +386,12 @@ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
385386
/// A simple buffer writer implementation using pooled arrays.
386387
/// </summary>
387388
/// <typeparam name="T">The type of items to store in the list.</typeparam>
388-
private sealed class ArrayPoolBufferWriter<T> : IDisposable
389+
/// <remarks>
390+
/// This type is a <see langword="ref"/> <see langword="struct"/> to avoid the object allocation and to
391+
/// enable the pattern-based <see cref="IDisposable"/> support. We aren't worried with consumers not
392+
/// using this type correctly since it's private and only accessible within the parent type.
393+
/// </remarks>
394+
private ref struct ArrayPoolBufferWriter<T>
389395
{
390396
/// <summary>
391397
/// The default buffer size to use to expand empty arrays.
@@ -403,12 +409,13 @@ private sealed class ArrayPoolBufferWriter<T> : IDisposable
403409
private int index;
404410

405411
/// <summary>
406-
/// Initializes a new instance of the <see cref="ArrayPoolBufferWriter{T}"/> class.
412+
/// Creates a new instance of the <see cref="ArrayPoolBufferWriter{T}"/> struct.
407413
/// </summary>
408-
public ArrayPoolBufferWriter()
414+
[Pure]
415+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
416+
public static ArrayPoolBufferWriter<T> Create()
409417
{
410-
this.array = ArrayPool<T>.Shared.Rent(DefaultInitialBufferSize);
411-
this.index = 0;
418+
return new ArrayPoolBufferWriter<T> { array = ArrayPool<T>.Shared.Rent(DefaultInitialBufferSize) };
412419
}
413420

414421
/// <summary>
@@ -461,7 +468,7 @@ private void ResizeBuffer()
461468
this.array = rent;
462469
}
463470

464-
/// <inheritdoc/>
471+
/// <inheritdoc cref="IDisposable.Dispose"/>
465472
public void Dispose()
466473
{
467474
Array.Clear(this.array, 0, this.index);

0 commit comments

Comments
 (0)