Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/jstedfast/mimeparserbenchmark

Benchmark for popular MIME parsers for .NET
https://github.com/jstedfast/mimeparserbenchmark

Last synced: 12 days ago
JSON representation

Benchmark for popular MIME parsers for .NET

Awesome Lists containing this project

README

        

# MimeParserBenchmark

This project benchmarks various .NET MIME parsers for comparison purposes.

## Package Versions

| Package | Version |
|-----------------------------------------------------------------------:|:-----------------------------------------------------------------------------------:|
| MimeKit | 3.0.0 |
| LimiLabs' Mail.dll | 3.0.21294.1630 |
| Mime4Net | 1.8.1 |
| AE.Net.Mail | 1.7.10 |
| MailSystem.NET | 2.0.1 |
| OpenPOP.NET | 2.0.6.1120 |

## Runtime

```
Intel Core i7-9700 CPU 3.00GHz, 1 CPU, 8 logical and 8 physical cores
[Host] : .NET Framework 4.8 (4.8.4420.0), X64 RyuJIT
DefaultJob : .NET Framework 4.8 (4.8.4420.0), X64 RyuJIT
```

## Results

### HeavyHeaderEmailBenchmark

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.22 ms | 0.207 ms | 0.183 ms |
| MimeKitPersistent | 30.08 ms | 0.311 ms | 0.276 ms |
| LimiLabs | 629.92 ms | 3.252 ms | 2.883 ms |
| Mime4Net | 517.56 ms | 3.442 ms | 3.051 ms |
| OpenPOP | 353.23 ms | 4.355 ms | 4.074 ms |
| AENetMail | 2,862.46 ms | 17.677 ms | 16.535 ms |
| MailSystemNET | 1,911.98 ms | 11.197 ms | 10.474 ms |

### JwzMboxBenchmark

In this benchmark, each library is used to parse the `jwz.mbox` Unix mbox spool from disk 10 times.

| Method | Mean | Error | StdDev |
|------------------ |-----------:|--------:|--------:|
| MimeKit | 171.3 ms | 0.87 ms | 0.77 ms |
| MimeKitPersistent | 160.1 ms | 1.50 ms | 1.33 ms |
| LimiLabs | 1,148.3 ms | 8.28 ms | 7.75 ms |

### StarTrekEmailBenchmark

In this benchmark, each library is used to parse `startrek.eml` from disk 1,000 times.

| Method | Mean | Error | StdDev |
|------------------ |------------:|---------:|---------:|
| MimeKit | 218.6 ms | 1.95 ms | 1.73 ms |
| MimeKitPersistent | 205.5 ms | 1.72 ms | 1.61 ms |
| LimiLabs | 2,318.0 ms | 12.37 ms | 10.96 ms |
| Mime4Net | 10,726.6 ms | 38.19 ms | 35.73 ms |
| OpenPOP | NA | NA | NA |
| AENetMail | 3,897.4 ms | 74.18 ms | 69.39 ms |
| MailSystemNET | 8,928.0 ms | 29.92 ms | 26.53 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)
```

### Xamarin3EmailBenchmark

In this benchmark, each library is used to parse `xamarin3.eml` from disk 1,000 times.

| Method | Mean | Error | StdDev |
|------------------ |---------:|---------:|---------:|
| MimeKit | 1.629 s | 0.0168 s | 0.0157 s |
| MimeKitPersistent | 1.344 s | 0.0086 s | 0.0080 s |
| LimiLabs | 12.503 s | 0.0421 s | 0.0394 s |
| Mime4Net | 85.075 s | 0.4774 s | 0.3987 s |
| OpenPOP | 80.162 s | 0.6835 s | 0.6059 s |
| AENetMail | 30.925 s | 0.2161 s | 0.1915 s |
| MailSystemNET | 48.179 s | 0.6107 s | 0.5713 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.

### Conclusions

Yea. No contest. MimeKit mops the floor with all of the other parsers out there.

How does **your** MIME parser compare?