From 3fd8d4f251b912a4e647a8c60dbaa644ef0b2241 Mon Sep 17 00:00:00 2001 From: The Robur team Date: Mon, 10 Jun 2024 11:44:59 +0000 Subject: [PATCH] Built from 29221af45101db8048bce3bdaacff41dc16b9b48 --- articles/miragevpn-performance.html | 61 +++++++++++++++++++++++++++++ feed.xml | 2 +- index.html | 13 ++++++ tags/community.html | 2 +- tags/cryptography.html | 6 +-- tags/git.html | 2 +- tags/gpt.html | 2 +- tags/mbr.html | 2 +- tags/mirageos.html | 6 +-- tags/ocaml.html | 6 +-- tags/performance.html | 41 +++++++++++++++++++ tags/persistent storage.html | 2 +- tags/python.html | 2 +- tags/scheduler.html | 2 +- tags/security.html | 6 +-- tags/tar.html | 2 +- tags/unicode.html | 2 +- tags/unikernel.html | 2 +- tags/vpn.html | 6 +-- 19 files changed, 141 insertions(+), 26 deletions(-) create mode 100644 articles/miragevpn-performance.html create mode 100644 tags/performance.html diff --git a/articles/miragevpn-performance.html b/articles/miragevpn-performance.html new file mode 100644 index 0000000..ca43706 --- /dev/null +++ b/articles/miragevpn-performance.html @@ -0,0 +1,61 @@ + + + + + + + + + Robur's blog - Speeding up MirageVPN and use it in the wild + + + + + + + + +
+

blog.robur.coop

+
+ The Robur cooperative blog. +
+
+
Back to index + +
+

Speeding up MirageVPN and use it in the wild

+

As we were busy continuing to work on MirageVPN, we got in touch with eduVPN, who are interested about deploying MirageVPN. We got example configuration from their side, and fixed some issues, and also implemented tls-crypt - which was straightforward since we earlier spend time to implement tls-crypt-v2.

+

In January, they gave MirageVPN another try, and measured the performance -- which was very poor -- MirageVPN (run as a Unix binary) provided a bandwith of 9.3Mb/s, while OpenVPN provided a bandwidth of 360Mb/s (using a VPN tunnel over TCP).

+

We aim at spending less resources for computing, thus the result was not satisfying for us. We re-read a lot of code, refactored a lot, and are now at ~250Mb/s.

+

Tooling for performance engineering of OCaml

+

As a first approach we connected with the MirageVPN unix client & OpenVPN client to a eduVPN server and ran speed tests using fast.com. This was sufficient to show the initial huge gap in download speeds between MirageVPN and OpenVPN. There is a lot of noise in this approach as there are many computers and routers involved in this setup, and it is hard to reproduce.

+

To get more reproducible results we set up a local VM with openvpn and iperf3 installed. On the host machine we can then connect to the VM's OpenVPN server and run iperf3 against the VPN ip address. This worked more reliably. However, it was still noisy and not suitable to measure single digit percentage changes in performance. +To better guide the performance engineering, we also developed a microbenchmark using OCaml tooling. This will setup a client and server without any input and output, and transfer data in memory.

+

We also re-read our code and used the Linux utility perf together with Flamegraph to graph its output. This works nicely with OCaml programs (we're using the 4.14.1 compiler and runtime system). We did the performance engineering on Unix binaries, i.e. not on MirageOS unikernels - but the MirageVPN protocol is used in both scenarios - thus the performance improvements described here are also in the MirageVPN unikernels.

+

Takeaway of performance engineering

+

The learnings of our performance engineering are in three areas:

+
    +
  • Formatting strings is computational expensive -- thus if in an error case a hexdump is produced of a packet, its construction must be delayed for when the error case is executed (we have this PR and that PR). Alain Frisch wrote a nice blog post at LexiFi about performance of Printf and Format[1].
  • +
  • Rethink allocations: fundamentally, only a single big buffer (to be send out) for each incoming packet should be allocated, not a series of buffers that are concatenated (see this PR and that PR). Additionally, not zeroing out the just allocated buffer (if it is filled with data anyways) removes some further instructions (see this PR). And we figured that appending to an empty buffer nevertheless allocated and copied in OCaml, so we worked on this PR.
  • +
  • Still an open topic is: we are in the memory-safe language OCaml, and we sometimes extract data out of a buffer (or set data in a buffer). Now, each operation lead to bounds checks (that we do not touch memory that is not allocated or not ours). However, if we just checked for the buffer being long enough (either by checking the length, or by allocating a specific amount of data), these bounds checks are superfluous. So far, we don't have an automated solution for this issue, but we are discussing it in the OCaml community, and are eager to find a solution to avoid unneeded computations.
  • +
+

Conclusion

+

To conclude: we already achieved a factor of 25 in performance by adapting the code in various ways. We have ideas to improve the performance even more in the future - we also work on using OCaml string and bytes, instead of off-the-OCaml-heap-allocated bigarrays (see our previous article, which provided some speedups).

+

Don't hesitate to reach out to us on GitHub, or by mail if you're stuck.

+

We want to thank NLnet for their funding (via NGI assure), and eduVPN for their interest.

+
    +
  1. +

    It has come to our attention that the blog post is rather old (2012) and that the implementation has been completely rewritten since then.

    +↩︎︎
+ +
+ +
+ + + + diff --git a/feed.xml b/feed.xml index 41eba56..7da4fcc 100644 --- a/feed.xml +++ b/feed.xml @@ -1 +1 @@ -Robur's bloghttps://blog.robur.coopThe Robur cooperative blogyocamlteam@robur.coopGPTarhttps://blog.robur.coop/articles/gptar.htmlWed, 21 Feb 2024 10:00:00 GMTHybrid GUID partition table and tar archivehttps://blog.robur.coop/articles/gptar.htmlSpeeding elliptic curve cryptographyhttps://blog.robur.coop/articles/speeding-ec-string.htmlTue, 13 Feb 2024 10:00:00 GMTHow we improved the performance of elliptic curves by only modifying the underlying byte arrayhttps://blog.robur.coop/articles/speeding-ec-string.htmlCooperation and Lwt.pausehttps://blog.robur.coop/articles/lwt_pause.htmlSun, 11 Feb 2024 10:00:00 GMTA disgression about Lwt and Miouhttps://blog.robur.coop/articles/lwt_pause.htmlPython's `str.__repr__()`https://blog.robur.coop/articles/2024-02-03-python-str-repr.htmlSat, 03 Feb 2024 10:00:00 GMTReimplementing Python string escaping in OCamlhttps://blog.robur.coop/articles/2024-02-03-python-str-repr.htmlMirageVPN updated (AEAD, NCP)https://blog.robur.coop/articles/miragevpn-ncp.htmlMon, 20 Nov 2023 10:00:00 GMTHow we resurrected MirageVPN from its bitrot statehttps://blog.robur.coop/articles/miragevpn-ncp.htmlMirageVPN & tls-crypt-v2https://blog.robur.coop/articles/miragevpn.htmlTue, 14 Nov 2023 10:00:00 GMTHow we implementated tls-crypt-v2 for miragevpnhttps://blog.robur.coop/articles/miragevpn.html \ No newline at end of file +Robur's bloghttps://blog.robur.coopThe Robur cooperative blogyocamlteam@robur.coopSpeeding up MirageVPN and use it in the wildhttps://blog.robur.coop/articles/miragevpn-performance.htmlTue, 16 Apr 2024 10:00:00 GMTPerformance engineering of MirageVPN, speeding it up by a factor of 25.https://blog.robur.coop/articles/miragevpn-performance.htmlGPTarhttps://blog.robur.coop/articles/gptar.htmlWed, 21 Feb 2024 10:00:00 GMTHybrid GUID partition table and tar archivehttps://blog.robur.coop/articles/gptar.htmlSpeeding elliptic curve cryptographyhttps://blog.robur.coop/articles/speeding-ec-string.htmlTue, 13 Feb 2024 10:00:00 GMTHow we improved the performance of elliptic curves by only modifying the underlying byte arrayhttps://blog.robur.coop/articles/speeding-ec-string.htmlCooperation and Lwt.pausehttps://blog.robur.coop/articles/lwt_pause.htmlSun, 11 Feb 2024 10:00:00 GMTA disgression about Lwt and Miouhttps://blog.robur.coop/articles/lwt_pause.htmlPython's `str.__repr__()`https://blog.robur.coop/articles/2024-02-03-python-str-repr.htmlSat, 03 Feb 2024 10:00:00 GMTReimplementing Python string escaping in OCamlhttps://blog.robur.coop/articles/2024-02-03-python-str-repr.htmlMirageVPN updated (AEAD, NCP)https://blog.robur.coop/articles/miragevpn-ncp.htmlMon, 20 Nov 2023 10:00:00 GMTHow we resurrected MirageVPN from its bitrot statehttps://blog.robur.coop/articles/miragevpn-ncp.htmlMirageVPN & tls-crypt-v2https://blog.robur.coop/articles/miragevpn.htmlTue, 14 Nov 2023 10:00:00 GMTHow we implementated tls-crypt-v2 for miragevpnhttps://blog.robur.coop/articles/miragevpn.html \ No newline at end of file diff --git a/index.html b/index.html index 89447df..7ee7958 100644 --- a/index.html +++ b/index.html @@ -26,6 +26,19 @@

Essays and ramblings

  1. + +
    + 2024-04-16 + Speeding up MirageVPN and use it in the wild
    +

    Performance engineering of MirageVPN, speeding it up by a factor of 25.

    + +
    +
  2. diff --git a/tags/community.html b/tags/community.html index 1d1bbb1..d665acf 100644 --- a/tags/community.html +++ b/tags/community.html @@ -23,7 +23,7 @@
    Back to index - +
    diff --git a/tags/git.html b/tags/git.html index e9f9799..8c10891 100644 --- a/tags/git.html +++ b/tags/git.html @@ -23,7 +23,7 @@
    Back to index - +

    git diff --git a/tags/gpt.html b/tags/gpt.html index bca92c5..45da39d 100644 --- a/tags/gpt.html +++ b/tags/gpt.html @@ -23,7 +23,7 @@
    Back to index - +

    gpt diff --git a/tags/mbr.html b/tags/mbr.html index cb3d936..22886bf 100644 --- a/tags/mbr.html +++ b/tags/mbr.html @@ -23,7 +23,7 @@
    Back to index - +
    diff --git a/tags/ocaml.html b/tags/ocaml.html index c6ebdc6..61e8ee3 100644 --- a/tags/ocaml.html +++ b/tags/ocaml.html @@ -23,12 +23,12 @@
    Back to index - +

    +
    diff --git a/tags/performance.html b/tags/performance.html new file mode 100644 index 0000000..75b2856 --- /dev/null +++ b/tags/performance.html @@ -0,0 +1,41 @@ + + + + + + + + + Robur's blog + + + + + + + + +
    +

    blog.robur.coop

    +
    + The Robur cooperative blog. +
    +
    +
    Back to index + + + + + +
    + + + + diff --git a/tags/persistent storage.html b/tags/persistent storage.html index c2fdf19..3e9e832 100644 --- a/tags/persistent storage.html +++ b/tags/persistent storage.html @@ -23,7 +23,7 @@
    Back to index - +

    persistent storage diff --git a/tags/python.html b/tags/python.html index 26bcb22..64b2967 100644 --- a/tags/python.html +++ b/tags/python.html @@ -23,7 +23,7 @@
    Back to index - +

    python diff --git a/tags/scheduler.html b/tags/scheduler.html index bafb772..0a6262b 100644 --- a/tags/scheduler.html +++ b/tags/scheduler.html @@ -23,7 +23,7 @@
    Back to index - +
    diff --git a/tags/tar.html b/tags/tar.html index 4f09825..e880b35 100644 --- a/tags/tar.html +++ b/tags/tar.html @@ -23,7 +23,7 @@
    Back to index - +

    tar diff --git a/tags/unicode.html b/tags/unicode.html index bb75b3a..1f0a9f2 100644 --- a/tags/unicode.html +++ b/tags/unicode.html @@ -23,7 +23,7 @@
    Back to index - +