I have built an application to send email mailers for a website through Amazon SES. It is coded in C#.
Each email takes .3 seconds to send via the Amazon SES API. That means, using a single-threaded application, I can only send 3 emails per second.
I have implemented a producer/consumer, multi-threaded application with 1 producer to query customize the emails for each customer, and 25 consumers to pull from the queue and send the emails.
My multi-threaded application sends 12 emails per second (a quadruple speed increase). I would have expected a greater speed increase from a 25-thread application.
My question is: How much can I really speed up the sending of a mailer on a single-processor machine? Do my gains seem reasonable, or is my speed problem more likely due to coding than to the computer's inability to process the emails mroe quickly?
Thanks in advance!
UPDATE: In case others are facing the same issue.... connecting to AWS in order to send the email takes up a lot of time. The following thread on AWS Developer forums gives some insight (You may need to scroll down to get to the more useful posts).
https://forums.aws.amazon.com/thread.jspa?threadID=78737
You can speed up very much even though it's single-processor machine.
Sending an Email does not consume a lot of CPU, it's an IO bound operation. Therefore you will increase your performance very much by doing the work in parallel.
I blogged about my solution. Basically you use a Parallel.ForEach
loop with a MaxDegreeOfParallelism
, don't forget to increase the maxconnection
count in app.config
.
Below is the app.config
sample:
<system.net>
<connectionManagement>
<add address="*" maxconnection="392" />
</connectionManagement>
<mailSettings>
<smtp from="[email protected]" deliveryMethod="Network">
<network host="email-smtp.us-east-1.amazonaws.com" userName="SmtpUsername" password="SmtpPassword" enableSsl="true" port="587" />
</smtp>
</mailSettings>
</system.net>
And here is the Parallel.ForEach
loop sample:
class Program
{
static readonly object syncRoot = new object();
private readonly static int maxParallelEmails = 196;
static void Main(string[] args)
{
IList<Model.SendEmailTo> recipients = _emailerService.GetEmailsToSend();
int cnt = 0;
int totalCnt = recipients.Count;
Parallel.ForEach(recipients.AsParallel(), new ParallelOptions { MaxDegreeOfParallelism = maxParallelEmails }, recipient =>
{
// Do any other logic
// Build the email HTML
// Send the email, make sure to log exceptions
// Track email, etc
lock (syncRoot) cnt++;
Console.WriteLine(String.Format("{0}/{1} - Sent newsletter email to: {2}", cnt, totalCnt, recipient.Email));
});
}
}
My blog explains it in more detail: http://michaeldimoudis.com/blog/2013/5/25/reliably-and-speedily-send-mass-emails-via-amazon-ses-in-c
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With