Skip to content

SES service allocates huge amounts of memory  #1922

@dziedrius

Description

@dziedrius

Description

We've noticed huge memory traffic in our app after we started to send larger attachments with SES, so I've composed small app to see what is going on. To send ~5MB email message SES SDK allocates > 250MB of memory, which is 50 times more than message itself, to send 4 such messages in parallel we need to allocate more than 1GB of RAM, which in my opinion is not right.

Screenshots are taken from dotMemory profiler, I was running console app below with allocations recording.
In total sending email allocated:
image
The call tree is very deep, hence did not fit in single screenshot, but main parts are two, CreateWebRequest:
image
and signing:
image

Some strange things, I have to admit that I haven't checked the source code:

  1. Seems that GetParametersAsString was called twice, hence allocating twice.
  2. Why you need to sign request - I'm pretty sure it travels through HTTPS.
  3. Why you need to encode everything as url and why it takes so much memory.

Reproduction Steps

Project:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="AWSSDK.SimpleEmail" Version="3.7.0.73" />
      <PackageReference Include="MimeKit" Version="2.15.1" />
    </ItemGroup>

</Project>

Program.cs

using System;
using System.IO;
using System.Threading.Tasks;
using Amazon;
using Amazon.Runtime;
using Amazon.SimpleEmail;
using Amazon.SimpleEmail.Model;
using MimeKit;

namespace SesMemory
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var options = FormatOptions.Default.Clone();
            
            var sesKey = "my-ses-key";
            var sesSecret = "my-ses-secret";
            var region = "us-west-2";
            var amazonSimpleEmailService = new AmazonSimpleEmailServiceClient(
                new BasicAWSCredentials(sesKey, sesSecret),
                RegionEndpoint.GetBySystemName(region));
            
            var mimeMessage = CreateMimeMessage();

            // entry point for memory profiler capture
            Console.WriteLine("press key to start");
            Console.ReadKey();
            
            using (var memoryStream = new MemoryStream())
            {
                await mimeMessage.WriteToAsync(options, memoryStream);
                
                var sendRequest = new SendRawEmailRequest  { RawMessage = new RawMessage(memoryStream)};
                var response = await amazonSimpleEmailService.SendRawEmailAsync(sendRequest);
            }
            
            // exit point for memory profiler capture
            Console.WriteLine("press key to exit");
            Console.ReadKey();
        }

        private static MimeMessage CreateMimeMessage()
        {
            var emailMessage = new MimeMessage();

            emailMessage.From.Add(new MailboxAddress("[email protected]", "[email protected]"));
            emailMessage.To.Add(new MailboxAddress(string.Empty, "[email protected]"));
            emailMessage.Subject = "test subject";

            var emailBody = new BodyBuilder
            {
                TextBody = "text body",
                HtmlBody = "html body"
            };
            
            // ~5mb png
            emailBody.Attachments.Add("test.jpg", File.ReadAllBytes(@"C:\temp\test-image.png"));
            
            emailMessage.Body = emailBody.ToMessageBody();

            return emailMessage;
        }
    }
}

Environment

  • SDK Version: 3.7.0.73
  • Package Version: 3.7.0.73
  • OS Info: Windows 10 | Linux Alpine
  • Build Environment: Rider
  • Targeted .NET Platform: 5.0

Resolution

Optimize memory allocations so that it would not be 50 times size of the message.


This is a 🐛 bug-report

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions