about summary refs log tree commit diff
path: root/third_party/immer/benchmark/vector
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/immer/benchmark/vector')
-rw-r--r--third_party/immer/benchmark/vector/access.hpp261
-rw-r--r--third_party/immer/benchmark/vector/assoc.hpp245
-rw-r--r--third_party/immer/benchmark/vector/branching/access.ipp20
-rw-r--r--third_party/immer/benchmark/vector/branching/assoc.ipp20
-rw-r--r--third_party/immer/benchmark/vector/branching/basic/access.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/basic/assoc.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/basic/concat.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/basic/push.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/concat.ipp20
-rw-r--r--third_party/immer/benchmark/vector/branching/gc/access.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/gc/assoc.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/gc/concat.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/gc/push.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/push.ipp20
-rw-r--r--third_party/immer/benchmark/vector/branching/safe/access.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/safe/assoc.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/safe/concat.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/safe/push.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/unsafe/access.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/unsafe/assoc.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/unsafe/concat.cpp10
-rw-r--r--third_party/immer/benchmark/vector/branching/unsafe/push.cpp10
-rw-r--r--third_party/immer/benchmark/vector/common.hpp212
-rw-r--r--third_party/immer/benchmark/vector/concat.hpp166
-rw-r--r--third_party/immer/benchmark/vector/drop.hpp142
-rw-r--r--third_party/immer/benchmark/vector/misc/access.cpp94
-rw-r--r--third_party/immer/benchmark/vector/misc/assoc.cpp119
-rw-r--r--third_party/immer/benchmark/vector/misc/concat.cpp49
-rw-r--r--third_party/immer/benchmark/vector/misc/drop.cpp63
-rw-r--r--third_party/immer/benchmark/vector/misc/push-front.cpp30
-rw-r--r--third_party/immer/benchmark/vector/misc/push.cpp83
-rw-r--r--third_party/immer/benchmark/vector/misc/take.cpp65
-rw-r--r--third_party/immer/benchmark/vector/paper/access.cpp31
-rw-r--r--third_party/immer/benchmark/vector/paper/assoc-random.cpp40
-rw-r--r--third_party/immer/benchmark/vector/paper/assoc.cpp40
-rw-r--r--third_party/immer/benchmark/vector/paper/concat.cpp22
-rw-r--r--third_party/immer/benchmark/vector/paper/push.cpp28
-rw-r--r--third_party/immer/benchmark/vector/push.hpp111
-rw-r--r--third_party/immer/benchmark/vector/push_front.hpp46
-rw-r--r--third_party/immer/benchmark/vector/take.hpp144
40 files changed, 2231 insertions, 0 deletions
diff --git a/third_party/immer/benchmark/vector/access.hpp b/third_party/immer/benchmark/vector/access.hpp
new file mode 100644
index 0000000000..4dff7a667f
--- /dev/null
+++ b/third_party/immer/benchmark/vector/access.hpp
@@ -0,0 +1,261 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include "benchmark/vector/common.hpp"
+
+#include <immer/algorithm.hpp>
+
+#if IMMER_BENCHMARK_BOOST_COROUTINE
+#include <boost/coroutine2/all.hpp>
+#endif
+
+namespace {
+
+template <typename Vektor>
+auto benchmark_access_reduce_chunkedseq()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v.push_back(i);
+        return [=] {
+            auto init = 0u;
+            v.for_each_segment([&] (auto first, auto last) {
+                init = std::accumulate(first, last, init);
+            });
+            return init;
+        };
+    };
+}
+
+template <typename Vektor>
+auto benchmark_access_iter_std()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v.push_back(i);
+        return [=] {
+            auto volatile x = std::accumulate(v.begin(), v.end(), 0u);
+            return x;
+        };
+    };
+}
+
+template <typename Vektor>
+auto benchmark_access_idx_std()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v.push_back(i);
+        return [=] {
+            auto r = 0u;
+            for (auto i = 0u; i < n; ++i)
+                r += v[i];
+            volatile auto rr = r;
+            return rr;
+        };
+    };
+}
+
+template <typename Vektor>
+auto benchmark_access_random_std()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+        auto v = Vektor{};
+        auto g = make_generator(n);
+        for (auto i = 0u; i < n; ++i)
+            v.push_back(i);
+        return [=] {
+            auto r = 0u;
+            for (auto i = 0u; i < n; ++i)
+                r += v[g[i]];
+            volatile auto rr = r;
+            return rr;
+        };
+    };
+}
+
+template <typename Vektor, typename PushFn=push_back_fn>
+auto benchmark_access_iter()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        return [=] {
+            auto volatile x = std::accumulate(v.begin(), v.end(), 0u);
+            return x;
+        };
+    };
+}
+
+#if IMMER_BENCHMARK_BOOST_COROUTINE
+template <typename Vektor, typename PushFn=push_back_fn>
+auto benchmark_access_coro()
+{
+    return [] (nonius::parameters params)
+    {
+        using coro_t = typename boost::coroutines2::coroutine<int>;
+
+        auto n = params.get<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        return [=] {
+            auto c = coro_t::pull_type { [&](auto& sink) {
+                v.for_each_chunk([&](auto f, auto l) {
+                    for (; f != l; ++f)
+                        sink(*f);
+                });
+            }};
+            auto volatile x = std::accumulate(begin(c), end(c), 0u);
+            return x;
+        };
+    };
+}
+#endif
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_access_idx()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        return [=] {
+            auto r = 0u;
+            for (auto i = 0u; i < n; ++i)
+                r += v[i];
+            volatile auto rr = r;
+            return rr;
+        };
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_access_reduce()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        return [=] {
+            auto volatile x = immer::accumulate(v, 0u);
+            return x;
+        };
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_access_reduce_range()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        return [=] {
+            auto volatile x = immer::accumulate(v.begin(), v.end(), 0u);
+            return x;
+        };
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_access_random()
+{
+    return [] (nonius::parameters params)
+    {
+        auto n = params.get<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+        auto g = make_generator(n);
+
+        return [=] {
+            auto r = 0u;
+            for (auto i = 0u; i < n; ++i)
+                r += v[g[i]];
+            volatile auto rr = r;
+            return rr;
+        };
+    };
+}
+
+template <typename Fn>
+auto benchmark_access_librrb(Fn maker)
+{
+    return
+        [=] (nonius::parameters params) {
+            auto n = params.get<N>();
+            auto v = maker(n);
+            return
+                [=] {
+                    auto r = 0u;
+                    for (auto i = 0u; i < n; ++i)
+                        r += reinterpret_cast<unsigned long>(rrb_nth(v, i));
+                    volatile auto rr = r;
+                    return rr;
+                };
+        };
+}
+
+template <typename Fn>
+auto benchmark_access_random_librrb(Fn maker)
+{
+    return
+        [=] (nonius::parameters params) {
+            auto n = params.get<N>();
+            auto v = maker(n);
+            auto g = make_generator(n);
+            return
+                [=] {
+                    auto r = 0u;
+                    for (auto i = 0u; i < n; ++i)
+                        r += reinterpret_cast<unsigned long>(rrb_nth(v, g[i]));
+                    volatile auto rr = r;
+                    return rr;
+                };
+        };
+}
+
+} // anonymous namespace
diff --git a/third_party/immer/benchmark/vector/assoc.hpp b/third_party/immer/benchmark/vector/assoc.hpp
new file mode 100644
index 0000000000..5619d7ee69
--- /dev/null
+++ b/third_party/immer/benchmark/vector/assoc.hpp
@@ -0,0 +1,245 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include "benchmark/vector/common.hpp"
+
+namespace {
+
+template <typename Vektor>
+auto benchmark_assoc_std()
+{
+    return
+        [] (nonius::chronometer meter)
+        {
+            auto n = meter.param<N>();
+            auto v = Vektor(n, 0);
+            std::iota(v.begin(), v.end(), 0u);
+            auto all = std::vector<Vektor>(meter.runs(), v);
+            meter.measure([&] (int iter) {
+                auto& r = all[iter];
+                for (auto i = 0u; i < n; ++i)
+                    r[i] = n - i;
+                return r;
+            });
+        };
+}
+
+template <typename Vektor>
+auto benchmark_assoc_random_std()
+{
+    return
+        [](nonius::chronometer meter)
+        {
+            auto n = meter.param<N>();
+            auto g = make_generator(n);
+            auto v = Vektor(n, 0);
+            std::iota(v.begin(), v.end(), 0u);
+            auto all = std::vector<Vektor>(meter.runs(), v);
+            meter.measure([&] (int iter) {
+                auto& r = all[iter];
+                for (auto i = 0u; i < n; ++i)
+                    r[g[i]] = n - i;
+                return r;
+            });
+        };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn,
+          typename SetFn=set_fn>
+auto benchmark_assoc()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v;
+            for (auto i = 0u; i < n; ++i)
+                r = SetFn{}(r, i, n - i);
+            return r;
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_assoc_move()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v;
+            for (auto i = 0u; i < n; ++i)
+                r = std::move(r).set(i, n - i);
+            return r;
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn,
+          typename SetFn=set_fn>
+auto benchmark_assoc_random()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        auto g = make_generator(n);
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v;
+            for (auto i = 0u; i < n; ++i)
+                r = SetFn{}(r, g[i], i);
+            return r;
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_assoc_mut()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v.transient();
+            for (auto i = 0u; i < n; ++i)
+                r.set(i, n - i);
+            return r;
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_assoc_mut_random()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        auto g = make_generator(n);
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v.transient();
+            for (auto i = 0u; i < n; ++i)
+                r.set(g[i], i);
+            return r;
+        });
+    };
+}
+
+template <typename Fn>
+auto benchmark_assoc_librrb(Fn maker)
+{
+    return
+        [=] (nonius::chronometer meter) {
+            auto n = meter.param<N>();
+            auto v = maker(n);
+            measure(
+                meter, [&] {
+                    auto r = v;
+                    for (auto i = 0u; i < n; ++i)
+                        r = rrb_update(r, i, reinterpret_cast<void*>(n - i));
+                    return r;
+                });
+        };
+}
+
+template <typename Fn>
+auto benchmark_assoc_random_librrb(Fn maker)
+{
+    return
+        [=] (nonius::chronometer meter) {
+            auto n = meter.param<N>();
+            auto v = maker(n);
+            auto g = make_generator(n);
+            measure(
+                meter, [&] {
+                    auto r = v;
+                    for (auto i = 0u; i < n; ++i)
+                        r = rrb_update(r, g[i], reinterpret_cast<void*>(i));
+                    return r;
+                });
+        };
+}
+
+template <typename Fn>
+auto benchmark_assoc_mut_librrb(Fn maker)
+{
+    return
+        [=] (nonius::chronometer meter) {
+            auto n = meter.param<N>();
+            auto v = maker(n);
+            measure(
+                meter, [&] {
+                    auto r = rrb_to_transient(v);
+                    for (auto i = 0u; i < n; ++i)
+                        r = transient_rrb_update(
+                            r, i, reinterpret_cast<void*>(i));
+                    return r;
+                });
+        };
+}
+
+template <typename Fn>
+auto benchmark_assoc_mut_random_librrb(Fn maker)
+{
+    return
+        [=] (nonius::chronometer meter) {
+            auto n = meter.param<N>();
+            auto v = maker(n);
+            auto g = make_generator(n);
+            measure(
+                meter, [&] {
+                    auto r = rrb_to_transient(v);
+                    for (auto i = 0u; i < n; ++i)
+                        r = transient_rrb_update(
+                            r, g[i], reinterpret_cast<void*>(i));
+                    return r;
+                });
+        };
+}
+
+} // anonymous namespace
diff --git a/third_party/immer/benchmark/vector/branching/access.ipp b/third_party/immer/benchmark/vector/branching/access.ipp
new file mode 100644
index 0000000000..bd7f985d4d
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/access.ipp
@@ -0,0 +1,20 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/access.hpp"
+#include <immer/flex_vector.hpp>
+
+#ifndef MEMORY_T
+#error "define the MEMORY_T"
+#endif
+
+NONIUS_BENCHMARK("flex/3", benchmark_access_idx<immer::flex_vector<std::size_t,MEMORY_T,3>>())
+NONIUS_BENCHMARK("flex/4", benchmark_access_idx<immer::flex_vector<std::size_t,MEMORY_T,4>>())
+NONIUS_BENCHMARK("flex/5", benchmark_access_idx<immer::flex_vector<std::size_t,MEMORY_T,5>>())
+NONIUS_BENCHMARK("flex/6", benchmark_access_idx<immer::flex_vector<std::size_t,MEMORY_T,6>>())
+NONIUS_BENCHMARK("flex/7", benchmark_access_idx<immer::flex_vector<std::size_t,MEMORY_T,7>>())
diff --git a/third_party/immer/benchmark/vector/branching/assoc.ipp b/third_party/immer/benchmark/vector/branching/assoc.ipp
new file mode 100644
index 0000000000..4aa9984f92
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/assoc.ipp
@@ -0,0 +1,20 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/assoc.hpp"
+#include <immer/flex_vector.hpp>
+
+#ifndef MEMORY_T
+#error "define the MEMORY_T"
+#endif
+
+NONIUS_BENCHMARK("flex/3", benchmark_assoc<immer::flex_vector<std::size_t,MEMORY_T,3>>())
+NONIUS_BENCHMARK("flex/4", benchmark_assoc<immer::flex_vector<std::size_t,MEMORY_T,4>>())
+NONIUS_BENCHMARK("flex/5", benchmark_assoc<immer::flex_vector<std::size_t,MEMORY_T,5>>())
+NONIUS_BENCHMARK("flex/6", benchmark_assoc<immer::flex_vector<std::size_t,MEMORY_T,6>>())
+NONIUS_BENCHMARK("flex/7", benchmark_assoc<immer::flex_vector<std::size_t,MEMORY_T,7>>())
diff --git a/third_party/immer/benchmark/vector/branching/basic/access.cpp b/third_party/immer/benchmark/vector/branching/basic/access.cpp
new file mode 100644
index 0000000000..23eb25565d
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/basic/access.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T basic_memory
+#include "../access.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/basic/assoc.cpp b/third_party/immer/benchmark/vector/branching/basic/assoc.cpp
new file mode 100644
index 0000000000..210a432aba
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/basic/assoc.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T basic_memory
+#include "../assoc.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/basic/concat.cpp b/third_party/immer/benchmark/vector/branching/basic/concat.cpp
new file mode 100644
index 0000000000..21163bdc0b
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/basic/concat.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T basic_memory
+#include "../concat.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/basic/push.cpp b/third_party/immer/benchmark/vector/branching/basic/push.cpp
new file mode 100644
index 0000000000..6be28f9219
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/basic/push.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T basic_memory
+#include "../push.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/concat.ipp b/third_party/immer/benchmark/vector/branching/concat.ipp
new file mode 100644
index 0000000000..0e21ca0b11
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/concat.ipp
@@ -0,0 +1,20 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/concat.hpp"
+#include <immer/flex_vector.hpp>
+
+#ifndef MEMORY_T
+#error "define the MEMORY_T"
+#endif
+
+NONIUS_BENCHMARK("flex/3", benchmark_concat<immer::flex_vector<std::size_t,MEMORY_T,3>>())
+NONIUS_BENCHMARK("flex/4", benchmark_concat<immer::flex_vector<std::size_t,MEMORY_T,4>>())
+NONIUS_BENCHMARK("flex/5", benchmark_concat<immer::flex_vector<std::size_t,MEMORY_T,5>>())
+NONIUS_BENCHMARK("flex/6", benchmark_concat<immer::flex_vector<std::size_t,MEMORY_T,6>>())
+NONIUS_BENCHMARK("flex/7", benchmark_concat<immer::flex_vector<std::size_t,MEMORY_T,7>>())
diff --git a/third_party/immer/benchmark/vector/branching/gc/access.cpp b/third_party/immer/benchmark/vector/branching/gc/access.cpp
new file mode 100644
index 0000000000..cec060481c
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/gc/access.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T gc_memory
+#include "../access.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/gc/assoc.cpp b/third_party/immer/benchmark/vector/branching/gc/assoc.cpp
new file mode 100644
index 0000000000..448b2fd2ff
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/gc/assoc.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T gc_memory
+#include "../assoc.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/gc/concat.cpp b/third_party/immer/benchmark/vector/branching/gc/concat.cpp
new file mode 100644
index 0000000000..6c32ca821c
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/gc/concat.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T gc_memory
+#include "../concat.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/gc/push.cpp b/third_party/immer/benchmark/vector/branching/gc/push.cpp
new file mode 100644
index 0000000000..f1d1e33b92
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/gc/push.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T gc_memory
+#include "../push.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/push.ipp b/third_party/immer/benchmark/vector/branching/push.ipp
new file mode 100644
index 0000000000..2f92d65692
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/push.ipp
@@ -0,0 +1,20 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/push.hpp"
+#include <immer/flex_vector.hpp>
+
+#ifndef MEMORY_T
+#error "define the MEMORY_T"
+#endif
+
+NONIUS_BENCHMARK("flex/3", benchmark_push<immer::flex_vector<std::size_t,MEMORY_T,3>>())
+NONIUS_BENCHMARK("flex/4", benchmark_push<immer::flex_vector<std::size_t,MEMORY_T,4>>())
+NONIUS_BENCHMARK("flex/5", benchmark_push<immer::flex_vector<std::size_t,MEMORY_T,5>>())
+NONIUS_BENCHMARK("flex/6", benchmark_push<immer::flex_vector<std::size_t,MEMORY_T,6>>())
+NONIUS_BENCHMARK("flex/7", benchmark_push<immer::flex_vector<std::size_t,MEMORY_T,7>>())
diff --git a/third_party/immer/benchmark/vector/branching/safe/access.cpp b/third_party/immer/benchmark/vector/branching/safe/access.cpp
new file mode 100644
index 0000000000..027aa1b761
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/safe/access.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T safe_memory
+#include "../access.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/safe/assoc.cpp b/third_party/immer/benchmark/vector/branching/safe/assoc.cpp
new file mode 100644
index 0000000000..c2f5b0cc20
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/safe/assoc.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T safe_memory
+#include "../assoc.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/safe/concat.cpp b/third_party/immer/benchmark/vector/branching/safe/concat.cpp
new file mode 100644
index 0000000000..3c5dbb8a70
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/safe/concat.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T safe_memory
+#include "../concat.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/safe/push.cpp b/third_party/immer/benchmark/vector/branching/safe/push.cpp
new file mode 100644
index 0000000000..19d5bbd254
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/safe/push.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T safe_memory
+#include "../push.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/unsafe/access.cpp b/third_party/immer/benchmark/vector/branching/unsafe/access.cpp
new file mode 100644
index 0000000000..156d84e717
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/unsafe/access.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T unsafe_memory
+#include "../access.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/unsafe/assoc.cpp b/third_party/immer/benchmark/vector/branching/unsafe/assoc.cpp
new file mode 100644
index 0000000000..ff1802c0bc
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/unsafe/assoc.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T unsafe_memory
+#include "../assoc.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/unsafe/concat.cpp b/third_party/immer/benchmark/vector/branching/unsafe/concat.cpp
new file mode 100644
index 0000000000..d6d401bd48
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/unsafe/concat.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T unsafe_memory
+#include "../concat.ipp"
diff --git a/third_party/immer/benchmark/vector/branching/unsafe/push.cpp b/third_party/immer/benchmark/vector/branching/unsafe/push.cpp
new file mode 100644
index 0000000000..09ba8d7a37
--- /dev/null
+++ b/third_party/immer/benchmark/vector/branching/unsafe/push.cpp
@@ -0,0 +1,10 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#define MEMORY_T unsafe_memory
+#include "../push.ipp"
diff --git a/third_party/immer/benchmark/vector/common.hpp b/third_party/immer/benchmark/vector/common.hpp
new file mode 100644
index 0000000000..c96d6d017d
--- /dev/null
+++ b/third_party/immer/benchmark/vector/common.hpp
@@ -0,0 +1,212 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include <utility>
+#include <cstddef>
+#include <limits>
+
+#include "benchmark/config.hpp"
+
+#if IMMER_BENCHMARK_LIBRRB
+extern "C" {
+#define restrict __restrict__
+#include <rrb.h>
+#undef restrict
+}
+#include <immer/heap/gc_heap.hpp>
+#endif
+
+namespace immer {
+template <typename T, typename MP> class array;
+} // namespace immer
+
+namespace {
+
+auto make_generator(std::size_t runs)
+{
+    assert(runs > 0);
+    auto engine = std::default_random_engine{42};
+    auto dist = std::uniform_int_distribution<std::size_t>{0, runs-1};
+    auto r = std::vector<std::size_t>(runs);
+    std::generate_n(r.begin(), runs, std::bind(dist, engine));
+    return r;
+}
+
+struct push_back_fn
+{
+    template <typename T, typename U>
+    auto operator() (T&& v, U&& x)
+    { return std::forward<T>(v).push_back(std::forward<U>(x)); }
+};
+
+struct push_front_fn
+{
+    template <typename T, typename U>
+    auto operator() (T&& v, U&& x)
+    { return std::forward<T>(v).push_front(std::forward<U>(x)); }
+};
+
+struct set_fn
+{
+    template <typename T, typename I, typename U>
+    decltype(auto) operator() (T&& v, I i, U&& x)
+    { return std::forward<T>(v).set(i, std::forward<U>(x)); }
+};
+
+struct store_fn
+{
+    template <typename T, typename I, typename U>
+    decltype(auto) operator() (T&& v, I i, U&& x)
+    { return std::forward<T>(v).store(i, std::forward<U>(x)); }
+};
+
+template <typename T>
+struct get_limit : std::integral_constant<
+    std::size_t, std::numeric_limits<std::size_t>::max()> {};
+
+template <typename T, typename MP>
+struct get_limit<immer::array<T, MP>> : std::integral_constant<
+    std::size_t, 10000> {};
+
+auto make_librrb_vector(std::size_t n)
+{
+    auto v = rrb_create();
+    for (auto i = 0u; i < n; ++i) {
+        v = rrb_push(v, reinterpret_cast<void*>(i));
+    }
+    return v;
+}
+
+auto make_librrb_vector_f(std::size_t n)
+{
+    auto v = rrb_create();
+    for (auto i = 0u; i < n; ++i) {
+        auto f = rrb_push(rrb_create(),
+                          reinterpret_cast<void*>(i));
+        v = rrb_concat(f, v);
+    }
+    return v;
+}
+
+
+// copied from:
+// https://github.com/ivmai/bdwgc/blob/master/include/gc_allocator.h
+
+template <class GC_tp>
+struct GC_type_traits
+{
+  std::false_type GC_is_ptr_free;
+};
+
+# define GC_DECLARE_PTRFREE(T)                  \
+    template<> struct GC_type_traits<T> {       \
+        std::true_type GC_is_ptr_free;          \
+    }
+
+GC_DECLARE_PTRFREE(char);
+GC_DECLARE_PTRFREE(signed char);
+GC_DECLARE_PTRFREE(unsigned char);
+GC_DECLARE_PTRFREE(signed short);
+GC_DECLARE_PTRFREE(unsigned short);
+GC_DECLARE_PTRFREE(signed int);
+GC_DECLARE_PTRFREE(unsigned int);
+GC_DECLARE_PTRFREE(signed long);
+GC_DECLARE_PTRFREE(unsigned long);
+GC_DECLARE_PTRFREE(float);
+GC_DECLARE_PTRFREE(double);
+GC_DECLARE_PTRFREE(long double);
+
+template <class IsPtrFree>
+inline void* GC_selective_alloc(size_t n, IsPtrFree, bool ignore_off_page)
+{
+    return ignore_off_page
+        ? GC_MALLOC_IGNORE_OFF_PAGE(n)
+        : GC_MALLOC(n);
+}
+
+template <>
+inline void* GC_selective_alloc<std::true_type>(size_t n,
+                                                std::true_type,
+                                                bool ignore_off_page)
+{
+    return ignore_off_page
+        ? GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(n)
+        : GC_MALLOC_ATOMIC(n);
+}
+
+template <class T>
+class gc_allocator
+{
+public:
+    typedef size_t       size_type;
+    typedef ptrdiff_t    difference_type;
+    typedef T*       pointer;
+    typedef const T* const_pointer;
+    typedef T&       reference;
+    typedef const T& const_reference;
+    typedef T        value_type;
+
+    template <class T1> struct rebind {
+        typedef gc_allocator<T1> other;
+    };
+
+    gc_allocator()  {}
+    gc_allocator(const gc_allocator&) throw() {}
+    template <class T1>
+    explicit gc_allocator(const gc_allocator<T1>&) throw() {}
+    ~gc_allocator() throw() {}
+
+    pointer address(reference GC_x) const { return &GC_x; }
+    const_pointer address(const_reference GC_x) const { return &GC_x; }
+
+    // GC_n is permitted to be 0.  The C++ standard says nothing about what
+    // the return value is when GC_n == 0.
+    T* allocate(size_type GC_n, const void* = 0)
+    {
+        GC_type_traits<T> traits;
+        return static_cast<T *>
+            (GC_selective_alloc(GC_n * sizeof(T),
+                                traits.GC_is_ptr_free, false));
+    }
+
+    // p is not permitted to be a null pointer.
+    void deallocate(pointer p, size_type /* GC_n */)
+    { GC_FREE(p); }
+
+    size_type max_size() const throw()
+    { return size_t(-1) / sizeof(T); }
+
+    void construct(pointer p, const T& __val) { new(p) T(__val); }
+    void destroy(pointer p) { p->~T(); }
+};
+
+template<>
+class gc_allocator<void>
+{
+    typedef size_t      size_type;
+    typedef ptrdiff_t   difference_type;
+    typedef void*       pointer;
+    typedef const void* const_pointer;
+    typedef void        value_type;
+
+    template <class T1> struct rebind {
+        typedef gc_allocator<T1> other;
+    };
+};
+
+template <class T1, class T2>
+inline bool operator==(const gc_allocator<T1>&, const gc_allocator<T2>&)
+{ return true; }
+
+template <class T1, class T2>
+inline bool operator!=(const gc_allocator<T1>&, const gc_allocator<T2>&)
+{ return false; }
+
+} // anonymous namespace
diff --git a/third_party/immer/benchmark/vector/concat.hpp b/third_party/immer/benchmark/vector/concat.hpp
new file mode 100644
index 0000000000..8656587d5d
--- /dev/null
+++ b/third_party/immer/benchmark/vector/concat.hpp
@@ -0,0 +1,166 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include "benchmark/vector/common.hpp"
+
+namespace {
+
+constexpr auto concat_steps = 10u;
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_concat()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            return v + v;
+        });
+    };
+}
+
+template <typename Fn>
+auto benchmark_concat_librrb(Fn maker)
+{
+    return
+        [=] (nonius::chronometer meter) {
+            auto n = meter.param<N>();
+            auto v = maker(n);
+            measure(meter, [&] {
+                    return rrb_concat(v, v);
+                });
+        };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_concat_incr()
+{
+    return
+        [] (nonius::chronometer meter)
+        {
+            auto n = meter.param<N>();
+
+            auto v = Vektor{};
+            for (auto i = 0u; i < n / concat_steps; ++i)
+                v = PushFn{}(std::move(v), i);
+
+            measure(meter, [&] {
+                    auto r = Vektor{};
+                    for (auto i = 0u; i < concat_steps; ++i)
+                        r = r + v;
+                    return r;
+                });
+        };
+}
+
+template <typename Vektor>
+auto benchmark_concat_incr_mut()
+{
+    return
+        [] (nonius::chronometer meter)
+        {
+            auto n = meter.param<N>();
+
+            auto v = Vektor{}.transient();
+            for (auto i = 0u; i < n / concat_steps; ++i)
+                v.push_back(i);
+
+            measure(meter, [&] (int run) {
+                auto r = Vektor{}.transient();
+                for (auto i = 0u; i < concat_steps; ++i)
+                    r.append(v);
+                return r;
+            });
+        };
+}
+
+template <typename Vektor>
+auto benchmark_concat_incr_mut2()
+{
+    return
+        [] (nonius::chronometer meter)
+        {
+            auto n = meter.param<N>();
+
+            using transient_t = typename Vektor::transient_type;
+            using steps_t = std::vector<transient_t, gc_allocator<transient_t>>;
+            auto vs = std::vector<steps_t, gc_allocator<steps_t>>(meter.runs());
+            for (auto k = 0u; k < vs.size(); ++k) {
+                vs[k].reserve(concat_steps);
+                for (auto j = 0u; j < concat_steps; ++j) {
+                    auto vv = Vektor{}.transient();
+                    for (auto i = 0u; i < n / concat_steps; ++i)
+                        vv.push_back(i);
+                    vs[k].push_back(std::move(vv));
+                }
+            }
+            measure(meter, [&] (int run) {
+                auto& vr = vs[run];
+                auto r = Vektor{}.transient();
+                assert(vr.size() == concat_steps);
+                for (auto i = 0u; i < concat_steps; ++i)
+                    r.append(std::move(vr[i]));
+                return r;
+            });
+        };
+}
+
+template <typename Vektor>
+auto benchmark_concat_incr_chunkedseq()
+{
+    return
+        [] (nonius::chronometer meter)
+        {
+            auto n = meter.param<N>();
+
+            using steps_t = std::vector<Vektor>;
+            auto vs = std::vector<steps_t>(meter.runs());
+            for (auto k = 0u; k < vs.size(); ++k) {
+                for (auto j = 0u; j < concat_steps; ++j) {
+                    auto vv = Vektor{};
+                    for (auto i = 0u; i < n / concat_steps; ++i)
+                        vv.push_back(i);
+                    vs[k].push_back(std::move(vv));
+                }
+            }
+            measure(meter, [&] (int run) {
+                auto& vr = vs[run];
+                auto r = Vektor{};
+                for (auto i = 0u; i < concat_steps; ++i)
+                    r.concat(vr[i]);
+                return r;
+            });
+        };
+}
+
+template <typename Fn>
+auto benchmark_concat_incr_librrb(Fn maker)
+{
+    return
+        [=] (nonius::chronometer meter) {
+            auto n = meter.param<N>();
+            auto v = maker(n / concat_steps);
+            measure(meter, [&] {
+                    auto r = rrb_create();
+                    for (auto i = 0ul; i < concat_steps; ++i)
+                        r = rrb_concat(r, v);
+                    return r;
+                });
+        };
+}
+
+} // anonymous namespace
diff --git a/third_party/immer/benchmark/vector/drop.hpp b/third_party/immer/benchmark/vector/drop.hpp
new file mode 100644
index 0000000000..0a525f67a5
--- /dev/null
+++ b/third_party/immer/benchmark/vector/drop.hpp
@@ -0,0 +1,142 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include "benchmark/vector/common.hpp"
+
+namespace {
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_drop()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            for (auto i = 0u; i < n; ++i)
+                (void) v.drop(i);
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_drop_lin()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v;
+            for (auto i = 0u; i < n; ++i)
+                r = r.drop(1);
+            return r;
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_drop_move()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v;
+            for (auto i = 0u; i < n; ++i)
+                r = std::move(r).drop(1);
+            return r;
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_drop_mut()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto vv = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            vv = PushFn{}(std::move(vv), i);
+
+        measure(meter, [&] {
+            auto v = vv.transient();
+            for (auto i = 0u; i < n; ++i)
+                (void) v.drop(1);
+        });
+    };
+}
+
+template <typename Fn>
+auto benchmark_drop_librrb(Fn make)
+{
+    return [=] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        auto v = make(n);
+        measure(meter, [&] {
+                for (auto i = 0u; i < n; ++i)
+                    rrb_slice(v, i, n);
+            });
+    };
+}
+
+template <typename Fn>
+auto benchmark_drop_lin_librrb(Fn make)
+{
+    return [=] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        auto v = make(n);
+        measure(meter, [&] {
+                auto r = v;
+                for (auto i = 0u; i < n; ++i)
+                    r = rrb_slice(r, 1, n);
+                return r;
+            });
+    };
+}
+
+template <typename Fn>
+auto benchmark_drop_mut_librrb(Fn make)
+{
+    return [=] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        auto v = make(n);
+        measure(meter, [&] {
+                auto r = rrb_to_transient(v);
+                for (auto i = 0u; i < n; ++i)
+                    r = transient_rrb_slice(r, 1, n);
+                return r;
+            });
+    };
+}
+
+} // anonymous namespace
diff --git a/third_party/immer/benchmark/vector/misc/access.cpp b/third_party/immer/benchmark/vector/misc/access.cpp
new file mode 100644
index 0000000000..9a00266a87
--- /dev/null
+++ b/third_party/immer/benchmark/vector/misc/access.cpp
@@ -0,0 +1,94 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/access.hpp"
+
+#include <immer/algorithm.hpp>
+#include <immer/array.hpp>
+#include <immer/flex_vector.hpp>
+#include <immer/vector.hpp>
+
+#if IMMER_BENCHMARK_EXPERIMENTAL
+#include <immer/experimental/dvektor.hpp>
+#endif
+
+#if IMMER_BENCHMARK_STEADY
+#define QUARK_ASSERT_ON 0
+#include <steady/steady_vector.h>
+#endif
+
+#include <vector>
+#include <list>
+#include <numeric>
+
+NONIUS_BENCHMARK("std::vector", benchmark_access_iter_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("std::vector/idx", benchmark_access_idx_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("std::vector/random", benchmark_access_random_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("std::list", benchmark_access_iter_std<std::list<unsigned>>())
+
+#if IMMER_BENCHMARK_LIBRRB
+NONIUS_BENCHMARK("librrb", benchmark_access_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("librrb/F", benchmark_access_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("librrb/random", benchmark_access_random_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("librrb/F/random", benchmark_access_random_librrb(make_librrb_vector_f))
+#endif
+
+NONIUS_BENCHMARK("flex/5B",     benchmark_access_iter<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex/F/5B",   benchmark_access_iter<immer::flex_vector<unsigned,def_memory,5>,push_front_fn>())
+NONIUS_BENCHMARK("vector/4B",   benchmark_access_iter<immer::vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("vector/5B",   benchmark_access_iter<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/6B",   benchmark_access_iter<immer::vector<unsigned,def_memory,6>>())
+
+#if IMMER_BENCHMARK_EXPERIMENTAL
+NONIUS_BENCHMARK("dvektor/4B",  benchmark_access_iter<immer::dvektor<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("dvektor/5B",  benchmark_access_iter<immer::dvektor<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("dvektor/6B",  benchmark_access_iter<immer::dvektor<unsigned,def_memory,6>>())
+#endif
+
+#if IMMER_BENCHMARK_STEADY
+NONIUS_BENCHMARK("steady/idx",      benchmark_access_idx<steady::vector<unsigned>>())
+#endif
+
+NONIUS_BENCHMARK("flex/5B/idx",     benchmark_access_idx<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex/F/5B/idx",   benchmark_access_idx<immer::flex_vector<unsigned,def_memory,5>,push_front_fn>())
+NONIUS_BENCHMARK("vector/4B/idx",   benchmark_access_idx<immer::vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("vector/5B/idx",   benchmark_access_idx<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/6B/idx",   benchmark_access_idx<immer::vector<unsigned,def_memory,6>>())
+#if IMMER_BENCHMARK_EXPERIMENTAL
+NONIUS_BENCHMARK("dvektor/4B/idx",  benchmark_access_idx<immer::dvektor<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("dvektor/5B/idx",  benchmark_access_idx<immer::dvektor<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("dvektor/6B/idx",  benchmark_access_idx<immer::dvektor<unsigned,def_memory,6>>())
+#endif
+
+NONIUS_BENCHMARK("flex/5B/reduce_i", benchmark_access_reduce_range<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/5B/reduce_i", benchmark_access_reduce_range<immer::vector<unsigned,def_memory,5>>())
+
+NONIUS_BENCHMARK("flex/5B/reduce",   benchmark_access_reduce<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex/F/5B/reduce", benchmark_access_reduce<immer::flex_vector<unsigned,def_memory,5>,push_front_fn>())
+NONIUS_BENCHMARK("vector/4B/reduce", benchmark_access_reduce<immer::vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("vector/5B/reduce", benchmark_access_reduce<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/6B/reduce", benchmark_access_reduce<immer::vector<unsigned,def_memory,6>>())
+
+#if IMMER_BENCHMARK_STEADY
+NONIUS_BENCHMARK("steady/random",      benchmark_access_random<steady::vector<unsigned>>())
+#endif
+
+NONIUS_BENCHMARK("flex/5B/random",     benchmark_access_random<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex/F/5B/random",   benchmark_access_random<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
+NONIUS_BENCHMARK("vector/4B/random",   benchmark_access_random<immer::vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("vector/5B/random",   benchmark_access_random<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/6B/random",   benchmark_access_random<immer::vector<unsigned,def_memory,6>>())
+#if IMMER_BENCHMARK_EXPERIMENTAL
+NONIUS_BENCHMARK("dvektor/4B/random",  benchmark_access_random<immer::dvektor<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("dvektor/5B/random",  benchmark_access_random<immer::dvektor<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("dvektor/6B/random",  benchmark_access_random<immer::dvektor<unsigned,def_memory,6>>())
+#endif
+
+#if IMMER_BENCHMARK_BOOST_COROUTINE
+NONIUS_BENCHMARK("vector/5B/coro", benchmark_access_coro<immer::vector<unsigned,def_memory,5>>())
+#endif
diff --git a/third_party/immer/benchmark/vector/misc/assoc.cpp b/third_party/immer/benchmark/vector/misc/assoc.cpp
new file mode 100644
index 0000000000..2b3d6d76b9
--- /dev/null
+++ b/third_party/immer/benchmark/vector/misc/assoc.cpp
@@ -0,0 +1,119 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/assoc.hpp"
+
+#include <immer/array.hpp>
+#include <immer/flex_vector.hpp>
+#include <immer/flex_vector_transient.hpp>
+#include <immer/vector.hpp>
+#include <immer/vector_transient.hpp>
+
+#if IMMER_BENCHMARK_EXPERIMENTAL
+#include <immer/experimental/dvektor.hpp>
+#endif
+
+#include <immer/heap/gc_heap.hpp>
+#include <immer/refcount/no_refcount_policy.hpp>
+#include <immer/refcount/unsafe_refcount_policy.hpp>
+
+#include <vector>
+#include <list>
+
+#if IMMER_BENCHMARK_STEADY
+#define QUARK_ASSERT_ON 0
+#include <steady/steady_vector.h>
+#endif
+
+#if IMMER_BENCHMARK_LIBRRB
+extern "C" {
+#define restrict __restrict__
+#include <rrb.h>
+#undef restrict
+}
+#endif
+
+NONIUS_BENCHMARK("std::vector", benchmark_assoc_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("std::vector/random", benchmark_assoc_random_std<std::vector<unsigned>>())
+
+#if IMMER_BENCHMARK_LIBRRB
+NONIUS_BENCHMARK("librrb", benchmark_assoc_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("librrb/F", benchmark_assoc_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("librrb/random", benchmark_assoc_random_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("t/librrb", benchmark_assoc_mut_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("t/librrb/F", benchmark_assoc_mut_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("t/librrb/random", benchmark_assoc_mut_random_librrb(make_librrb_vector))
+#endif
+
+#if IMMER_BENCHMARK_STEADY
+NONIUS_BENCHMARK("steady",     benchmark_assoc<steady::vector<unsigned>, push_back_fn, store_fn>())
+#endif
+
+NONIUS_BENCHMARK("flex/5B",    benchmark_assoc<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex/F/5B",  benchmark_assoc<immer::flex_vector<unsigned,def_memory,5>,push_front_fn>())
+
+NONIUS_BENCHMARK("flex/GC",    benchmark_assoc<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("flex/F/GC",  benchmark_assoc<immer::flex_vector<unsigned,gc_memory,5>,push_front_fn>())
+NONIUS_BENCHMARK("flex/F/GCF", benchmark_assoc<immer::flex_vector<unsigned,gcf_memory,5>,push_front_fn>())
+
+NONIUS_BENCHMARK("flex_s/GC",  benchmark_assoc<immer::flex_vector<std::size_t,gc_memory,5>>())
+NONIUS_BENCHMARK("flex_s/F/GC",benchmark_assoc<immer::flex_vector<std::size_t,gc_memory,5>,push_front_fn>())
+NONIUS_BENCHMARK("flex_s/F/GCF",benchmark_assoc<immer::flex_vector<std::size_t,gcf_memory,5>,push_front_fn>())
+
+NONIUS_BENCHMARK("vector/4B",  benchmark_assoc<immer::vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("vector/5B",  benchmark_assoc<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/6B",  benchmark_assoc<immer::vector<unsigned,def_memory,6>>())
+
+NONIUS_BENCHMARK("vector/GC",  benchmark_assoc<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("vector/NO",  benchmark_assoc<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("vector/UN",  benchmark_assoc<immer::vector<unsigned,unsafe_memory,5>>())
+
+#if IMMER_BENCHMARK_EXPERIMENTAL
+NONIUS_BENCHMARK("dvektor/4B", benchmark_assoc<immer::dvektor<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("dvektor/5B", benchmark_assoc<immer::dvektor<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("dvektor/6B", benchmark_assoc<immer::dvektor<unsigned,def_memory,6>>())
+
+NONIUS_BENCHMARK("dvektor/GC", benchmark_assoc<immer::dvektor<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("dvektor/NO", benchmark_assoc<immer::dvektor<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("dvektor/UN", benchmark_assoc<immer::dvektor<unsigned,unsafe_memory,5>>())
+#endif
+
+NONIUS_BENCHMARK("array",      benchmark_assoc<immer::array<unsigned>>())
+
+#if IMMER_BENCHMARK_STEADY
+NONIUS_BENCHMARK("steady/random",      benchmark_assoc_random<steady::vector<unsigned>, push_back_fn, store_fn>())
+#endif
+
+NONIUS_BENCHMARK("flex/5B/random",     benchmark_assoc_random<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/4B/random",   benchmark_assoc_random<immer::vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("vector/5B/random",   benchmark_assoc_random<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/6B/random",   benchmark_assoc_random<immer::vector<unsigned,def_memory,6>>())
+#if IMMER_BENCHMARK_EXPERIMENTAL
+NONIUS_BENCHMARK("dvektor/4B/random",  benchmark_assoc_random<immer::dvektor<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("dvektor/5B/random",  benchmark_assoc_random<immer::dvektor<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("dvektor/6B/random",  benchmark_assoc_random<immer::dvektor<unsigned,def_memory,6>>())
+#endif
+NONIUS_BENCHMARK("array/random",       benchmark_assoc_random<immer::array<unsigned>>())
+
+NONIUS_BENCHMARK("t/vector/5B",  benchmark_assoc_mut<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("t/vector/GC",  benchmark_assoc_mut<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("t/vector/NO",  benchmark_assoc_mut<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("t/vector/UN",  benchmark_assoc_mut<immer::vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("t/flex/F/5B",  benchmark_assoc_mut<immer::flex_vector<unsigned,def_memory,5>,push_front_fn>())
+
+NONIUS_BENCHMARK("m/vector/5B",  benchmark_assoc_move<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("m/vector/GC",  benchmark_assoc_move<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("m/vector/NO",  benchmark_assoc_move<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("m/vector/UN",  benchmark_assoc_move<immer::vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("m/flex/F/5B",  benchmark_assoc_move<immer::flex_vector<unsigned,def_memory,5>,push_front_fn>())
+
+NONIUS_BENCHMARK("t/vector/5B/random",  benchmark_assoc_mut_random<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("t/vector/GC/random",  benchmark_assoc_mut_random<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("t/vector/NO/random",  benchmark_assoc_mut_random<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("t/vector/UN/random",  benchmark_assoc_mut_random<immer::vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("t/flex/F/5B/random",  benchmark_assoc_mut_random<immer::flex_vector<unsigned,def_memory,5>,push_front_fn>())
diff --git a/third_party/immer/benchmark/vector/misc/concat.cpp b/third_party/immer/benchmark/vector/misc/concat.cpp
new file mode 100644
index 0000000000..9bc10c5c23
--- /dev/null
+++ b/third_party/immer/benchmark/vector/misc/concat.cpp
@@ -0,0 +1,49 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/concat.hpp"
+
+#include <immer/flex_vector.hpp>
+#include <immer/flex_vector_transient.hpp>
+#include <immer/heap/gc_heap.hpp>
+#include <immer/refcount/no_refcount_policy.hpp>
+#include <immer/refcount/unsafe_refcount_policy.hpp>
+
+#if IMMER_BENCHMARK_LIBRRB
+extern "C" {
+#define restrict __restrict__
+#include <rrb.h>
+#undef restrict
+}
+#endif
+
+#if IMMER_BENCHMARK_LIBRRB
+NONIUS_BENCHMARK("librrb", benchmark_concat_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("librrb/F", benchmark_concat_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("i/librrb", benchmark_concat_incr_librrb(make_librrb_vector))
+#endif
+
+NONIUS_BENCHMARK("flex/4B", benchmark_concat<immer::flex_vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("flex/5B", benchmark_concat<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex/6B", benchmark_concat<immer::flex_vector<unsigned,def_memory,6>>())
+NONIUS_BENCHMARK("flex/GC", benchmark_concat<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("flex_s/GC", benchmark_concat<immer::flex_vector<std::size_t,gc_memory,5>>())
+NONIUS_BENCHMARK("flex/NO", benchmark_concat<immer::flex_vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("flex/UN", benchmark_concat<immer::flex_vector<unsigned,unsafe_memory,5>>())
+
+NONIUS_BENCHMARK("flex/F/5B", benchmark_concat<immer::flex_vector<unsigned,def_memory,5>,push_front_fn>())
+NONIUS_BENCHMARK("flex/F/GC", benchmark_concat<immer::flex_vector<unsigned,gc_memory,5>,push_front_fn>())
+NONIUS_BENCHMARK("flex_s/F/GC", benchmark_concat<immer::flex_vector<std::size_t,gc_memory,5>,push_front_fn>())
+
+NONIUS_BENCHMARK("i/flex/GC", benchmark_concat_incr<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("i/flex_s/GC", benchmark_concat_incr<immer::flex_vector<std::size_t,gc_memory,5>>())
+NONIUS_BENCHMARK("i/flex/5B", benchmark_concat_incr<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("i/flex/UN", benchmark_concat_incr<immer::flex_vector<unsigned,unsafe_memory,5>>())
+
+NONIUS_BENCHMARK("m/flex/GC", benchmark_concat_incr_mut<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("m/flex_s/GC", benchmark_concat_incr_mut<immer::flex_vector<std::size_t,gc_memory,5>>())
diff --git a/third_party/immer/benchmark/vector/misc/drop.cpp b/third_party/immer/benchmark/vector/misc/drop.cpp
new file mode 100644
index 0000000000..c2ca48390b
--- /dev/null
+++ b/third_party/immer/benchmark/vector/misc/drop.cpp
@@ -0,0 +1,63 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/drop.hpp"
+
+#include <immer/flex_vector.hpp>
+#include <immer/flex_vector_transient.hpp>
+#include <immer/heap/gc_heap.hpp>
+#include <immer/refcount/no_refcount_policy.hpp>
+#include <immer/refcount/unsafe_refcount_policy.hpp>
+
+#if IMMER_BENCHMARK_LIBRRB
+extern "C" {
+#define restrict __restrict__
+#include <rrb.h>
+#undef restrict
+}
+#endif
+
+#if IMMER_BENCHMARK_LIBRRB
+NONIUS_BENCHMARK("librrb", benchmark_drop_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("librrb/F", benchmark_drop_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("l/librrb", benchmark_drop_lin_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("l/librrb/F", benchmark_drop_lin_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("t/librrb", benchmark_drop_mut_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("t/librrb/F", benchmark_drop_mut_librrb(make_librrb_vector_f))
+#endif
+
+NONIUS_BENCHMARK("flex/4B", benchmark_drop<immer::flex_vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("flex/5B", benchmark_drop<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex/6B", benchmark_drop<immer::flex_vector<unsigned,def_memory,6>>())
+NONIUS_BENCHMARK("flex/GC", benchmark_drop<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("flex/NO", benchmark_drop<immer::flex_vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("flex/UN", benchmark_drop<immer::flex_vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("flex_s/GC", benchmark_drop<immer::flex_vector<std::size_t,gc_memory,5>>())
+
+NONIUS_BENCHMARK("flex/F/5B", benchmark_drop<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
+NONIUS_BENCHMARK("flex/F/GC", benchmark_drop<immer::flex_vector<unsigned,gc_memory,5>, push_front_fn>())
+NONIUS_BENCHMARK("flex/F/GCF", benchmark_drop<immer::flex_vector<unsigned,gcf_memory,5>, push_front_fn>())
+NONIUS_BENCHMARK("flex_s/F/GC", benchmark_drop<immer::flex_vector<std::size_t,gc_memory,5>, push_front_fn>())
+
+NONIUS_BENCHMARK("l/flex/5B", benchmark_drop_lin<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("l/flex/GC", benchmark_drop_lin<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("l/flex/NO", benchmark_drop_lin<immer::flex_vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("l/flex/UN", benchmark_drop_lin<immer::flex_vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("l/flex/F/5B", benchmark_drop_lin<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
+
+NONIUS_BENCHMARK("m/flex/5B", benchmark_drop_move<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("m/flex/GC", benchmark_drop_move<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("m/flex/NO", benchmark_drop_move<immer::flex_vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("m/flex/UN", benchmark_drop_move<immer::flex_vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("m/flex/F/5B", benchmark_drop_move<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
+
+NONIUS_BENCHMARK("t/flex/5B", benchmark_drop_mut<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("t/flex/GC", benchmark_drop_mut<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("t/flex/NO", benchmark_drop_mut<immer::flex_vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("t/flex/UN", benchmark_drop_mut<immer::flex_vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("t/flex/F/5B", benchmark_drop_mut<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
diff --git a/third_party/immer/benchmark/vector/misc/push-front.cpp b/third_party/immer/benchmark/vector/misc/push-front.cpp
new file mode 100644
index 0000000000..48b98c8ee9
--- /dev/null
+++ b/third_party/immer/benchmark/vector/misc/push-front.cpp
@@ -0,0 +1,30 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/push_front.hpp"
+
+#include <immer/flex_vector.hpp>
+
+#if IMMER_BENCHMARK_LIBRRB
+extern "C" {
+#define restrict __restrict__
+#include <rrb.h>
+#undef restrict
+}
+#endif
+
+#if IMMER_BENCHMARK_LIBRRB
+NONIUS_BENCHMARK("librrb", benchmark_push_front_librrb)
+#endif
+NONIUS_BENCHMARK("flex/4B", bechmark_push_front<immer::flex_vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("flex/5B", bechmark_push_front<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex/6B", bechmark_push_front<immer::flex_vector<unsigned,def_memory,6>>())
+NONIUS_BENCHMARK("flex/GC", bechmark_push_front<immer::flex_vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("flex_s/GC", bechmark_push_front<immer::flex_vector<std::size_t,gc_memory,5>>())
+NONIUS_BENCHMARK("flex/NO", bechmark_push_front<immer::flex_vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("flex/UN", bechmark_push_front<immer::flex_vector<unsigned,unsafe_memory,5>>())
diff --git a/third_party/immer/benchmark/vector/misc/push.cpp b/third_party/immer/benchmark/vector/misc/push.cpp
new file mode 100644
index 0000000000..98f57600bd
--- /dev/null
+++ b/third_party/immer/benchmark/vector/misc/push.cpp
@@ -0,0 +1,83 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/push.hpp"
+
+#include <immer/array.hpp>
+#include <immer/flex_vector.hpp>
+#include <immer/vector_transient.hpp>
+#include <immer/vector.hpp>
+
+#if IMMER_BENCHMARK_EXPERIMENTAL
+#include <immer/experimental/dvektor.hpp>
+#endif
+
+#include <immer/heap/gc_heap.hpp>
+#include <immer/refcount/no_refcount_policy.hpp>
+#include <immer/refcount/unsafe_refcount_policy.hpp>
+
+#include <vector>
+#include <list>
+#include <numeric>
+
+#if IMMER_BENCHMARK_STEADY
+#define QUARK_ASSERT_ON 0
+#include <steady/steady_vector.h>
+#endif
+
+#if IMMER_BENCHMARK_LIBRRB
+extern "C" {
+#define restrict __restrict__
+#include <rrb.h>
+#undef restrict
+}
+#endif
+
+#if IMMER_BENCHMARK_LIBRRB
+NONIUS_BENCHMARK("librrb", benchmark_push_librrb)
+NONIUS_BENCHMARK("t/librrb", benchmark_push_mut_librrb)
+#endif
+
+NONIUS_BENCHMARK("std::vector", benchmark_push_mut_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("std::list",   benchmark_push_mut_std<std::list<unsigned>>())
+
+NONIUS_BENCHMARK("m/vector/5B", benchmark_push_move<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("m/vector/GC", benchmark_push_move<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("m/vector/NO", benchmark_push_move<immer::vector<unsigned,basic_memory,5>>())
+
+NONIUS_BENCHMARK("t/vector/5B", benchmark_push_mut<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("t/vector/GC", benchmark_push_mut<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("t/vector/NO", benchmark_push_mut<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("t/vector/UN", benchmark_push_mut<immer::vector<unsigned,unsafe_memory,5>>())
+
+NONIUS_BENCHMARK("flex/5B",    benchmark_push<immer::flex_vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("flex_s/GC",  benchmark_push<immer::flex_vector<std::size_t,gc_memory,5>>())
+
+NONIUS_BENCHMARK("vector/4B",  benchmark_push<immer::vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("vector/5B",  benchmark_push<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/6B",  benchmark_push<immer::vector<unsigned,def_memory,6>>())
+
+NONIUS_BENCHMARK("vector/GC",  benchmark_push<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("vector/NO",  benchmark_push<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("vector/UN",  benchmark_push<immer::vector<unsigned,unsafe_memory,5>>())
+
+#if IMMER_BENCHMARK_EXPERIMENTAL
+NONIUS_BENCHMARK("dvektor/4B", benchmark_push<immer::dvektor<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("dvektor/5B", benchmark_push<immer::dvektor<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("dvektor/6B", benchmark_push<immer::dvektor<unsigned,def_memory,6>>())
+
+NONIUS_BENCHMARK("dvektor/GC", benchmark_push<immer::dvektor<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("dvektor/NO", benchmark_push<immer::dvektor<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("dvektor/UN", benchmark_push<immer::dvektor<unsigned,unsafe_memory,5>>())
+#endif
+
+NONIUS_BENCHMARK("array",      benchmark_push<immer::array<unsigned>>())
+
+#if IMMER_BENCHMARK_STEADY
+NONIUS_BENCHMARK("steady",     benchmark_push<steady::vector<unsigned>>())
+#endif
diff --git a/third_party/immer/benchmark/vector/misc/take.cpp b/third_party/immer/benchmark/vector/misc/take.cpp
new file mode 100644
index 0000000000..78f0e958db
--- /dev/null
+++ b/third_party/immer/benchmark/vector/misc/take.cpp
@@ -0,0 +1,65 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/take.hpp"
+
+#include <immer/vector.hpp>
+#include <immer/flex_vector.hpp>
+#include <immer/vector_transient.hpp>
+#include <immer/flex_vector_transient.hpp>
+#include <immer/heap/gc_heap.hpp>
+#include <immer/refcount/no_refcount_policy.hpp>
+#include <immer/refcount/unsafe_refcount_policy.hpp>
+
+#if IMMER_BENCHMARK_LIBRRB
+extern "C" {
+#define restrict __restrict__
+#include <rrb.h>
+#undef restrict
+}
+#endif
+
+#if IMMER_BENCHMARK_LIBRRB
+NONIUS_BENCHMARK("librrb", benchmark_take_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("librrb/F", benchmark_take_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("l/librrb", benchmark_take_lin_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("l/librrb/F", benchmark_take_lin_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("t/librrb", benchmark_take_mut_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("t/librrb/F", benchmark_take_mut_librrb(make_librrb_vector_f))
+#endif
+
+NONIUS_BENCHMARK("vector/4B", benchmark_take<immer::vector<unsigned,def_memory,4>>())
+NONIUS_BENCHMARK("vector/5B", benchmark_take<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("vector/6B", benchmark_take<immer::vector<unsigned,def_memory,6>>())
+NONIUS_BENCHMARK("vector/GC", benchmark_take<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("vector/NO", benchmark_take<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("vector/UN", benchmark_take<immer::vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("vector_s/GC", benchmark_take<immer::vector<std::size_t,gc_memory,5>>())
+
+NONIUS_BENCHMARK("flex/F/5B", benchmark_take<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
+NONIUS_BENCHMARK("flex/F/GC", benchmark_take<immer::flex_vector<unsigned,gc_memory,5>, push_front_fn>())
+NONIUS_BENCHMARK("flex/F/GCF", benchmark_take<immer::flex_vector<unsigned,gcf_memory,5>, push_front_fn>())
+NONIUS_BENCHMARK("flex_s/F/GC", benchmark_take<immer::flex_vector<std::size_t,gc_memory,5>, push_front_fn>())
+
+NONIUS_BENCHMARK("l/vector/5B", benchmark_take_lin<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("l/vector/GC", benchmark_take_lin<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("l/vector/NO", benchmark_take_lin<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("l/vector/UN", benchmark_take_lin<immer::vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("l/flex/F/5B", benchmark_take_lin<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
+
+NONIUS_BENCHMARK("m/vector/5B", benchmark_take_move<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("m/vector/GC", benchmark_take_move<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("m/vector/NO", benchmark_take_move<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("m/vector/UN", benchmark_take_move<immer::vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("m/flex/F/5B", benchmark_take_move<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
+
+NONIUS_BENCHMARK("t/vector/5B", benchmark_take_mut<immer::vector<unsigned,def_memory,5>>())
+NONIUS_BENCHMARK("t/vector/GC", benchmark_take_mut<immer::vector<unsigned,gc_memory,5>>())
+NONIUS_BENCHMARK("t/vector/NO", benchmark_take_mut<immer::vector<unsigned,basic_memory,5>>())
+NONIUS_BENCHMARK("t/vector/UN", benchmark_take_mut<immer::vector<unsigned,unsafe_memory,5>>())
+NONIUS_BENCHMARK("t/flex/F/5B", benchmark_take_mut<immer::flex_vector<unsigned,def_memory,5>, push_front_fn>())
diff --git a/third_party/immer/benchmark/vector/paper/access.cpp b/third_party/immer/benchmark/vector/paper/access.cpp
new file mode 100644
index 0000000000..db677a1adb
--- /dev/null
+++ b/third_party/immer/benchmark/vector/paper/access.cpp
@@ -0,0 +1,31 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/access.hpp"
+#include <immer/flex_vector.hpp>
+#include <chunkedseq/chunkedseq.hpp>
+
+NONIUS_BENCHMARK("idx owrs", benchmark_access_idx<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("idx librrb", benchmark_access_librrb(make_librrb_vector))
+NONIUS_BENCHMARK("idx relaxed owrs", benchmark_access_idx<immer::flex_vector<unsigned,def_memory>,push_front_fn>())
+NONIUS_BENCHMARK("idx relaxed librrb", benchmark_access_librrb(make_librrb_vector_f))
+NONIUS_BENCHMARK("idx std::vector", benchmark_access_idx_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("idx chunkedseq32", benchmark_access_idx_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned, 32>>())
+NONIUS_BENCHMARK("idx chunkedseq", benchmark_access_idx_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned>>())
+
+NONIUS_BENCHMARK("iter orws", benchmark_access_iter<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("iter relaxed orws", benchmark_access_iter<immer::flex_vector<unsigned,def_memory>,push_front_fn>())
+NONIUS_BENCHMARK("iter chunkedseq32", benchmark_access_iter_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned, 32>>())
+NONIUS_BENCHMARK("iter chunkedseq", benchmark_access_iter_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned>>())
+
+NONIUS_BENCHMARK("reduce owrs", benchmark_access_reduce<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("reduce relaxed owrs", benchmark_access_reduce<immer::flex_vector<unsigned,def_memory>,push_front_fn>())
+NONIUS_BENCHMARK("reduce chunkedseq32", benchmark_access_reduce_chunkedseq<pasl::data::chunkedseq::bootstrapped::deque<unsigned, 32>>())
+NONIUS_BENCHMARK("reduce chunkedseq", benchmark_access_reduce_chunkedseq<pasl::data::chunkedseq::bootstrapped::deque<unsigned>>())
+NONIUS_BENCHMARK("reduce std::vector", benchmark_access_iter_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("reduce std::list", benchmark_access_iter_std<std::list<unsigned>>())
diff --git a/third_party/immer/benchmark/vector/paper/assoc-random.cpp b/third_party/immer/benchmark/vector/paper/assoc-random.cpp
new file mode 100644
index 0000000000..becd4dc0c5
--- /dev/null
+++ b/third_party/immer/benchmark/vector/paper/assoc-random.cpp
@@ -0,0 +1,40 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/assoc.hpp"
+#include <immer/flex_vector.hpp>
+#include <immer/flex_vector_transient.hpp>
+#include <chunkedseq/chunkedseq.hpp>
+
+NONIUS_BENCHMARK("ours/basic",   benchmark_assoc_random<immer::flex_vector<unsigned,basic_memory>>())
+NONIUS_BENCHMARK("ours/safe",    benchmark_assoc_random<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("ours/unsafe",  benchmark_assoc_random<immer::flex_vector<unsigned,unsafe_memory>>())
+NONIUS_BENCHMARK("ours/gc",      benchmark_assoc_random<immer::flex_vector<unsigned,gc_memory>>())
+NONIUS_BENCHMARK("librrb",       benchmark_assoc_random_librrb(make_librrb_vector))
+
+NONIUS_BENCHMARK("relaxed ours/basic",   benchmark_assoc_random<immer::flex_vector<unsigned,basic_memory>,push_front_fn>())
+NONIUS_BENCHMARK("relaxed ours/safe",    benchmark_assoc_random<immer::flex_vector<unsigned,def_memory>,push_front_fn>())
+NONIUS_BENCHMARK("relaxed ours/unsafe",  benchmark_assoc_random<immer::flex_vector<unsigned,unsafe_memory>,push_front_fn>())
+NONIUS_BENCHMARK("relaxed ours/gc",      benchmark_assoc_random<immer::flex_vector<unsigned,gc_memory>,push_front_fn>())
+NONIUS_BENCHMARK("relaxed librrb",       benchmark_assoc_random_librrb(make_librrb_vector_f))
+
+NONIUS_BENCHMARK("transient ours/basic",   benchmark_assoc_mut_random<immer::flex_vector<unsigned,basic_memory>>())
+NONIUS_BENCHMARK("transient ours/safe",    benchmark_assoc_mut_random<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("transient ours/unsafe",  benchmark_assoc_mut_random<immer::flex_vector<unsigned,unsafe_memory>>())
+NONIUS_BENCHMARK("transient ours/gc",      benchmark_assoc_mut_random<immer::flex_vector<unsigned,gc_memory>>())
+NONIUS_BENCHMARK("transient librrb",       benchmark_assoc_mut_random_librrb(make_librrb_vector))
+
+NONIUS_BENCHMARK("transient relaxed ours/basic",   benchmark_assoc_mut_random<immer::flex_vector<unsigned,basic_memory>,push_back_fn>())
+NONIUS_BENCHMARK("transient relaxed ours/safe",    benchmark_assoc_mut_random<immer::flex_vector<unsigned,def_memory>,push_back_fn>())
+NONIUS_BENCHMARK("transient relaxed ours/unsafe",  benchmark_assoc_mut_random<immer::flex_vector<unsigned,unsafe_memory>,push_back_fn>())
+NONIUS_BENCHMARK("transient relaxed ours/gc",      benchmark_assoc_mut_random<immer::flex_vector<unsigned,gc_memory>,push_back_fn>())
+NONIUS_BENCHMARK("transient relaxed librrb",       benchmark_assoc_mut_random_librrb(make_librrb_vector_f))
+
+NONIUS_BENCHMARK("transient std::vector",  benchmark_assoc_random_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("transient chunkedseq32", benchmark_assoc_random_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned>>())
+NONIUS_BENCHMARK("transient chunkedseq",   benchmark_assoc_random_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned, 32>>())
diff --git a/third_party/immer/benchmark/vector/paper/assoc.cpp b/third_party/immer/benchmark/vector/paper/assoc.cpp
new file mode 100644
index 0000000000..fe682ce749
--- /dev/null
+++ b/third_party/immer/benchmark/vector/paper/assoc.cpp
@@ -0,0 +1,40 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/assoc.hpp"
+#include <immer/flex_vector.hpp>
+#include <immer/flex_vector_transient.hpp>
+#include <chunkedseq/chunkedseq.hpp>
+
+NONIUS_BENCHMARK("ours/basic",   benchmark_assoc<immer::flex_vector<unsigned,basic_memory>>())
+NONIUS_BENCHMARK("ours/safe",    benchmark_assoc<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("ours/unsafe",  benchmark_assoc<immer::flex_vector<unsigned,unsafe_memory>>())
+NONIUS_BENCHMARK("ours/gc",      benchmark_assoc<immer::flex_vector<unsigned,gc_memory>>())
+NONIUS_BENCHMARK("librrb",       benchmark_assoc_librrb(make_librrb_vector))
+
+NONIUS_BENCHMARK("relaxed ours/basic",   benchmark_assoc<immer::flex_vector<unsigned,basic_memory>,push_front_fn>())
+NONIUS_BENCHMARK("relaxed ours/safe",    benchmark_assoc<immer::flex_vector<unsigned,def_memory>,push_front_fn>())
+NONIUS_BENCHMARK("relaxed ours/unsafe",  benchmark_assoc<immer::flex_vector<unsigned,unsafe_memory>,push_front_fn>())
+NONIUS_BENCHMARK("relaxed ours/gc",      benchmark_assoc<immer::flex_vector<unsigned,gc_memory>,push_front_fn>())
+NONIUS_BENCHMARK("relaxed librrb",       benchmark_assoc_librrb(make_librrb_vector_f))
+
+NONIUS_BENCHMARK("transient ours/basic",   benchmark_assoc_mut<immer::flex_vector<unsigned,basic_memory>>())
+NONIUS_BENCHMARK("transient ours/safe",    benchmark_assoc_mut<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("transient ours/unsafe",  benchmark_assoc_mut<immer::flex_vector<unsigned,unsafe_memory>>())
+NONIUS_BENCHMARK("transient ours/gc",      benchmark_assoc_mut<immer::flex_vector<unsigned,gc_memory>>())
+NONIUS_BENCHMARK("transient librrb",       benchmark_assoc_mut_librrb(make_librrb_vector))
+
+NONIUS_BENCHMARK("transient relaxed ours/basic",   benchmark_assoc_mut<immer::flex_vector<unsigned,basic_memory>,push_back_fn>())
+NONIUS_BENCHMARK("transient relaxed ours/safe",    benchmark_assoc_mut<immer::flex_vector<unsigned,def_memory>,push_back_fn>())
+NONIUS_BENCHMARK("transient relaxed ours/unsafe",  benchmark_assoc_mut<immer::flex_vector<unsigned,unsafe_memory>,push_back_fn>())
+NONIUS_BENCHMARK("transient relaxed ours/gc",      benchmark_assoc_mut<immer::flex_vector<unsigned,gc_memory>,push_back_fn>())
+NONIUS_BENCHMARK("transient relaxed librrb",       benchmark_assoc_mut_librrb(make_librrb_vector_f))
+
+NONIUS_BENCHMARK("transient std::vector",  benchmark_assoc_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("transient chunkedseq32", benchmark_assoc_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned, 32>>())
+NONIUS_BENCHMARK("transient chunkedseq",   benchmark_assoc_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned>>())
diff --git a/third_party/immer/benchmark/vector/paper/concat.cpp b/third_party/immer/benchmark/vector/paper/concat.cpp
new file mode 100644
index 0000000000..af9b3d20ed
--- /dev/null
+++ b/third_party/immer/benchmark/vector/paper/concat.cpp
@@ -0,0 +1,22 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/concat.hpp"
+#include <immer/flex_vector.hpp>
+#include <immer/flex_vector_transient.hpp>
+#include <chunkedseq/chunkedseq.hpp>
+
+NONIUS_BENCHMARK("ours/basic",   benchmark_concat_incr<immer::flex_vector<unsigned,basic_memory>>())
+NONIUS_BENCHMARK("ours/safe",    benchmark_concat_incr<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("ours/unsafe",  benchmark_concat_incr<immer::flex_vector<unsigned,unsafe_memory>>())
+NONIUS_BENCHMARK("ours/gc",      benchmark_concat_incr<immer::flex_vector<unsigned,gc_memory>>())
+NONIUS_BENCHMARK("librrb",       benchmark_concat_incr_librrb(make_librrb_vector))
+
+NONIUS_BENCHMARK("transient ours/gc",      benchmark_concat_incr_mut<immer::flex_vector<unsigned,gc_memory>>())
+NONIUS_BENCHMARK("transient chunkedseq32", benchmark_concat_incr_chunkedseq<pasl::data::chunkedseq::bootstrapped::deque<unsigned, 32>>())
+NONIUS_BENCHMARK("transient chunkedseq",   benchmark_concat_incr_chunkedseq<pasl::data::chunkedseq::bootstrapped::deque<unsigned>>())
diff --git a/third_party/immer/benchmark/vector/paper/push.cpp b/third_party/immer/benchmark/vector/paper/push.cpp
new file mode 100644
index 0000000000..7c467985bb
--- /dev/null
+++ b/third_party/immer/benchmark/vector/paper/push.cpp
@@ -0,0 +1,28 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#include "benchmark/vector/push.hpp"
+#include <immer/flex_vector.hpp>
+#include <immer/flex_vector_transient.hpp>
+#include <chunkedseq/chunkedseq.hpp>
+
+NONIUS_BENCHMARK("ours/basic",   benchmark_push<immer::flex_vector<unsigned,basic_memory>>())
+NONIUS_BENCHMARK("ours/safe",    benchmark_push<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("ours/unsafe",  benchmark_push<immer::flex_vector<unsigned,unsafe_memory>>())
+NONIUS_BENCHMARK("ours/gc",      benchmark_push<immer::flex_vector<unsigned,gc_memory>>())
+NONIUS_BENCHMARK("librrb",       benchmark_push_librrb)
+
+NONIUS_BENCHMARK("transient ours/basic",   benchmark_push_mut<immer::flex_vector<unsigned,basic_memory>>())
+NONIUS_BENCHMARK("transient ours/safe",    benchmark_push_mut<immer::flex_vector<unsigned,def_memory>>())
+NONIUS_BENCHMARK("transient ours/unsafe",  benchmark_push_mut<immer::flex_vector<unsigned,unsafe_memory>>())
+NONIUS_BENCHMARK("transient ours/gc",      benchmark_push_mut<immer::flex_vector<unsigned,gc_memory>>())
+NONIUS_BENCHMARK("transient librrb",       benchmark_push_mut_librrb)
+NONIUS_BENCHMARK("transient std::vector",  benchmark_push_mut_std<std::vector<unsigned>>())
+NONIUS_BENCHMARK("transient std::list",    benchmark_push_mut_std<std::list<unsigned>>())
+NONIUS_BENCHMARK("transient chunkedseq32", benchmark_push_mut_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned, 32>>())
+NONIUS_BENCHMARK("transient chunkedseq",   benchmark_push_mut_std<pasl::data::chunkedseq::bootstrapped::deque<unsigned>>())
diff --git a/third_party/immer/benchmark/vector/push.hpp b/third_party/immer/benchmark/vector/push.hpp
new file mode 100644
index 0000000000..83f128c8fc
--- /dev/null
+++ b/third_party/immer/benchmark/vector/push.hpp
@@ -0,0 +1,111 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include "benchmark/vector/common.hpp"
+
+namespace {
+
+template <typename Vektor>
+auto benchmark_push_mut_std()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        measure(meter, [&] {
+            auto v = Vektor{};
+            for (auto i = 0u; i < n; ++i)
+                v.push_back(i);
+            return v;
+        });
+    };
+}
+
+template <typename Vektor>
+auto benchmark_push_mut()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        measure(meter, [&] {
+            auto v = Vektor{}.transient();
+            for (auto i = 0u; i < n; ++i)
+                v.push_back(i);
+            return v;
+        });
+    };
+}
+
+template <typename Vektor>
+auto benchmark_push_move()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        measure(meter, [&] {
+            auto v = Vektor{};
+            for (auto i = 0u; i < n; ++i)
+                v = std::move(v).push_back(i);
+            return v;
+        });
+    };
+}
+
+template <typename Vektor>
+auto benchmark_push()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        if (n > get_limit<Vektor>{})
+            nonius::skip();
+
+        measure(meter, [&] {
+            auto v = Vektor{};
+            for (auto i = 0u; i < n; ++i)
+                v = v.push_back(i);
+            return v;
+        });
+    };
+}
+
+auto benchmark_push_librrb(nonius::chronometer meter)
+{
+    auto n = meter.param<N>();
+
+    measure(meter, [&] {
+        auto v = rrb_create();
+        for (auto i = 0u; i < n; ++i)
+            v = rrb_push(v, reinterpret_cast<void*>(i));
+        return v;
+    });
+}
+
+auto benchmark_push_mut_librrb(nonius::chronometer meter)
+{
+    auto n = meter.param<N>();
+
+    measure(meter, [&] {
+        auto v = rrb_to_transient(rrb_create());
+        for (auto i = 0u; i < n; ++i)
+            v = transient_rrb_push(v, reinterpret_cast<void*>(i));
+        return v;
+    });
+}
+
+} // anonymous namespace
diff --git a/third_party/immer/benchmark/vector/push_front.hpp b/third_party/immer/benchmark/vector/push_front.hpp
new file mode 100644
index 0000000000..25ccbab0f9
--- /dev/null
+++ b/third_party/immer/benchmark/vector/push_front.hpp
@@ -0,0 +1,46 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include "benchmark/vector/common.hpp"
+
+namespace {
+
+template <typename Vektor>
+auto bechmark_push_front()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        measure(meter, [&] {
+            auto v = Vektor{};
+            for (auto i = 0u; i < n; ++i)
+                v = v.push_front(i);
+            return v;
+        });
+    };
+}
+
+auto benchmark_push_front_librrb(nonius::chronometer meter)
+{
+    auto n = meter.param<N>();
+
+    measure(meter, [&] {
+        auto v = rrb_create();
+        for (auto i = 0u; i < n; ++i) {
+            auto f = rrb_push(rrb_create(),
+                              reinterpret_cast<void*>(i));
+            v = rrb_concat(f, v);
+        }
+        return v;
+    });
+}
+
+} // anonymous namespace
diff --git a/third_party/immer/benchmark/vector/take.hpp b/third_party/immer/benchmark/vector/take.hpp
new file mode 100644
index 0000000000..bce5aceb00
--- /dev/null
+++ b/third_party/immer/benchmark/vector/take.hpp
@@ -0,0 +1,144 @@
+//
+// immer: immutable data structures for C++
+// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
+//
+// This software is distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
+//
+
+#pragma once
+
+#include "benchmark/vector/common.hpp"
+
+namespace {
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_take()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            for (auto i = 0u; i < n; ++i)
+                (void) v.take(i);
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_take_lin()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v;
+            for (auto i = n; i > 0; --i)
+                r = r.take(i);
+            return r;
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_take_move()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto v = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            v = PushFn{}(std::move(v), i);
+
+        measure(meter, [&] {
+            auto r = v;
+            for (auto i = n; i > 0; --i)
+                r = std::move(r).take(i);
+            return r;
+        });
+    };
+}
+
+template <typename Vektor,
+          typename PushFn=push_back_fn>
+auto benchmark_take_mut()
+{
+    return [] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+
+        auto vv = Vektor{};
+        for (auto i = 0u; i < n; ++i)
+            vv = PushFn{}(std::move(vv), i);
+
+        measure(meter, [&] {
+            auto v = vv.transient();
+            for (auto i = n; i > 0; --i)
+                (void) v.take(i);
+        });
+    };
+}
+
+template <typename Fn>
+auto benchmark_take_librrb(Fn make)
+{
+    return [=] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        auto v = make(n);
+        measure(meter, [&] {
+                for (auto i = 0u; i < n; ++i)
+                    rrb_slice(v, 0, i);
+            });
+    };
+}
+
+template <typename Fn>
+auto benchmark_take_lin_librrb(Fn make)
+{
+    return [=] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        auto v = make(n);
+        measure(
+            meter, [&] {
+                auto r = v;
+                for (auto i = n; i > 0; --i)
+                    r = rrb_slice(r, 0, i);
+                return r;
+            });
+    };
+}
+
+template <typename Fn>
+auto benchmark_take_mut_librrb(Fn make)
+{
+    return [=] (nonius::chronometer meter)
+    {
+        auto n = meter.param<N>();
+        auto v = make(n);
+        measure(
+            meter, [&] {
+                auto r = rrb_to_transient(v);
+                for (auto i = n; i > 0; --i)
+                    r = transient_rrb_slice(r, 0, i);
+                return r;
+            });
+    };
+}
+
+} // anonymous namespace