This project benchmarks various .NET MIME parsers for comparison purposes.
Package | Version |
---|---|
MimeKit | 4.12.0 |
LimiLabs' Mail.dll | 3.0.25121.1408 |
Mime4Net | 1.8.1 |
AE.Net.Mail | 1.7.10 |
MailSystem.NET | 2.0.1 |
OpenPOP.NET | 2.0.6.1120 |
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775)
Intel Core i7-9700 CPU 3.00GHz, 1 CPU, 8 logical and 8 physical cores
[Host] : .NET Framework 4.8.1 (4.8.9290.0), X64 RyuJIT VectorSize=256
DefaultJob : .NET Framework 4.8.1 (4.8.9290.0), X64 RyuJIT VectorSize=256
In this benchmark, each library is used to parse an in-memory email message that is almost all headers 1,000 times.
Method | Mean | Error | StdDev |
---|---|---|---|
MimeKit | 30.28 ms | 0.229 ms | 0.215 ms |
MimeKitPersistent | 30.53 ms | 0.546 ms | 0.484 ms |
LimiLabs | 729.34 ms | 7.569 ms | 6.321 ms |
Mime4Net | 573.89 ms | 9.861 ms | 10.551 ms |
OpenPOP | 399.10 ms | 7.696 ms | 8.554 ms |
AENetMail | 2,912.24 ms | 57.274 ms | 70.338 ms |
MailSystemNET | 1,954.23 ms | 25.525 ms | 22.627 ms |
In this benchmark, each library is used to parse the jwz.mbox
Unix mbox spool from disk 10 times.
Method | Mean | Error | StdDev |
---|---|---|---|
MimeKit | 177.1 ms | 2.52 ms | 2.36 ms |
MimeKitPersistent | 163.7 ms | 2.92 ms | 4.64 ms |
LimiLabs | 1,166.2 ms | 23.01 ms | 21.52 ms |
In this benchmark, each library is used to parse startrek.eml
from disk 1,000 times.
Method | Mean | Error | StdDev |
---|---|---|---|
MimeKit | 216.6 ms | 4.33 ms | 5.48 ms |
MimeKitPersistent | 195.7 ms | 3.91 ms | 5.48 ms |
LimiLabs | 5,776.4 ms | 110.47 ms | 118.20 ms |
Mime4Net | 11,114.1 ms | 85.75 ms | 76.01 ms |
OpenPOP | NA | NA | NA |
AENetMail | 4,018.5 ms | 26.65 ms | 20.80 ms |
MailSystemNET | 9,528.9 ms | 127.01 ms | 99.16 ms |
Notes:
- MailSystem.NET's parser only supports parsing from byte[] or MemoryStream, so in this test, MailSystem.NET is allowed to "cheat" by parsing an in-memory version of the message instead of being forced to parse from disk in each iteration.
- OpenPOP.NET fails to parse this message with the following exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: Media Type must be in the format type "/" subtype
Parameter name: mediaType
at OpenPop.Mime.Header.HeaderFieldParser.cleanMediaType(String mediaType)
at OpenPop.Mime.Header.HeaderFieldParser.ParseContentType(String headerValue)
at OpenPop.Mime.Header.MessageHeader.ParseHeader(String headerName, String headerValue)
at OpenPop.Mime.Header.MessageHeader.ParseHeaders(NameValueCollection headers)
at OpenPop.Mime.Header.HeaderExtractor.ExtractHeadersAndBody(Byte[] fullRawMessage, MessageHeader& headers, Byte[]& body, IParsingErrorHandler parsingErrorHandler)
at OpenPop.Mime.MessagePart.ParseMultiPartBody(Byte[] rawBody)
at OpenPop.Mime.MessagePart.ParseMultiPartBody(Byte[] rawBody)
at OpenPop.Mime.Message.Load(Stream messageStream, IParsingErrorHandler parsingErrorHandler)
at Benchmarks.StarTrekEmailBenchmarks.OpenPOP()
at BenchmarkDotNet.Autogenerated.Runnable_14.WorkloadActionNoUnroll(Int64 invokeCount)
at BenchmarkDotNet.Engines.Engine.RunIteration(IterationData data)
at BenchmarkDotNet.Engines.EngineFactory.Jit(Engine engine, Int32 jitIndex, Int32 invokeCount, Int32 unrollFactor)
at BenchmarkDotNet.Engines.EngineFactory.CreateReadyToRun(EngineParameters engineParameters)
at BenchmarkDotNet.Autogenerated.Runnable_14.Run(IHost host, String benchmarkName)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at BenchmarkDotNet.Autogenerated.UniqueProgramName.AfterAssemblyLoadingAttached(String[] args)
In this benchmark, each library is used to parse xamarin3.eml
from disk 1,000 times.
Method | Mean | Error | StdDev | Median |
---|---|---|---|---|
MimeKit | 1.693 s | 0.0316 s | 0.0400 s | 1.679 s |
MimeKitPersistent | 1.314 s | 0.0201 s | 0.0188 s | 1.312 s |
LimiLabs | 14.392 s | 0.1196 s | 0.1060 s | 14.362 s |
Mime4Net | 90.029 s | 1.0404 s | 0.9732 s | 90.027 s |
OpenPOP | 78.548 s | 1.0670 s | 0.9981 s | 78.792 s |
AENetMail | 31.338 s | 0.5670 s | 0.6529 s | 31.322 s |
MailSystemNET | 54.039 s | 1.0752 s | 3.1363 s | 52.791 s |
Notes:
- MailSystem.NET's parser only supports parsing from byte[] or MemoryStream, so in this test, MailSystem.NET is allowed to "cheat" by parsing an in-memory version of the message instead of being forced to parse from disk in each iteration.
Yea. No contest. MimeKit mops the floor with all of the other parsers out there.
How does your MIME parser compare?