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 Aug 27, 2023
1 parent 9e8e83a commit ba9a703
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 ba9a703

Please sign in to comment.