Skip to content

Commit

Permalink
Modified ByteArrayBuilder.Clear() to downsize its buffer if it has gr…
Browse files Browse the repository at this point in the history
…own too large

One potential problem with reusing ByteArrayBuilders is that, because they can
grow for some abnormally long tokens/lines/commands/etc, those oversized buffers
will remain referenced by the ImapStream/ImapEngine until they are disposed which
could be the life of the program.

If we oportunistically scale back the size of the buffers when they are Clear()'d,
then we can periodically reduce memory usage and allow those larger buffers to be
used elsewhere.
  • Loading branch information
jstedfast committed Sep 2, 2023
1 parent 6da7279 commit 3b06559
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions MailKit/ByteArrayBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,20 @@
using System;
using System.Text;
using System.Buffers;
using System.Runtime.CompilerServices;

namespace MailKit
{
class ByteArrayBuilder : IDisposable
{
readonly int initialCapacity;
byte[] buffer;
int length;

public ByteArrayBuilder (int initialCapacity)
public ByteArrayBuilder (int capacity)
{
buffer = ArrayPool<byte>.Shared.Rent (initialCapacity);
buffer = ArrayPool<byte>.Shared.Rent (capacity);
initialCapacity = capacity;
length = 0;
}

Expand All @@ -54,6 +57,7 @@ public byte[] GetBuffer ()
return buffer;
}

[MethodImpl (MethodImplOptions.AggressiveInlining)]
void EnsureCapacity (int capacity)
{
if (capacity > buffer.Length) {
Expand All @@ -79,6 +83,11 @@ public void Append (byte[] text, int startIndex, int count)

public void Clear ()
{
if (buffer.Length > initialCapacity * 4) {
ArrayPool<byte>.Shared.Return (buffer);
buffer = ArrayPool<byte>.Shared.Rent (initialCapacity);
}

length = 0;
}

Expand Down

0 comments on commit 3b06559

Please sign in to comment.