Performance deep dive

Protein Translation
Protein Translation in F#

In this approach, we'll find out how to most efficiently translate the RNA to proteins in F#.

The approaches page lists three idiomatic approaches to this exercise:

  1. Using recursion
  2. Using Seq.unfold
  3. Using the Seq module

For our performance investigation, we'll also include a fourth approach that uses the Span<T> type.

Benchmarks

To benchmark the approaches, we wrote a small benchmark application using BenchmarkDotNet library. We've benchmarked using RNA sequences with 0, 1, 10 and 1000 codons.

Method NumberOfCodons Mean Error StdDev Gen0 Gen1 Allocated
Recursion 0 7.493 ns 0.0388 ns 0.0363 ns - - -
SeqModule 0 152.652 ns 2.1404 ns 2.0021 ns 0.0956 - 600 B
Span 0 14.663 ns 0.1050 ns 0.0931 ns - - -
Unfold 0 43.211 ns 0.5399 ns 0.4786 ns 0.0204 - 128 B
Recursion 1 17.780 ns 0.3530 ns 0.3302 ns 0.0051 - 32 B
SeqModule 1 235.316 ns 3.6080 ns 3.3749 ns 0.1109 - 696 B
Span 1 29.655 ns 0.2732 ns 0.2556 ns 0.0051 - 32 B
Unfold 1 82.138 ns 0.9021 ns 0.7997 ns 0.0343 - 216 B
Recursion 10 137.225 ns 1.5763 ns 1.4744 ns 0.1109 - 696 B
SeqModule 10 509.363 ns 7.7862 ns 7.2832 ns 0.1669 - 1048 B
Span 10 24.006 ns 0.4712 ns 0.4408 ns 0.0051 - 32 B
Unfold 10 237.525 ns 3.9554 ns 5.0023 ns 0.1466 - 920 B
Recursion 1000 1,785.969 ns 17.1735 ns 16.0641 ns 4.8676 0.0019 30544 B
SeqModule 1000 501.784 ns 4.8090 ns 4.4983 ns 0.1669 - 1048 B
Span 1000 146.319 ns 1.3266 ns 1.2409 ns 0.0713 - 448 B
Unfold 1000 408.245 ns 5.8096 ns 5.4343 ns 1.0028 0.0224 6296 B

For zero or one codons, the recursion approach is the fastest one. For bigger numbers of codons, the Span<T> approach is undoubtedly the best one, which shows that not allocating strings can be a great boost to performance.

It is interesting to see that, for all but a tiny number of codonds, manual recursion is far less optimal than Seq.unfold.

28th Aug 2024 · Found it useful?