Upgrade google-fruit to 45fa33d27da5a9b21471094f34e7f26c21e71f5b am: f54f09cdcd

Original change: undetermined

Change-Id: Ib499a3818937c8cf7f2efd1c4589d73b7cff2bfb
diff --git a/.travis.yml b/.travis.yml
index d111db3..2b7f4b8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,38 +10,38 @@
   fast_finish: true
   include:
   - compiler: gcc
-    env: COMPILER=gcc-9 UBUNTU=19.10 TEST=ReleasePlain
-    install: export OS=linux; export COMPILER='gcc-9'; export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+    env: COMPILER=gcc-10 UBUNTU=20.04 TEST=ReleasePlain
+    install: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
-    script: export OS=linux; export COMPILER='gcc-9'; export UBUNTU='19.10'; extras/scripts/postsubmit.sh
+    script: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.04'; extras/scripts/postsubmit.sh
       ReleasePlain
   - compiler: gcc
-    env: COMPILER=gcc-9 UBUNTU=19.10 TEST=DebugPlain
-    install: export OS=linux; export COMPILER='gcc-9'; export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+    env: COMPILER=gcc-10 UBUNTU=20.04 TEST=DebugPlain
+    install: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
-    script: export OS=linux; export COMPILER='gcc-9'; export UBUNTU='19.10'; extras/scripts/postsubmit.sh
+    script: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.04'; extras/scripts/postsubmit.sh
       DebugPlain
   - compiler: clang
-    env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=19.10 TEST=ReleasePlain
+    env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=20.04 TEST=ReleasePlain
     install: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+      export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
     script: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/postsubmit.sh ReleasePlain
+      export UBUNTU='20.04'; extras/scripts/postsubmit.sh ReleasePlain
   - compiler: clang
-    env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=19.10 TEST=DebugAsanUbsan
+    env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=20.04 TEST=DebugAsanUbsan
     install: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+      export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
     script: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/postsubmit.sh DebugAsanUbsan
+      export UBUNTU='20.04'; extras/scripts/postsubmit.sh DebugAsanUbsan
   - compiler: clang
-    env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=19.10 TEST=DebugPlain
+    env: COMPILER=clang-6.0 STL=libstdc++ UBUNTU=20.04 TEST=DebugPlain
     install: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+      export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
     script: export OS=linux; export COMPILER='clang-6.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/postsubmit.sh DebugPlain
+      export UBUNTU='20.04'; extras/scripts/postsubmit.sh DebugPlain
   - compiler: gcc
     env: COMPILER=bazel UBUNTU=18.04
     install: export OS=linux; export COMPILER='bazel'; export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh
@@ -49,45 +49,51 @@
     script: export OS=linux; export COMPILER='bazel'; export UBUNTU='18.04'; extras/scripts/postsubmit.sh
       DebugPlain
   - compiler: gcc
-    env: COMPILER=gcc-7 UBUNTU=19.10 TEST=ReleasePlain
-    install: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+    env: COMPILER=gcc-7 UBUNTU=20.04 TEST=ReleasePlain
+    install: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
-    script: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='19.10'; extras/scripts/postsubmit.sh
+    script: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.04'; extras/scripts/postsubmit.sh
       ReleasePlain
   - compiler: gcc
-    env: COMPILER=gcc-7 UBUNTU=19.10 TEST=DebugPlain
-    install: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+    env: COMPILER=gcc-7 UBUNTU=20.04 TEST=DebugAsanUbsan
+    install: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
-    script: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='19.10'; extras/scripts/postsubmit.sh
-      DebugPlain
+    script: export OS=linux; export COMPILER='gcc-7'; export UBUNTU='20.04'; extras/scripts/postsubmit.sh
+      DebugAsanUbsan
+  - compiler: gcc
+    env: COMPILER=gcc-10 UBUNTU=20.04 TEST=DebugAsanUbsan
+    install: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
+    os: linux
+    script: export OS=linux; export COMPILER='gcc-10'; export UBUNTU='20.04'; extras/scripts/postsubmit.sh
+      DebugAsanUbsan
   - compiler: clang
-    env: COMPILER=clang-10.0 STL=libstdc++ UBUNTU=19.10 TEST=ReleasePlain
+    env: COMPILER=clang-10.0 STL=libstdc++ UBUNTU=20.04 TEST=ReleasePlain
     install: export OS=linux; export COMPILER='clang-10.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+      export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
     script: export OS=linux; export COMPILER='clang-10.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/postsubmit.sh ReleasePlain
+      export UBUNTU='20.04'; extras/scripts/postsubmit.sh ReleasePlain
   - compiler: clang
-    env: COMPILER=clang-10.0 STL=libstdc++ UBUNTU=19.10 TEST=DebugAsanUbsan
+    env: COMPILER=clang-10.0 STL=libstdc++ UBUNTU=20.04 TEST=DebugAsanUbsan
     install: export OS=linux; export COMPILER='clang-10.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+      export UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
     script: export OS=linux; export COMPILER='clang-10.0'; export STL='libstdc++';
-      export UBUNTU='19.10'; extras/scripts/postsubmit.sh DebugAsanUbsan
+      export UBUNTU='20.04'; extras/scripts/postsubmit.sh DebugAsanUbsan
   - compiler: clang
-    env: COMPILER=clang-9.0 STL=libc++ UBUNTU=19.10 TEST=ReleasePlainNoPchNoClangTidy
-    install: export OS=linux; export COMPILER='clang-9.0'; export STL='libc++'; export
-      UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+    env: COMPILER=clang-10.0 STL=libc++ UBUNTU=20.04 TEST=ReleasePlain
+    install: export OS=linux; export COMPILER='clang-10.0'; export STL='libc++'; export
+      UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
-    script: export OS=linux; export COMPILER='clang-9.0'; export STL='libc++'; export
-      UBUNTU='19.10'; extras/scripts/postsubmit.sh ReleasePlainNoPchNoClangTidy
+    script: export OS=linux; export COMPILER='clang-10.0'; export STL='libc++'; export
+      UBUNTU='20.04'; extras/scripts/postsubmit.sh ReleasePlain
   - compiler: clang
-    env: COMPILER=clang-9.0 STL=libc++ UBUNTU=19.10 TEST=DebugAsanUbsanNoPchNoClangTidy
-    install: export OS=linux; export COMPILER='clang-9.0'; export STL='libc++'; export
-      UBUNTU='19.10'; extras/scripts/travis_ci_install_linux.sh
+    env: COMPILER=clang-10.0 STL=libc++ UBUNTU=20.04 TEST=DebugAsanUbsan
+    install: export OS=linux; export COMPILER='clang-10.0'; export STL='libc++'; export
+      UBUNTU='20.04'; extras/scripts/travis_ci_install_linux.sh
     os: linux
-    script: export OS=linux; export COMPILER='clang-9.0'; export STL='libc++'; export
-      UBUNTU='19.10'; extras/scripts/postsubmit.sh DebugAsanUbsanNoPchNoClangTidy
+    script: export OS=linux; export COMPILER='clang-10.0'; export STL='libc++'; export
+      UBUNTU='20.04'; extras/scripts/postsubmit.sh DebugAsanUbsan
   - compiler: gcc
     env: COMPILER=gcc-5 UBUNTU=18.04 TEST=ReleasePlain
     install: export OS=linux; export COMPILER='gcc-5'; export UBUNTU='18.04'; extras/scripts/travis_ci_install_linux.sh
@@ -261,29 +267,29 @@
     script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh
       DebugAsanUbsanNoClangTidy
   - compiler: clang
-    env: COMPILER=clang-default STL=libc++ TEST=ReleasePlainNoClangTidy
+    env: COMPILER=clang-default STL=libc++ TEST=ReleasePlainNoPchNoClangTidy
     install: export OS=osx; export COMPILER='clang-default'; export STL='libc++';
       travis_wait extras/scripts/travis_ci_install_osx.sh
     os: osx
-    osx_image: xcode11.4
+    osx_image: xcode11.3
     script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh
-      ReleasePlainNoClangTidy
+      ReleasePlainNoPchNoClangTidy
   - compiler: clang
-    env: COMPILER=clang-default STL=libc++ TEST=DebugAsanUbsanNoClangTidy
+    env: COMPILER=clang-default STL=libc++ TEST=DebugAsanUbsanNoPchNoClangTidy
     install: export OS=osx; export COMPILER='clang-default'; export STL='libc++';
       travis_wait extras/scripts/travis_ci_install_osx.sh
     os: osx
-    osx_image: xcode11.4
+    osx_image: xcode11.3
     script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh
-      DebugAsanUbsanNoClangTidy
+      DebugAsanUbsanNoPchNoClangTidy
   - compiler: clang
-    env: COMPILER=clang-default STL=libc++ TEST=DebugPlainNoClangTidy
+    env: COMPILER=clang-default STL=libc++ TEST=DebugPlainNoPchNoClangTidy
     install: export OS=osx; export COMPILER='clang-default'; export STL='libc++';
       travis_wait extras/scripts/travis_ci_install_osx.sh
     os: osx
-    osx_image: xcode11.4
+    osx_image: xcode11.3
     script: export OS=osx; export COMPILER='clang-default'; export STL='libc++'; extras/scripts/postsubmit.sh
-      DebugPlainNoClangTidy
+      DebugPlainNoPchNoClangTidy
 services:
 - docker
 sudo: required
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 524d1f3..d5b6a64 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.2)
 
-project(Fruit VERSION 3.4.0 LANGUAGES CXX)
+project(Fruit VERSION 3.5.0 LANGUAGES CXX)
 
 set(FRUIT_IS_BEING_BUILT_BY_CONAN FALSE CACHE BOOL "This is set in Conan builds.")
 if("${FRUIT_IS_BEING_BUILT_BY_CONAN}")
diff --git a/METADATA b/METADATA
index 264897b..999b035 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@
     type: GIT
     value: "https://github.com/google/fruit.git"
   }
-  version: "0ac041ff302faec7c8218989c86773613a621523"
+  version: "45fa33d27da5a9b21471094f34e7f26c21e71f5b"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 4
+    month: 6
     day: 1
   }
 }
diff --git a/appveyor.yml b/appveyor.yml
index eceb425..2406142 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -13,11 +13,6 @@
     VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build'
     ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX /DFRUIT_DEBUG /DFRUIT_EXTRA_DEBUG /D_ITERATOR_DEBUG_LEVEL=2" -T host=x64 -A x64'
     CONFIGURATION: Debug
-  - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
-    CMAKE_GENERATOR: 'Visual Studio 14 2015 Win64'
-    VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC'
-    ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX /DFRUIT_DEBUG /DFRUIT_EXTRA_DEBUG /D_ITERATOR_DEBUG_LEVEL=2" -T host=x64'
-    CONFIGURATION: Debug
   - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
     CMAKE_GENERATOR: 'Visual Studio 15 2017 Win64'
     VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build'
@@ -33,11 +28,6 @@
     VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build'
     ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64'
     CONFIGURATION: Release
-  - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
-    CMAKE_GENERATOR: 'Visual Studio 14 2015 Win64'
-    VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC'
-    ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64'
-    CONFIGURATION: Release
   - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
     CMAKE_GENERATOR: 'Visual Studio 16 2019'
     VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build'
@@ -48,11 +38,6 @@
     VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build'
     ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DBUILD_SHARED_LIBS=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64'
     CONFIGURATION: Release
-  - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
-    CMAKE_GENERATOR: 'Visual Studio 14 2015 Win64'
-    VCVARSALL_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC'
-    ADDITIONAL_CMAKE_ARGS: '-DFRUIT_USES_BOOST=False -DBUILD_SHARED_LIBS=False -DCMAKE_CXX_FLAGS="/WX" -T host=x64'
-    CONFIGURATION: Release
 
   - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
     MINGW_PATH: 'C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin'
diff --git a/cmake-modules/FindFruit.cmake b/cmake-modules/FindFruit.cmake
index a6155cd..3b4fc24 100644
--- a/cmake-modules/FindFruit.cmake
+++ b/cmake-modules/FindFruit.cmake
@@ -2,23 +2,23 @@
 # set(ENV{FRUIT_INSTALLED_DIR} "/path/to/fruit/build")
 
 find_path(FRUIT_INCLUDE_DIR fruit.h
-    HINTS (
-        FRUIT_INSTALLED_DIR
-        /usr
-        /usr/local
-    )
-    PATH_SUFFIXES include/fruit include fruit
-)
+        HINTS (
+            ${FRUIT_INSTALLED_DIR}
+            /usr
+            /usr/local
+            )
+        PATH_SUFFIXES include/fruit
+        )
 
 find_library(FRUIT_LIBRARY
-  NAMES fruit
-  HINTS (
-      FRUIT_INSTALLED_DIR
-      /usr
-      /usr/local
-  )
-  PATH_SUFFIXES lib ${FRUIT_INSTALLED_DIR}
-)
+        NAMES fruit
+        HINTS (
+            ${FRUIT_INSTALLED_DIR}
+            /usr
+            /usr/local
+            )
+        PATH_SUFFIXES lib lib64
+        )
 
 include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(fruit DEFAULT_MSG FRUIT_LIBRARY FRUIT_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Fruit DEFAULT_MSG FRUIT_LIBRARY FRUIT_INCLUDE_DIR)
diff --git a/conanfile.py b/conanfile.py
index 9d2c664..9c87a68 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -5,7 +5,7 @@
 
 class FruitConan(ConanFile):
     name = "fruit"
-    version = "3.4.0"
+    version = "3.5.0"
     license = "Apache"
     url = "https://github.com/google/fruit"
     homepage = "https://github.com/google/fruit"
diff --git a/extras/benchmark/boost_di_source_generator.py b/extras/benchmark/boost_di_source_generator.py
index 6a3f91f..d2858a1 100644
--- a/extras/benchmark/boost_di_source_generator.py
+++ b/extras/benchmark/boost_di_source_generator.py
@@ -11,23 +11,27 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from typing import List
 
-def generate_files(injection_graph, generate_runtime_bench_code):
+import networkx as nx
+
+
+def generate_files(injection_graph: nx.DiGraph, generate_runtime_bench_code: bool):
     file_content_by_name = dict()
 
-    for node_id in injection_graph.nodes_iter():
-        deps = injection_graph.successors(node_id)
+    for node_id in injection_graph.nodes:
+        deps = list(injection_graph.successors(node_id))
         file_content_by_name['component%s.h' % node_id] = _generate_component_header(node_id, deps)
         file_content_by_name['component%s.cpp' % node_id] = _generate_component_source(node_id, deps)
 
     [toplevel_node] = [node_id
-                       for node_id in injection_graph.nodes_iter()
-                       if not injection_graph.predecessors(node_id)]
+                       for node_id in injection_graph.nodes
+                       if not any(True for p in injection_graph.predecessors(node_id))]
     file_content_by_name['main.cpp'] = _generate_main(injection_graph, toplevel_node, generate_runtime_bench_code)
 
     return file_content_by_name
 
-def _generate_component_header(component_index, deps):
+def _generate_component_header(component_index: int, deps: List[int]):
     fields = ''.join(['std::shared_ptr<Interface%s> x%s;\n' % (dep, dep)
                       for dep in deps])
     component_deps = ''.join([', std::shared_ptr<Interface%s>' % dep for dep in deps])
@@ -39,7 +43,7 @@
 #define COMPONENT{component_index}_H
 
 #include <boost/di.hpp>
-#include <boost/di/extension/scopes/scoped_scope.hpp>
+#include <boost/di/extension/scopes/scoped.hpp>
 #include <memory>
 
 // Example include that the code might use
@@ -69,7 +73,7 @@
 """
     return template.format(**locals())
 
-def _generate_component_source(component_index, deps):
+def _generate_component_source(component_index: int, deps: List[int]):
     param_initializers = ', '.join('x%s(x%s)' % (dep, dep)
                                    for dep in deps)
     if param_initializers:
@@ -86,12 +90,12 @@
 """
     return template.format(**locals())
 
-def _generate_main(injection_graph, toplevel_component, generate_runtime_bench_code):
+def _generate_main(injection_graph: nx.DiGraph, toplevel_component: int, generate_runtime_bench_code: bool):
     include_directives = ''.join('#include "component%s.h"\n' % index
-                                 for index in injection_graph.nodes_iter())
+                                 for index in injection_graph.nodes)
 
     injector_params = ', '.join('x%sComponent()' % index
-                                for index in injection_graph.nodes_iter())
+                                for index in injection_graph.nodes)
 
     if generate_runtime_bench_code:
         template = """
diff --git a/extras/benchmark/format_bench_results.py b/extras/benchmark/format_bench_results.py
index 49c4893..614db07 100755
--- a/extras/benchmark/format_bench_results.py
+++ b/extras/benchmark/format_bench_results.py
@@ -15,30 +15,47 @@
 
 import argparse
 import json
+from typing import Tuple, List, Dict, Union, Callable, Any, Sequence, Set, Iterable
+
 import yaml
 from collections import defaultdict
 
-def extract_results(bench_results, fixed_benchmark_params, column_dimension, row_dimension, result_dimension):
-    table_data = defaultdict(lambda: dict())
+def extract_results(bench_results: List[Dict[str, Dict[Any, Any]]],
+                    fixed_benchmark_params: Dict[str, Union[str, Tuple[str, ...]]],
+                    column_dimension: str,
+                    row_dimension: str,
+                    result_dimension: str) -> Tuple[Dict[str, Dict[str, Dict[str, Any]]],
+                                                    Set[Tuple[List[Tuple[str, str]], ...]],
+                                                    Set[Tuple[Tuple[List[Tuple[str, str]], ...],
+                                                              str]]]:
+    table_data = defaultdict(lambda: dict())  # type: Dict[str, Dict[str, Dict[str, Any]]]
     remaining_dimensions_by_row_column = dict()
+    used_bench_results = set()  # type: Set[Tuple[List[Tuple[str, str]], ...]]
+    used_bench_result_values = set() # type: Set[Tuple[Tuple[List[Tuple[str, str]], ...], str]]
     for bench_result in bench_results:
         try:
             params = {dimension_name: make_immutable(dimension_value) 
                       for dimension_name, dimension_value in bench_result['benchmark'].items()}
+            original_params = dict(params)
             results = bench_result['results']
+            matches = True
+            if result_dimension not in results:
+                # result_dimension not found in this result, skip
+                matches = False
             for param_name, param_value in fixed_benchmark_params.items():
-                if params.get(param_name) != param_value:
+                if (isinstance(param_value, tuple) and params.get(param_name) in param_value) or (params.get(param_name) == param_value):
+                    pass
+                else:
                     # fixed_benchmark_params not satisfied by this result, skip
-                    break
-                if result_dimension not in results:
-                    # result_dimension not found in this result, skip
-                    break
-                params.pop(param_name)
-            else:
+                    matches = False
+            if matches:
                 # fixed_benchmark_params were satisfied by these params (and were removed)
                 assert row_dimension in params.keys(), '%s not in %s' % (row_dimension, params.keys())
                 assert column_dimension in params.keys(), '%s not in %s' % (column_dimension, params.keys())
                 assert result_dimension in results, '%s not in %s' % (result_dimension, results)
+                used_bench_results.add(tuple(sorted(original_params.items())))
+                used_bench_result_values.add((tuple(sorted(original_params.items())),
+                                              result_dimension))
                 row_value = params[row_dimension]
                 column_value = params[column_dimension]
                 remaining_dimensions = params.copy()
@@ -48,21 +65,16 @@
                     previous_remaining_dimensions = remaining_dimensions_by_row_column[(row_value, column_value)]
                     raise Exception(
                         'Found multiple benchmark results with the same fixed benchmark params, benchmark param for row and benchmark param for column, so a result can\'t be uniquely determined. '
-                        + 'Consider adding additional values in fixed_benchmark_params. Remaining dimensions: %s vs %s' % (
+                        + 'Consider adding additional values in fixed_benchmark_params. Remaining dimensions:\n%s\nvs\n%s' % (
                             remaining_dimensions, previous_remaining_dimensions))
                 table_data[row_value][column_value] = results[result_dimension]
                 remaining_dimensions_by_row_column[(row_value, column_value)] = remaining_dimensions
         except Exception as e:
             raise Exception('While processing %s' % bench_result) from e
-    return table_data
-
-
-def identity(x):
-    return x
-
+    return table_data, used_bench_results, used_bench_result_values
 
 # Takes a 2-dimensional array (list of lists) and prints a markdown table with that content.
-def print_markdown_table(table_data):
+def print_markdown_table(table_data: List[List[str]]) -> None:
     max_content_length_by_column = [max([len(str(row[column_index])) for row in table_data])
                                     for column_index in range(len(table_data[0]))]
     for row_index in range(len(table_data)):
@@ -81,7 +93,11 @@
                                 for column_index in range(len(row))])
                   + '-|')
 
-def compute_min_max(table_data, row_headers, column_headers):
+# A sequence of length 2, with the lower and upper bound of the interval.
+# TODO: use a class instead.
+Interval = Sequence[float]
+
+def compute_min_max(table_data, row_headers: List[str], column_headers: List[str]) -> Interval:
     values_by_row = {row_header: [table_data[row_header][column_header]
                                   for column_header in column_headers
                                   if column_header in table_data[row_header]]
@@ -93,8 +109,7 @@
                         for row_header in row_headers])
     return (min_in_table, max_in_table)
 
-
-def pretty_print_percentage_difference(baseline_value, current_value):
+def pretty_print_percentage_difference(baseline_value: Interval, current_value: Interval):
     baseline_min = baseline_value[0]
     baseline_max = baseline_value[1]
     current_min = current_value[0]
@@ -108,6 +123,10 @@
     else:
         return "%s - %s" % (percentage_min_s, percentage_max_s)
 
+DimensionPrettyPrinter = Callable[[Any], str]
+
+IntervalPrettyPrinter = Callable[[Interval, float, float], str]
+
 
 # Takes a table as a dict of dicts (where each table_data[row_key][column_key] is a confidence interval) and prints it as a markdown table using
 # the specified pretty print functions for column keys, row keys and values respectively.
@@ -117,18 +136,19 @@
 def print_confidence_intervals_table(table_name,
                                      table_data,
                                      baseline_table_data,
-                                     column_header_pretty_printer=identity,
-                                     row_header_pretty_printer=identity,
-                                     value_pretty_printer=identity):
+                                     column_header_pretty_printer: DimensionPrettyPrinter,
+                                     row_header_pretty_printer: DimensionPrettyPrinter,
+                                     value_pretty_printer: IntervalPrettyPrinter,
+                                     row_sort_key: Callable[[Any], Any]):
     if table_data == {}:
         print('%s: (no data)' % table_name)
         return
 
-    row_headers = sorted(list(table_data.keys()))
+    row_headers = sorted(list(table_data.keys()), key=row_sort_key)
     # We need to compute the union of the headers of all rows; some rows might be missing values for certain columns.
     column_headers = sorted(set().union(*[list(row_values.keys()) for row_values in table_data.values()]))
     if baseline_table_data:
-        baseline_row_headers = sorted(list(baseline_table_data.keys()))
+        baseline_row_headers = sorted(list(baseline_table_data.keys()), key=row_sort_key)
         baseline_column_headers = sorted(set().union(*[list(row_values.keys()) for row_values in baseline_table_data.values()]))
         unmached_baseline_column_headers = set(baseline_row_headers) - set(row_headers)
         if unmached_baseline_column_headers:
@@ -166,15 +186,20 @@
     print_markdown_table(table_content)
 
 
-def format_string_pretty_printer(format_string):
-    def pretty_print(s):
+def format_string_pretty_printer(format_string: str) -> Callable[[str], str]:
+    def pretty_print(s: str):
         return format_string % s
 
     return pretty_print
 
+def float_to_str(x: float) -> str:
+    if x > 100:
+        return str(int(x))
+    else:
+        return '%.2g' % x
 
-def interval_pretty_printer(interval, unit, multiplier):
-    interval = interval.copy()
+def interval_pretty_printer(interval: Interval, unit: str, multiplier: float) -> str:
+    interval = list(interval)  # type: List[Any]
     interval[0] *= multiplier
     interval[1] *= multiplier
 
@@ -184,11 +209,11 @@
     if int(interval[0]) == interval[0] and interval[0] >= 10:
         interval[0] = int(interval[0])
     else:
-        interval[0] = '%.3g' % interval[0]
+        interval[0] = float_to_str(interval[0])
     if int(interval[1]) == interval[1] and interval[1] >= 10:
         interval[1] = int(interval[1])
     else:
-        interval[1] = '%.3g' % interval[1]
+        interval[1] = float_to_str(interval[1])
 
     if interval[0] == interval[1]:
         return '%s %s' % (interval[0], unit)
@@ -198,7 +223,7 @@
 
 # Finds the best unit to represent values in the range [min_value, max_value].
 # The units must be specified as an ordered list [multiplier1, ..., multiplierN]
-def find_best_unit(units, min_value, max_value):
+def find_best_unit(units: List[float], min_value: float, max_value: float) -> float:
     assert min_value <= max_value
     if max_value <= units[0]:
         return units[0]
@@ -222,7 +247,7 @@
     return units[0]
 
 
-def time_interval_pretty_printer(time_interval, min_in_table, max_in_table):
+def time_interval_pretty_printer(time_interval: Interval, min_in_table: float, max_in_table: float) -> str:
     sec = 1
     milli = 0.001
     micro = milli * milli
@@ -235,7 +260,7 @@
     return interval_pretty_printer(time_interval, unit=unit_name, multiplier=1 / unit)
 
 
-def file_size_interval_pretty_printer(file_size_interval, min_in_table, max_in_table):
+def file_size_interval_pretty_printer(file_size_interval: Interval, min_in_table: float, max_in_table: float) -> str:
     byte = 1
     kb = 1024
     mb = kb * kb
@@ -254,11 +279,11 @@
     return x
 
 
-def dict_pretty_printer(dict_data):
+def dict_pretty_printer(dict_data: List[Dict[str, Union[str, Tuple[str]]]]) -> Callable[[Union[str, Tuple[str]]], str]:
     if isinstance(dict_data, list):
         dict_data = {make_immutable(mapping['from']): mapping['to'] for mapping in dict_data}
 
-    def pretty_print(s):
+    def pretty_print(s: Union[str, Tuple[str]]) -> str:
         if s in dict_data:
             return dict_data[s]
         else:
@@ -267,7 +292,8 @@
     return pretty_print
 
 
-def determine_column_pretty_printer(pretty_printer_definition):
+
+def determine_column_pretty_printer(pretty_printer_definition: Dict[str, Any]) -> DimensionPrettyPrinter:
     if 'format_string' in pretty_printer_definition:
         return format_string_pretty_printer(pretty_printer_definition['format_string'])
 
@@ -276,19 +302,23 @@
 
     raise Exception("Unrecognized pretty printer description: %s" % pretty_printer_definition)
 
-
-def determine_row_pretty_printer(pretty_printer_definition):
+def determine_row_pretty_printer(pretty_printer_definition: Dict[str, Any]) -> DimensionPrettyPrinter:
     return determine_column_pretty_printer(pretty_printer_definition)
 
+def determine_row_sort_key(pretty_printer_definition: Dict[str, Any]) -> Callable[[Any], Any]:
+    if 'fixed_map' in pretty_printer_definition:
+        indexes = {x: i for i, x in enumerate(pretty_printer_definition['fixed_map'].keys())}
+        return lambda s: indexes[s]
 
-def determine_value_pretty_printer(unit):
+    return lambda x: x
+
+def determine_value_pretty_printer(unit: str) -> IntervalPrettyPrinter:
     if unit == "seconds":
         return time_interval_pretty_printer
     if unit == "bytes":
         return file_size_interval_pretty_printer
     raise Exception("Unrecognized unit: %s" % unit)
 
-
 def main():
     parser = argparse.ArgumentParser(description='Runs all the benchmarks whose results are on the Fruit website.')
     parser.add_argument('--benchmark-results',
@@ -314,17 +344,23 @@
         baseline_bench_results = None
 
     with open(args.benchmark_tables_definition, 'r') as f:
-        for table_definition in yaml.load(f)["tables"]:
+        used_bench_results = set()
+        # Set of (Benchmark definition, Benchmark result name) pairs
+        used_bench_result_values = set()
+        config = yaml.full_load(f)
+        for table_definition in config["tables"]:
             try:
                 fixed_benchmark_params = {dimension_name: make_immutable(dimension_value) for dimension_name, dimension_value in table_definition['benchmark_filter'].items()}
-                table_data = extract_results(
+                table_data, last_used_bench_results, last_used_bench_result_values = extract_results(
                     bench_results,
                     fixed_benchmark_params=fixed_benchmark_params,
                     column_dimension=table_definition['columns']['dimension'],
                     row_dimension=table_definition['rows']['dimension'],
                     result_dimension=table_definition['results']['dimension'])
+                used_bench_results = used_bench_results.union(last_used_bench_results)
+                used_bench_result_values = used_bench_result_values.union(last_used_bench_result_values)
                 if baseline_bench_results:
-                    baseline_table_data = extract_results(
+                    baseline_table_data, _, _ = extract_results(
                         baseline_bench_results,
                         fixed_benchmark_params=fixed_benchmark_params,
                         column_dimension=table_definition['columns']['dimension'],
@@ -340,13 +376,29 @@
                                                  baseline_table_data,
                                                  column_header_pretty_printer=determine_column_pretty_printer(columns_pretty_printer_definition),
                                                  row_header_pretty_printer=determine_row_pretty_printer(rows_pretty_printer_definition),
-                                                 value_pretty_printer=determine_value_pretty_printer(results_unit))
+                                                 value_pretty_printer=determine_value_pretty_printer(results_unit),
+                                                 row_sort_key=determine_row_sort_key(rows_pretty_printer_definition))
                 print()
                 print()
             except Exception as e:
-                print('While processing table:\n' + table_definition)
+                print('While processing table:\n%s' % table_definition)
                 print()
                 raise e
+        allowed_unused_benchmarks = set(config.get('allowed_unused_benchmarks', []))
+        allowed_unused_benchmark_results = set(config.get('allowed_unused_benchmark_results', []))
+        for bench_result in bench_results:
+            params = {dimension_name: make_immutable(dimension_value)
+                      for dimension_name, dimension_value in bench_result['benchmark'].items()}
+            benchmark_defn = tuple(sorted(params.items()))
+            if benchmark_defn not in used_bench_results:
+                if params['name'] not in allowed_unused_benchmarks:
+                    print('Warning: benchmark result did not match any tables: %s' % params)
+            else:
+                unused_result_dimensions = {result_dimension
+                                            for result_dimension in bench_result['results'].keys()
+                                            if (benchmark_defn, result_dimension) not in used_bench_result_values and result_dimension not in allowed_unused_benchmark_results}
+                if unused_result_dimensions:
+                    print('Warning: unused result dimensions %s in benchmark result %s' % (unused_result_dimensions, params))
 
 
 if __name__ == "__main__":
diff --git a/extras/benchmark/fruit_source_generator.py b/extras/benchmark/fruit_source_generator.py
index 894bd28..f7bc786 100644
--- a/extras/benchmark/fruit_source_generator.py
+++ b/extras/benchmark/fruit_source_generator.py
@@ -11,29 +11,32 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from typing import List
+
+import networkx as nx
 
 
-def generate_files(injection_graph, generate_runtime_bench_code, use_normalized_component=False):
+def generate_files(injection_graph: nx.DiGraph, generate_runtime_bench_code: bool, use_normalized_component: bool=False):
     if use_normalized_component:
         assert not generate_runtime_bench_code
 
     file_content_by_name = dict()
 
-    for node_id in injection_graph.nodes_iter():
+    for node_id in injection_graph.nodes:
         file_content_by_name['component%s.h' % node_id] = _generate_component_header(node_id)
-        file_content_by_name['component%s.cpp' % node_id] = _generate_component_source(node_id, injection_graph.successors(node_id))
+        file_content_by_name['component%s.cpp' % node_id] = _generate_component_source(node_id, list(injection_graph.successors(node_id)))
 
     [toplevel_node] = [node_id
-                       for node_id in injection_graph.nodes_iter()
-                       if not injection_graph.predecessors(node_id)]
+                       for node_id in injection_graph.nodes
+                       if not any(True for p in injection_graph.predecessors(node_id))]
     file_content_by_name['main.cpp'] = _generate_main(toplevel_node, generate_runtime_bench_code)
 
     return file_content_by_name
 
-def _get_component_type(component_index):
+def _get_component_type(component_index: int):
     return 'fruit::Component<Interface{component_index}>'.format(**locals())
 
-def _generate_component_header(component_index):
+def _generate_component_header(component_index: int):
     component_type = _get_component_type(component_index)
     template = """
 #ifndef COMPONENT{component_index}_H
@@ -54,7 +57,7 @@
 """
     return template.format(**locals())
 
-def _generate_component_source(component_index, deps):
+def _generate_component_source(component_index: int, deps: List[int]):
     include_directives = ''.join(['#include "component%s.h"\n' % index for index in deps + [component_index]])
 
     fields = ''.join(['Interface%s& x%s;\n' % (dep, dep)
@@ -95,7 +98,7 @@
 
     return template.format(**locals())
 
-def _generate_main(toplevel_component, generate_runtime_bench_code):
+def _generate_main(toplevel_component: int, generate_runtime_bench_code: bool):
     if generate_runtime_bench_code:
         template = """
 #include "component{toplevel_component}.h"
diff --git a/extras/benchmark/generate_benchmark.py b/extras/benchmark/generate_benchmark.py
index cee0017..411e9a6 100755
--- a/extras/benchmark/generate_benchmark.py
+++ b/extras/benchmark/generate_benchmark.py
@@ -24,9 +24,9 @@
 import networkx as nx
 
 
-def generate_injection_graph(num_components_with_no_deps,
-                             num_components_with_deps,
-                             num_deps):
+def generate_injection_graph(num_components_with_no_deps: int,
+                             num_components_with_deps: int,
+                             num_deps: int):
     injection_graph = nx.DiGraph()
 
     num_used_ids = 0
@@ -71,23 +71,23 @@
     return injection_graph
 
 def generate_benchmark(
-        di_library,
-        compiler,
-        cxx_std,
-        output_dir,
-        num_components_with_no_deps,
-        num_components_with_deps,
-        num_deps,
-        generate_runtime_bench_code,
-        use_exceptions=True,
-        use_rtti=True,
-        fruit_build_dir=None,
-        fruit_sources_dir=None,
-        boost_di_sources_dir=None,
-        generate_debuginfo=False,
-        use_new_delete=False,
-        use_interfaces=False,
-        use_normalized_component=False):
+        di_library: str,
+        compiler: str,
+        cxx_std: str,
+        output_dir: str,
+        num_components_with_no_deps: int,
+        num_components_with_deps: int,
+        num_deps: int,
+        generate_runtime_bench_code: bool,
+        use_exceptions: bool=True,
+        use_rtti: bool=True,
+        fruit_build_dir: str=None,
+        fruit_sources_dir: str=None,
+        boost_di_sources_dir: str=None,
+        generate_debuginfo: bool=False,
+        use_new_delete: bool=False,
+        use_interfaces: bool=False,
+        use_normalized_component: bool=False):
     """Generates a sample codebase using the specified DI library, meant for benchmarking.
 
     :param boost_di_sources_dir: this is only used if di_library=='boost_di', it can be None otherwise.
@@ -135,8 +135,8 @@
         other_compile_flags.append('-fno-exceptions')
     if not use_rtti:
         other_compile_flags.append('-fno-rtti')
-    compile_command = '%s -std=%s -MMD -MP -O2 -W -Wall -Werror -DNDEBUG -ftemplate-depth=10000 %s %s' % (compiler, cxx_std, include_flags, ' '.join(other_compile_flags))
-    link_command = '%s -std=%s -O2 -W -Wall -Werror %s %s' % (compiler, cxx_std, rpath_flags, library_dirs_flags)
+    compile_command = '%s -std=%s -MMD -MP -O2 -W -Wall -DNDEBUG -ftemplate-depth=10000 %s %s' % (compiler, cxx_std, include_flags, ' '.join(other_compile_flags))
+    link_command = '%s -std=%s -O2 -W -Wall %s %s' % (compiler, cxx_std, rpath_flags, library_dirs_flags)
     # GCC requires passing the -lfruit flag *after* all object files to be linked for some reason.
     link_command_suffix = link_libraries_flags
 
diff --git a/extras/benchmark/makefile_generator.py b/extras/benchmark/makefile_generator.py
index 083fd36..7781a6e 100644
--- a/extras/benchmark/makefile_generator.py
+++ b/extras/benchmark/makefile_generator.py
@@ -11,23 +11,30 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+from typing import List
 
 
-def generate_makefile(cpp_files, executable_name, compile_command, link_command, link_command_suffix):
+def generate_makefile(cpp_files: List[str], executable_name: str, compile_command: str, link_command: str, link_command_suffix: str):
     assert executable_name + '.cpp' in cpp_files, '%s.cpp in %s' % (executable_name, cpp_files)
 
     link_rule_template = """
 {executable_name}: {object_files}
 \t{link_command} {object_files} -o {executable_name} {link_command_suffix}
+
+{executable_name}_ram.txt: {object_files_ram_txt}
+\t(cat {object_files_ram_txt}; /bin/time -v {link_command} {object_files} -o {executable_name}.tmp {link_command_suffix} 2>&1 | fgrep 'Maximum resident set size' | sed 's|.*: ||') >{executable_name}_ram.txt
 """
     compile_rule_template = """
 {name}.o: {name}.cpp
 \t{compile_command} -c {name}.cpp -o {name}.o
+
+{name}.o_ram.txt: {name}.cpp
+\t/bin/time -v {compile_command} -c {name}.cpp -o {name}.o 2>&1 | fgrep 'Maximum resident set size' | sed 's|.*: ||' >{name}.o_ram.txt
 """
 
     clean_rule_template = """
 clean:
-\trm -f {object_files} {dep_files} {executable_name}
+\trm -f {object_files} {dep_files} {executable_name} {executable_name}_ram.txt {object_files_ram_txt}
 """
 
     dep_file_deps = """
@@ -40,6 +47,7 @@
 
     compile_rules = []
     object_files = []
+    object_files_ram_txt = []
     dep_files = []
     for cpp_file in cpp_files:
         assert cpp_file.endswith('.cpp')
@@ -50,16 +58,19 @@
             compile_command=compile_command)
         compile_rules.append(compile_rule)
         object_files.append('%s.o' % source)
+        object_files_ram_txt.append('%s.o_ram.txt' % source)
         dep_files.append('%s.d' % source)
 
     link_rule = link_rule_template.format(
         object_files=' '.join(object_files),
+        object_files_ram_txt=' '.join(object_files_ram_txt),
         link_command=link_command,
         link_command_suffix=link_command_suffix,
         executable_name=executable_name)
 
     clean_rule = clean_rule_template.format(
         object_files=' '.join(object_files),
+        object_files_ram_txt=' '.join(object_files_ram_txt),
         executable_name=executable_name,
         dep_files=' '.join(dep_files))
 
diff --git a/extras/benchmark/new_delete_benchmark.cpp b/extras/benchmark/new_delete_benchmark.cpp
index 8131eac..d30d835 100644
--- a/extras/benchmark/new_delete_benchmark.cpp
+++ b/extras/benchmark/new_delete_benchmark.cpp
@@ -29,6 +29,9 @@
 #elif MULTIPLIER == 100
 #define REPEAT(X) REPEAT_100(X, _)
 
+#elif MULTIPLIER == 250
+#define REPEAT(X) REPEAT_250(X, _)
+
 #elif MULTIPLIER == 1000
 #define REPEAT(X) REPEAT_1000(X, _)
 
@@ -48,12 +51,21 @@
       R PLACEHOLDER(X, I##5) R PLACEHOLDER(X, I##6) R PLACEHOLDER(X, I##7) R PLACEHOLDER(X, I##8)                      \
           R PLACEHOLDER(X, I##9)
 
+#define META_REPEAT_5(R, X, I)                                                                                        \
+  R PLACEHOLDER(X, I##0) R PLACEHOLDER(X, I##1) R PLACEHOLDER(X, I##2) R PLACEHOLDER(X, I##3) R PLACEHOLDER(X, I##4)
+
 #define REPEAT_1(X, I) X(I)
 
+#define REPEAT_5(X, I) META_REPEAT_5(REPEAT_1, X, I)
+
 #define REPEAT_10(X, I) META_REPEAT_10(REPEAT_1, X, I)
 
+#define REPEAT_25(X, I) META_REPEAT_5(REPEAT_5, X, I)
+
 #define REPEAT_100(X, I) META_REPEAT_10(REPEAT_10, X, I)
 
+#define REPEAT_250(X, I) META_REPEAT_10(REPEAT_25, X, I)
+
 #define REPEAT_1000(X, I) META_REPEAT_10(REPEAT_100, X, I)
 
 using namespace std;
diff --git a/extras/benchmark/no_di_library_source_generator.py b/extras/benchmark/no_di_library_source_generator.py
index 2d91d04..65046a2 100644
--- a/extras/benchmark/no_di_library_source_generator.py
+++ b/extras/benchmark/no_di_library_source_generator.py
@@ -12,13 +12,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 import itertools
+from typing import List
+
 import networkx as nx
 
-def generate_files(injection_graph, use_new_delete, use_interfaces, generate_runtime_bench_code):
+def generate_files(injection_graph: nx.DiGraph, use_new_delete: bool, use_interfaces: bool, generate_runtime_bench_code: bool):
     file_content_by_name = dict()
 
-    for node_id in injection_graph.nodes_iter():
-        deps = injection_graph.successors(node_id)
+    for node_id in injection_graph.nodes:
+        deps = list(injection_graph.successors(node_id))
         if use_interfaces:
             file_content_by_name['class%s_interface.h' % node_id] = _generate_class_interface_header(node_id)
             file_content_by_name['class%s.h' % node_id] = _generate_class_header_with_interfaces(node_id, deps)
@@ -31,7 +33,7 @@
 
     return file_content_by_name
 
-def _generate_class_interface_header(class_index):
+def _generate_class_interface_header(class_index: int):
     template = """
 #ifndef CLASS{class_index}_INTERFACE_H
 #define CLASS{class_index}_INTERFACE_H
@@ -48,7 +50,7 @@
 """
     return template.format(**locals())
 
-def _generate_class_header_with_interfaces(class_index, deps):
+def _generate_class_header_with_interfaces(class_index: int, deps: List[int]):
     include_directives = ''.join('#include "class%s_interface.h"\n' % index
                                  for index in itertools.chain(deps, (class_index,)))
     fields = ''.join('Interface%s& x%s;\n' % (index, index)
@@ -75,7 +77,7 @@
 """
     return template.format(**locals())
 
-def _generate_class_header_without_interfaces(class_index, deps):
+def _generate_class_header_without_interfaces(class_index: int, deps: List[int]):
     include_directives = ''.join('#include "class%s.h"\n' % index
                                  for index in deps)
     fields = ''.join('Class%s& x%s;\n' % (index, index)
@@ -101,7 +103,7 @@
 """
     return template.format(**locals())
 
-def _generate_class_cpp_file_with_interfaces(class_index, deps):
+def _generate_class_cpp_file_with_interfaces(class_index: int, deps: List[int]):
     constructor_params = ', '.join('Interface%s& x%s' % (index, index)
                                    for index in deps)
     field_initializers = ', '.join('x%s(x%s)' % (index, index)
@@ -127,7 +129,7 @@
 """
     return template.format(**locals())
 
-def _generate_class_cpp_file_without_interfaces(class_index, deps):
+def _generate_class_cpp_file_without_interfaces(class_index: int, deps: List[int]):
     constructor_params = ', '.join('Class%s& x%s' % (index, index)
                                    for index in deps)
     field_initializers = ', '.join('x%s(x%s)' % (index, index)
@@ -145,14 +147,14 @@
     return template.format(**locals())
 
 
-def _generate_main(injection_graph, use_interfaces, use_new_delete, generate_runtime_bench_code):
+def _generate_main(injection_graph: nx.DiGraph, use_interfaces: bool, use_new_delete: bool, generate_runtime_bench_code: bool):
     [toplevel_class_index] = [node_id
-                              for node_id in injection_graph.nodes_iter()
-                              if not injection_graph.predecessors(node_id)]
+                              for node_id in injection_graph.nodes
+                              if not any(True for p in injection_graph.predecessors(node_id))]
 
     if use_interfaces:
         include_directives = ''.join('#include "class%s.h"\n' % index
-                                     for index in injection_graph.nodes_iter())
+                                     for index in injection_graph.nodes)
     else:
         include_directives = '#include "class%s.h"\n' % toplevel_class_index
 
@@ -171,7 +173,7 @@
                                      for class_index in reversed(list(nx.topological_sort(injection_graph))))
 
     void_casts = ''.join('(void) x%s;\n' % index
-                         for index in injection_graph.nodes_iter())
+                         for index in injection_graph.nodes)
 
     if generate_runtime_bench_code:
         template = """
diff --git a/extras/benchmark/run_benchmarks.py b/extras/benchmark/run_benchmarks.py
index d19232b..1fc3fd4 100755
--- a/extras/benchmark/run_benchmarks.py
+++ b/extras/benchmark/run_benchmarks.py
@@ -22,13 +22,15 @@
 import os
 import shutil
 import itertools
+import traceback
+from typing import Dict, List, Tuple, Optional, Any, TypeVar, Callable, Iterable
+
 import numpy
 import subprocess
 import yaml
 from numpy import floor, log10
 import scipy
 import multiprocessing
-import sh
 import json
 import statsmodels.stats.api as stats
 from generate_benchmark import generate_benchmark
@@ -36,7 +38,7 @@
 from functools import lru_cache as memoize
 
 class CommandFailedException(Exception):
-    def __init__(self, command, stdout, stderr, error_code):
+    def __init__(self, command: List[str], stdout: str, stderr: str, error_code: str):
         self.command = command
         self.stdout = stdout
         self.stderr = stderr
@@ -53,7 +55,7 @@
         {stderr}
         ''').format(command=self.command, error_code=self.error_code, stdout=self.stdout, stderr=self.stderr)
 
-def run_command(executable, args=[], cwd=None, env=None):
+def run_command(executable: str, args: List[Any]=[], cwd: str=None, env: Dict[str, str]=None) -> Tuple[str, str]:
     args = [str(arg) for arg in args]
     command = [executable] + args
     try:
@@ -70,7 +72,7 @@
 
 make_args = ['-j', multiprocessing.cpu_count() + 1]
 
-def parse_results(result_lines):
+def parse_results(result_lines: List[str]) -> Dict[str, float]:
     """
      Parses results from the format:
      ['Dimension name1        = 123',
@@ -89,7 +91,7 @@
 
 # We memoize the result since this might be called repeatedly and it's somewhat expensive.
 @memoize(maxsize=None)
-def determine_compiler_name(compiler_executable_name):
+def determine_compiler_name(compiler_executable_name: str) -> str:
     tmpdir = tempfile.gettempdir() + '/fruit-determine-compiler-version-dir'
     ensure_empty_dir(tmpdir)
     with open(tmpdir + '/CMakeLists.txt', 'w') as file:
@@ -112,7 +114,7 @@
 
 # Returns a pair (sha256_hash, version_name), where version_name will be None if no version tag was found at HEAD.
 @memoize(maxsize=None)
-def git_repo_info(repo_path):
+def git_repo_info(repo_path: str) -> Tuple[str, str]:
     repo = git.Repo(repo_path)
     head_tags = [tag.name for tag in repo.tags if tag.commit == repo.head.commit and re.match('v[0-9].*', tag.name)]
     if head_tags == []:
@@ -129,7 +131,7 @@
 # We put the compiler name/version in the results because the same 'compiler' value might refer to different compiler versions
 # (e.g. if GCC 6.0.0 is installed when benchmarks are run, then it's updated to GCC 6.0.1 and finally the results are formatted, we
 # want the formatted results to say "GCC 6.0.0" instead of "GCC 6.0.1").
-def add_synthetic_benchmark_parameters(original_benchmark_parameters, path_to_code_under_test):
+def add_synthetic_benchmark_parameters(original_benchmark_parameters: Dict[str, Any], path_to_code_under_test: Optional[str]):
     benchmark_params = original_benchmark_parameters.copy()
     benchmark_params['compiler_name'] = determine_compiler_name(original_benchmark_parameters['compiler'])
     if path_to_code_under_test is not None:
@@ -140,8 +142,13 @@
     return benchmark_params
 
 
-class SimpleNewDeleteRunTimeBenchmark:
-    def __init__(self, benchmark_definition, fruit_benchmark_sources_dir):
+class Benchmark:
+    def prepare(self) -> None: ...
+    def run(self) -> Dict[str, float]: ...
+    def describe(self) -> str: ...
+
+class SimpleNewDeleteRunTimeBenchmark(Benchmark):
+    def __init__(self, benchmark_definition: Dict[str, Any], fruit_benchmark_sources_dir: str):
         self.benchmark_definition = add_synthetic_benchmark_parameters(benchmark_definition, path_to_code_under_test=None)
         self.fruit_benchmark_sources_dir = fruit_benchmark_sources_dir
 
@@ -170,8 +177,8 @@
         return self.benchmark_definition
 
 
-class FruitSingleFileCompileTimeBenchmark:
-    def __init__(self, benchmark_definition, fruit_sources_dir, fruit_build_dir, fruit_benchmark_sources_dir):
+class FruitSingleFileCompileTimeBenchmark(Benchmark):
+    def __init__(self, benchmark_definition: Dict[str, Any], fruit_sources_dir: str, fruit_build_dir: str, fruit_benchmark_sources_dir: str):
         self.benchmark_definition = add_synthetic_benchmark_parameters(benchmark_definition, path_to_code_under_test=fruit_sources_dir)
         self.fruit_sources_dir = fruit_sources_dir
         self.fruit_build_dir = fruit_build_dir
@@ -207,7 +214,7 @@
         return self.benchmark_definition
 
 
-def ensure_empty_dir(dirname):
+def ensure_empty_dir(dirname: str):
     # We start by creating the directory instead of just calling rmtree with ignore_errors=True because that would ignore
     # all errors, so we might otherwise go ahead even if the directory wasn't properly deleted.
     os.makedirs(dirname, exist_ok=True)
@@ -215,7 +222,7 @@
     os.makedirs(dirname)
 
 
-class GenericGeneratedSourcesBenchmark:
+class GenericGeneratedSourcesBenchmark(Benchmark):
     def __init__(self,
                  di_library,
                  benchmark_definition,
@@ -258,6 +265,10 @@
         self.arbitrary_files = [files[i * (len(files) // (num_files_changed + 2))]
                                 for i in range(1, num_files_changed + 1)]
 
+    def prepare_compile_memory_benchmark(self):
+        self.prepare_compile_benchmark()
+        self.run_compile_memory_benchmark()
+
     def prepare_runtime_benchmark(self):
         self.prepare_compile_benchmark()
         self.run_make_build()
@@ -289,6 +300,16 @@
         result = {'incremental_compile_time': end - start}
         return result
 
+    def run_compile_memory_benchmark(self):
+        run_command('make', args=make_args + ['clean'], cwd=self.tmpdir)
+        run_command('make', args=make_args + ['main_ram.txt'], cwd=self.tmpdir)
+        with open(self.tmpdir + '/main_ram.txt') as f:
+            ram_usages = [int(n)*1024 for n in f.readlines()]
+        return {
+            'total_max_ram_usage': sum(ram_usages),
+            'max_ram_usage': max(ram_usages),
+        }
+
     def run_runtime_benchmark(self):
         num_classes = self.benchmark_definition['num_classes']
         loop_factor = self.benchmark_definition['loop_factor']
@@ -340,6 +361,17 @@
     def run(self):
         return self.run_incremental_compile_benchmark()
 
+class CompileMemoryBenchmark(GenericGeneratedSourcesBenchmark):
+    def __init__(self, **kwargs):
+        super().__init__(generate_runtime_bench_code=False,
+                         **kwargs)
+
+    def prepare(self):
+        self.prepare_compile_memory_benchmark()
+
+    def run(self):
+        return self.run_compile_memory_benchmark()
+
 class StartupTimeBenchmark(GenericGeneratedSourcesBenchmark):
     def __init__(self, **kwargs):
         super().__init__(generate_runtime_bench_code=False,
@@ -395,6 +427,13 @@
                          fruit_sources_dir=fruit_sources_dir,
                          **kwargs)
 
+class FruitCompileMemoryBenchmark(CompileMemoryBenchmark):
+    def __init__(self, fruit_sources_dir, **kwargs):
+        super().__init__(di_library='fruit',
+                         path_to_code_under_test=fruit_sources_dir,
+                         fruit_sources_dir=fruit_sources_dir,
+                         **kwargs)
+
 class FruitRunTimeBenchmark(RunTimeBenchmark):
     def __init__(self, fruit_sources_dir, **kwargs):
         super().__init__(di_library='fruit',
@@ -444,6 +483,13 @@
                          boost_di_sources_dir=boost_di_sources_dir,
                          **kwargs)
 
+class BoostDiCompileMemoryBenchmark(CompileMemoryBenchmark):
+    def __init__(self, boost_di_sources_dir, **kwargs):
+        super().__init__(di_library='boost_di',
+                         path_to_code_under_test=boost_di_sources_dir,
+                         boost_di_sources_dir=boost_di_sources_dir,
+                         **kwargs)
+
 class BoostDiRunTimeBenchmark(RunTimeBenchmark):
     def __init__(self, boost_di_sources_dir, **kwargs):
         super().__init__(di_library='boost_di',
@@ -484,6 +530,11 @@
         super().__init__(di_library='none',
                          **kwargs)
 
+class SimpleDiCompileMemoryBenchmark(CompileMemoryBenchmark):
+    def __init__(self, **kwargs):
+        super().__init__(di_library='none',
+                         **kwargs)
+
 class SimpleDiRunTimeBenchmark(RunTimeBenchmark):
     def __init__(self, **kwargs):
         super().__init__(di_library='none',
@@ -514,6 +565,10 @@
     def __init__(self, **kwargs):
         super().__init__(use_interfaces=True, **kwargs)
 
+class SimpleDiWithInterfacesCompileMemoryBenchmark(SimpleDiCompileMemoryBenchmark):
+    def __init__(self, **kwargs):
+        super().__init__(use_interfaces=True, **kwargs)
+
 class SimpleDiWithInterfacesRunTimeBenchmark(SimpleDiRunTimeBenchmark):
     def __init__(self, **kwargs):
         super().__init__(use_interfaces=True, **kwargs)
@@ -540,6 +595,10 @@
     def __init__(self, **kwargs):
         super().__init__(use_new_delete=True, **kwargs)
 
+class SimpleDiWithInterfacesAndNewDeleteCompileMemoryBenchmark(SimpleDiWithInterfacesCompileMemoryBenchmark):
+    def __init__(self, **kwargs):
+        super().__init__(use_new_delete=True, **kwargs)
+
 class SimpleDiWithInterfacesAndNewDeleteRunTimeBenchmark(SimpleDiWithInterfacesRunTimeBenchmark):
     def __init__(self, **kwargs):
         super().__init__(use_new_delete=True, **kwargs)
@@ -559,13 +618,13 @@
         super().__init__(use_new_delete=True, **kwargs)
 
 
-def round_to_significant_digits(n, num_significant_digits):
+def round_to_significant_digits(n: float, num_significant_digits: int) -> float:
     if n <= 0:
         # We special-case this, otherwise the log10 below will fail.
         return 0
     return round(n, num_significant_digits - int(floor(log10(n))) - 1)
 
-def run_benchmark(benchmark, max_runs, timeout_hours, output_file, min_runs=3):
+def run_benchmark(benchmark: Benchmark, max_runs: int, timeout_hours: int, output_file: str, min_runs: int=3) -> None:
     def run_benchmark_once():
         print('Running benchmark... ', end='', flush=True)
         result = benchmark.run()
@@ -627,7 +686,7 @@
     print()
 
 
-def expand_benchmark_definition(benchmark_definition):
+def expand_benchmark_definition(benchmark_definition: Dict[str, Any]) -> List[Dict[str, Tuple[Any]]]:
     """
     Takes a benchmark definition, e.g.:
     [{name: 'foo', compiler: ['g++-5', 'g++-6']},
@@ -650,12 +709,15 @@
             for value_combination in value_combinations]
 
 
-def expand_benchmark_definitions(benchmark_definitions):
+def expand_benchmark_definitions(benchmark_definitions: List[Dict[str, Any]]):
     return list(itertools.chain(*[expand_benchmark_definition(benchmark_definition) for benchmark_definition in benchmark_definitions]))
 
-def group_by(l, element_to_key):
-    """Takes a list and returns a dict of sublists, where the elements are grouped using the provided function"""
-    result = defaultdict(list)
+T = TypeVar('T')
+K = TypeVar('K')
+
+def group_by(l: List[T], element_to_key: Callable[[T], K]) -> Iterable[Tuple[K, List[T]]]:
+    """Takes a list and returns a list of sublists, where the elements are grouped using the provided function"""
+    result = defaultdict(list)  # type: Dict[K, List[T]]
     for elem in l:
         result[element_to_key(elem)].append(elem)
     return result.items()
@@ -690,7 +752,7 @@
     fruit_build_dir = tempfile.gettempdir() + '/fruit-benchmark-build-dir'
 
     with open(args.benchmark_definition, 'r') as f:
-        yaml_file_content = yaml.load(f)
+        yaml_file_content = yaml.full_load(f)
         global_definitions = yaml_file_content['global']
         benchmark_definitions = expand_benchmark_definitions(yaml_file_content['benchmarks'])
 
@@ -702,24 +764,28 @@
                             (benchmark_definition['compiler'], tuple(benchmark_definition['additional_cmake_args']))):
 
         print('Preparing for benchmarks with the compiler %s, with additional CMake args %s' % (compiler_executable_name, additional_cmake_args))
-        # We compute this here (and memoize the result) so that the benchmark's describe() will retrieve the cached
-        # value instantly.
-        determine_compiler_name(compiler_executable_name)
+        try:
+            # We compute this here (and memoize the result) so that the benchmark's describe() will retrieve the cached
+            # value instantly.
+            determine_compiler_name(compiler_executable_name)
 
-        # Build Fruit in fruit_build_dir, so that fruit_build_dir points to a built Fruit (useful for e.g. the config header).
-        shutil.rmtree(fruit_build_dir, ignore_errors=True)
-        os.makedirs(fruit_build_dir)
-        modified_env = os.environ.copy()
-        modified_env['CXX'] = compiler_executable_name
-        run_command('cmake',
-                    args=[
-                        args.fruit_sources_dir,
-                        '-DCMAKE_BUILD_TYPE=Release',
-                        *additional_cmake_args,
-                    ],
-                    cwd=fruit_build_dir,
-                    env=modified_env)
-        run_command('make', args=make_args, cwd=fruit_build_dir)
+            # Build Fruit in fruit_build_dir, so that fruit_build_dir points to a built Fruit (useful for e.g. the config header).
+            shutil.rmtree(fruit_build_dir, ignore_errors=True)
+            os.makedirs(fruit_build_dir)
+            modified_env = os.environ.copy()
+            modified_env['CXX'] = compiler_executable_name
+            run_command('cmake',
+                        args=[
+                            args.fruit_sources_dir,
+                            '-DCMAKE_BUILD_TYPE=Release',
+                            *additional_cmake_args,
+                        ],
+                        cwd=fruit_build_dir,
+                        env=modified_env)
+            run_command('make', args=make_args, cwd=fruit_build_dir)
+        except Exception as e:
+            print('Exception while preparing for benchmarks with the compiler %s, with additional CMake args %s.\n%s\nGoing ahead with the rest.' % (compiler_executable_name, additional_cmake_args, traceback.format_exc()))
+            continue
 
         for benchmark_definition in benchmark_definitions_with_current_config:
             benchmark_index += 1
@@ -744,6 +810,7 @@
                 benchmark_class = {
                     'fruit_compile_time': FruitCompileTimeBenchmark,
                     'fruit_incremental_compile_time': FruitIncrementalCompileTimeBenchmark,
+                    'fruit_compile_memory': FruitCompileMemoryBenchmark,
                     'fruit_run_time': FruitRunTimeBenchmark,
                     'fruit_startup_time': FruitStartupTimeBenchmark,
                     'fruit_startup_time_with_normalized_component': FruitStartupTimeWithNormalizedComponentBenchmark,
@@ -758,6 +825,7 @@
                 benchmark_class = {
                     'boost_di_compile_time': BoostDiCompileTimeBenchmark,
                     'boost_di_incremental_compile_time': BoostDiIncrementalCompileTimeBenchmark,
+                    'boost_di_compile_memory': BoostDiCompileMemoryBenchmark,
                     'boost_di_run_time': BoostDiRunTimeBenchmark,
                     'boost_di_startup_time': BoostDiStartupTimeBenchmark,
                     'boost_di_executable_size': BoostDiExecutableSizeBenchmark,
@@ -770,18 +838,21 @@
                 benchmark_class = {
                     'simple_di_compile_time': SimpleDiCompileTimeBenchmark,
                     'simple_di_incremental_compile_time': SimpleDiIncrementalCompileTimeBenchmark,
+                    'simple_di_compile_memory': SimpleDiCompileMemoryBenchmark,
                     'simple_di_run_time': SimpleDiRunTimeBenchmark,
                     'simple_di_startup_time': SimpleDiStartupTimeBenchmark,
                     'simple_di_executable_size': SimpleDiExecutableSizeBenchmark,
                     'simple_di_executable_size_without_exceptions_and_rtti': SimpleDiExecutableSizeBenchmarkWithoutExceptionsAndRtti,
                     'simple_di_with_interfaces_compile_time': SimpleDiWithInterfacesCompileTimeBenchmark,
                     'simple_di_with_interfaces_incremental_compile_time': SimpleDiWithInterfacesIncrementalCompileTimeBenchmark,
+                    'simple_di_with_interfaces_compile_memory': SimpleDiWithInterfacesCompileMemoryBenchmark,
                     'simple_di_with_interfaces_run_time': SimpleDiWithInterfacesRunTimeBenchmark,
                     'simple_di_with_interfaces_startup_time': SimpleDiWithInterfacesStartupTimeBenchmark,
                     'simple_di_with_interfaces_executable_size': SimpleDiWithInterfacesExecutableSizeBenchmark,
                     'simple_di_with_interfaces_executable_size_without_exceptions_and_rtti': SimpleDiWithInterfacesExecutableSizeBenchmarkWithoutExceptionsAndRtti,
                     'simple_di_with_interfaces_and_new_delete_compile_time': SimpleDiWithInterfacesAndNewDeleteCompileTimeBenchmark,
                     'simple_di_with_interfaces_and_new_delete_incremental_compile_time': SimpleDiWithInterfacesAndNewDeleteIncrementalCompileTimeBenchmark,
+                    'simple_di_with_interfaces_and_new_delete_compile_memory': SimpleDiWithInterfacesAndNewDeleteCompileMemoryBenchmark,
                     'simple_di_with_interfaces_and_new_delete_run_time': SimpleDiWithInterfacesAndNewDeleteRunTimeBenchmark,
                     'simple_di_with_interfaces_and_new_delete_startup_time': SimpleDiWithInterfacesAndNewDeleteStartupTimeBenchmark,
                     'simple_di_with_interfaces_and_new_delete_executable_size': SimpleDiWithInterfacesAndNewDeleteExecutableSizeBenchmark,
@@ -795,11 +866,14 @@
             if benchmark.describe() in previous_run_completed_benchmarks:
                 print("Skipping benchmark that was already run previously (due to --continue-benchmark):", benchmark.describe())
                 continue
-
-            run_benchmark(benchmark,
-                          output_file=args.output_file,
-                          max_runs=global_definitions['max_runs'],
-                          timeout_hours=global_definitions['max_hours_per_combination'])
+            
+            try:
+                run_benchmark(benchmark,
+                            output_file=args.output_file,
+                            max_runs=global_definitions['max_runs'],
+                            timeout_hours=global_definitions['max_hours_per_combination'])
+            except Exception as e:
+                print('Exception while running benchmark: %s.\n%s\nGoing ahead with the rest.' % (benchmark.describe(), traceback.format_exc()))
 
 
 if __name__ == "__main__":
diff --git a/extras/benchmark/suites/boost_di.yml b/extras/benchmark/suites/boost_di.yml
index 815991c..458d11e 100644
--- a/extras/benchmark/suites/boost_di.yml
+++ b/extras/benchmark/suites/boost_di.yml
@@ -19,18 +19,21 @@
 # These values are ignored, they are here just to be referenced below.
 constants:
   compilers: &compilers
-    - "g++-8"
-    - "clang++-6.0"
+    - "g++-9"
+    - "clang++-10"
 
 benchmarks:
   - name:
       - "boost_di_compile_time"
+      - "boost_di_compile_memory"
       - "boost_di_incremental_compile_time"
       - "boost_di_run_time"
+      - "boost_di_startup_time"
       - "boost_di_executable_size"
     loop_factor: 1.0
     num_classes:
       - 100
+      - 250
       - 1000
     compiler: *compilers
     cxx_std: "c++14"
@@ -38,3 +41,18 @@
       - []
     benchmark_generation_flags:
       - []
+
+  - name:
+      - "boost_di_executable_size_without_exceptions_and_rtti"
+    loop_factor: 1.0
+    num_classes:
+      - 100
+      - 250
+      - 1000
+    compiler: *compilers
+    cxx_std: "c++14"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
+
diff --git a/extras/benchmark/suites/debug.yml b/extras/benchmark/suites/debug.yml
index 13d6c0b..c31d4d5 100644
--- a/extras/benchmark/suites/debug.yml
+++ b/extras/benchmark/suites/debug.yml
@@ -22,12 +22,12 @@
 # These values are ignored, they are here just to be referenced below.
 constants:
   compilers: &compilers
-    - "g++-7"
-    - "clang++-4.0"
+    - "g++-9"
+    - "clang++-10"
   gcc: &gcc
-    - "g++-7"
+    - "g++-9"
   clang: &clang
-    - "clang++-4.0"
+    - "clang++-10"
 
 benchmarks:
   - name: "fruit_single_file_compile_time"
@@ -43,16 +43,19 @@
   - name:
     - "new_delete_run_time"
     - "simple_di_compile_time"
+    - "simple_di_compile_memory"
     - "simple_di_incremental_compile_time"
     - "simple_di_run_time"
     - "simple_di_startup_time"
     - "simple_di_executable_size"
     - "simple_di_with_interfaces_compile_time"
+    - "simple_di_with_interfaces_compile_memory"
     - "simple_di_with_interfaces_incremental_compile_time"
     - "simple_di_with_interfaces_run_time"
     - "simple_di_with_interfaces_startup_time"
     - "simple_di_with_interfaces_executable_size"
     - "simple_di_with_interfaces_and_new_delete_compile_time"
+    - "simple_di_with_interfaces_and_new_delete_compile_memory"
     - "simple_di_with_interfaces_and_new_delete_incremental_compile_time"
     - "simple_di_with_interfaces_and_new_delete_run_time"
     - "simple_di_with_interfaces_and_new_delete_startup_time"
@@ -68,7 +71,22 @@
       - []
 
   - name:
+    - "simple_di_executable_size_without_exceptions_and_rtti"
+    - "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti"
+    - "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti"
+    loop_factor: 0.01
+    num_classes:
+      - 100
+    compiler: *compilers
+    cxx_std: "c++11"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
+
+  - name:
       - "fruit_compile_time"
+      - "fruit_compile_memory"
       - "fruit_incremental_compile_time"
       - "fruit_run_time"
       - "fruit_startup_time"
@@ -87,7 +105,22 @@
       - []
 
   - name:
+      - "fruit_executable_size_without_exceptions_and_rtti"
+    loop_factor: 0.01
+    num_classes:
+      - 100
+    compiler: *gcc
+    cxx_std: "c++11"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+      - ['-DFRUIT_USES_BOOST=False', '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+      - ["-DBUILD_SHARED_LIBS=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
+
+  - name:
       - "fruit_compile_time"
+      - "fruit_compile_memory"
       - "fruit_incremental_compile_time"
       - "fruit_run_time"
       - "fruit_startup_time"
@@ -104,7 +137,20 @@
       - []
 
   - name:
+      - "fruit_executable_size_without_exceptions_and_rtti"
+    loop_factor: 0.01
+    num_classes:
+      - 100
+    compiler: *clang
+    cxx_std: "c++11"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
+
+  - name:
       - "boost_di_compile_time"
+      - "boost_di_compile_memory"
       - "boost_di_incremental_compile_time"
       - "boost_di_run_time"
       - "boost_di_startup_time"
@@ -118,3 +164,15 @@
       - []
     benchmark_generation_flags:
       - []
+
+  - name:
+      - "boost_di_executable_size_without_exceptions_and_rtti"
+    loop_factor: 0.01
+    num_classes:
+      - 100
+    compiler: *compilers
+    cxx_std: "c++14"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
diff --git a/extras/benchmark/suites/fruit_full.yml b/extras/benchmark/suites/fruit_full.yml
index 32ac6d1..9709291 100644
--- a/extras/benchmark/suites/fruit_full.yml
+++ b/extras/benchmark/suites/fruit_full.yml
@@ -19,10 +19,11 @@
 # These values are ignored, they are here just to be referenced below.
 constants:
   compilers: &compilers
-    - "g++-8"
-    - "clang++-6.0"
+    - "g++-9"
+    - "clang++-10"
   num_classes: &num_classes
     - 100
+    - 250
     - 1000
 
 benchmarks:
@@ -39,10 +40,12 @@
       - []
 
   - name:
-      - "new_delete_run_time"
       - "fruit_compile_time"
+      - "fruit_compile_memory"
       - "fruit_incremental_compile_time"
       - "fruit_run_time"
+      - "fruit_startup_time"
+      - "fruit_startup_time_with_normalized_component"
       - "fruit_executable_size"
     loop_factor: 1.0
     num_classes: *num_classes
@@ -54,9 +57,23 @@
       - []
 
   - name:
+      - "fruit_executable_size_without_exceptions_and_rtti"
+    loop_factor: 1.0
+    num_classes: *num_classes
+    compiler: *compilers
+    cxx_std: "c++11"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
+
+  - name:
       - "fruit_compile_time"
+      - "fruit_compile_memory"
       - "fruit_incremental_compile_time"
       - "fruit_run_time"
+      - "fruit_startup_time"
+      - "fruit_startup_time_with_normalized_component"
       - "fruit_executable_size"
     loop_factor: 1.0
     num_classes: *num_classes
@@ -67,3 +84,15 @@
       - ["-DBUILD_SHARED_LIBS=False"]
     benchmark_generation_flags:
       - []
+
+  - name:
+      - "fruit_executable_size_without_exceptions_and_rtti"
+    loop_factor: 1.0
+    num_classes: *num_classes
+    compiler: *compilers
+    cxx_std: "c++11"
+    additional_cmake_args:
+      - ['-DFRUIT_USES_BOOST=False', '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+      - ["-DBUILD_SHARED_LIBS=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
diff --git a/extras/benchmark/suites/fruit_mostly_full.yml b/extras/benchmark/suites/fruit_mostly_full.yml
index e212ac8..f1eac70 100644
--- a/extras/benchmark/suites/fruit_mostly_full.yml
+++ b/extras/benchmark/suites/fruit_mostly_full.yml
@@ -19,11 +19,10 @@
 # These values are ignored, they are here just to be referenced below.
 constants:
   compilers: &compilers
-    - "g++-8"
-    - "clang++-6.0"
+    - "g++-9"
+    - "clang++-10"
   num_classes: &num_classes
     - 100
-    - 1000
 
 benchmarks:
   - name: "fruit_single_file_compile_time"
@@ -38,10 +37,12 @@
       - []
 
   - name:
-      - "new_delete_run_time"
       - "fruit_compile_time"
+      - "fruit_compile_memory"
       - "fruit_incremental_compile_time"
       - "fruit_run_time"
+      - "fruit_startup_time"
+      - "fruit_startup_time_with_normalized_component"
       - "fruit_executable_size"
     loop_factor: 1.0
     num_classes: *num_classes
@@ -51,3 +52,14 @@
       - []
     benchmark_generation_flags:
       - []
+
+  - name:
+      - "fruit_executable_size_without_exceptions_and_rtti"
+    loop_factor: 1.0
+    num_classes: *num_classes
+    compiler: *compilers
+    cxx_std: "c++11"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
diff --git a/extras/benchmark/suites/fruit_quick.yml b/extras/benchmark/suites/fruit_quick.yml
index 002e7e8..fd64ae7 100644
--- a/extras/benchmark/suites/fruit_quick.yml
+++ b/extras/benchmark/suites/fruit_quick.yml
@@ -19,8 +19,8 @@
 # These values are ignored, they are here just to be referenced below.
 constants:
   compilers: &compilers
-    - "g++-6"
-    - "clang++-4.0"
+    - "g++-9"
+    - "clang++-10"
   num_classes: &num_classes
     - 100
 
@@ -38,9 +38,13 @@
 
   - name:
       - "fruit_compile_time"
+      - "fruit_compile_memory"
       - "fruit_incremental_compile_time"
       - "fruit_run_time"
+      - "fruit_startup_time"
+      - "fruit_startup_time_with_normalized_component"
       - "fruit_executable_size"
+      - "fruit_executable_size_without_exceptions_and_rtti"
     loop_factor: 1.0
     num_classes: *num_classes
     compiler: *compilers
diff --git a/extras/benchmark/suites/fruit_single.yml b/extras/benchmark/suites/fruit_single.yml
index d269da9..e030c5e 100644
--- a/extras/benchmark/suites/fruit_single.yml
+++ b/extras/benchmark/suites/fruit_single.yml
@@ -21,7 +21,7 @@
 # These values are ignored, they are here just to be referenced below.
 constants:
   compilers: &compilers
-    - "g++-7"
+    - "g++-9"
 
 benchmarks:
   - name:
diff --git a/extras/benchmark/suites/simple_di_full.yml b/extras/benchmark/suites/simple_di_full.yml
index 6ed8d0f..6c104aa 100644
--- a/extras/benchmark/suites/simple_di_full.yml
+++ b/extras/benchmark/suites/simple_di_full.yml
@@ -22,33 +22,52 @@
 # These values are ignored, they are here just to be referenced below.
 constants:
   compilers: &compilers
-    - "g++-7"
-    - "clang++-4.0"
+    - "g++-9"
+    - "clang++-10"
   num_classes: &num_classes
     - 100
+    - 250
     - 1000
 
 benchmarks:
   - name:
     - "new_delete_run_time"
     - "simple_di_compile_time"
+    - "simple_di_compile_memory"
     - "simple_di_incremental_compile_time"
     - "simple_di_run_time"
+    - "simple_di_startup_time"
     - "simple_di_executable_size"
+    - "simple_di_with_interfaces_compile_memory"
     - "simple_di_with_interfaces_compile_time"
     - "simple_di_with_interfaces_incremental_compile_time"
     - "simple_di_with_interfaces_run_time"
+    - "simple_di_with_interfaces_startup_time"
     - "simple_di_with_interfaces_executable_size"
+    - "simple_di_with_interfaces_and_new_delete_compile_memory"
     - "simple_di_with_interfaces_and_new_delete_compile_time"
     - "simple_di_with_interfaces_and_new_delete_incremental_compile_time"
     - "simple_di_with_interfaces_and_new_delete_run_time"
+    - "simple_di_with_interfaces_and_new_delete_startup_time"
     - "simple_di_with_interfaces_and_new_delete_executable_size"
     loop_factor: 1.0
-    num_classes:
-      - 100
+    num_classes: *num_classes
     compiler: *compilers
     cxx_std: "c++11"
     additional_cmake_args:
       - []
     benchmark_generation_flags:
       - []
+
+  - name:
+    - "simple_di_executable_size_without_exceptions_and_rtti"
+    - "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti"
+    - "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti"
+    loop_factor: 1.0
+    num_classes: *num_classes
+    compiler: *compilers
+    cxx_std: "c++11"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
diff --git a/extras/benchmark/suites/simple_di_mostly_full.yml b/extras/benchmark/suites/simple_di_mostly_full.yml
index a833652..7ab0d00 100644
--- a/extras/benchmark/suites/simple_di_mostly_full.yml
+++ b/extras/benchmark/suites/simple_di_mostly_full.yml
@@ -22,8 +22,8 @@
 # These values are ignored, they are here just to be referenced below.
 constants:
   compilers: &compilers
-    - "g++-7"
-    - "clang++-4.0"
+    - "g++-9"
+    - "clang++-10"
   num_classes: &num_classes
     - 100
 
@@ -31,16 +31,22 @@
   - name:
     - "new_delete_run_time"
     - "simple_di_compile_time"
+    - "simple_di_compile_memory"
     - "simple_di_incremental_compile_time"
     - "simple_di_run_time"
+    - "simple_di_startup_time"
     - "simple_di_executable_size"
     - "simple_di_with_interfaces_compile_time"
+    - "simple_di_with_interfaces_compile_memory"
     - "simple_di_with_interfaces_incremental_compile_time"
     - "simple_di_with_interfaces_run_time"
+    - "simple_di_with_interfaces_startup_time"
     - "simple_di_with_interfaces_executable_size"
     - "simple_di_with_interfaces_and_new_delete_compile_time"
+    - "simple_di_with_interfaces_and_new_delete_compile_memory"
     - "simple_di_with_interfaces_and_new_delete_incremental_compile_time"
     - "simple_di_with_interfaces_and_new_delete_run_time"
+    - "simple_di_with_interfaces_and_new_delete_startup_time"
     - "simple_di_with_interfaces_and_new_delete_executable_size"
     loop_factor: 1.0
     num_classes:
@@ -51,3 +57,17 @@
       - []
     benchmark_generation_flags:
       - []
+
+  - name:
+    - "simple_di_executable_size_without_exceptions_and_rtti"
+    - "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti"
+    - "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti"
+    loop_factor: 1.0
+    num_classes:
+      - 100
+    compiler: *compilers
+    cxx_std: "c++11"
+    additional_cmake_args:
+      - ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    benchmark_generation_flags:
+      - []
diff --git a/extras/benchmark/tables/fruit_internal.yml b/extras/benchmark/tables/fruit_internal.yml
index 48ac40e..dfc7a27 100644
--- a/extras/benchmark/tables/fruit_internal.yml
+++ b/extras/benchmark/tables/fruit_internal.yml
@@ -16,120 +16,82 @@
     pretty_printer:
       format_string: "%s"
 
+allowed_unused_benchmarks:
+  - new_delete_run_time
+  - fruit_single_file_compile_time
+
+allowed_unused_benchmark_results:
+  - total_max_ram_usage
+
 tables:
-  - name: "Fruit compile time (single file)"
-    benchmark_filter:
-      name: "fruit_single_file_compile_time"
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns: *num_bindings_column
-    rows: *compiler_name_row
-    results:
-      dimension: "compile_time"
-      unit: "seconds"
-  
-  - name: "Fruit compile time"
-    benchmark_filter:
-      name: "fruit_compile_time"
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns: *num_classes_column
-    rows: *compiler_name_row
-    results:
-      dimension: "compile_time"
-      unit: "seconds"
 
-  - name: "Fruit incremental compile time"
-    benchmark_filter:
-      name: "fruit_incremental_compile_time"
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns: *num_classes_column
-    rows: *compiler_name_row
-    results:
-      dimension: "compile_time"
-      unit: "seconds"
+  # Fruit vs Boost.DI and "no DI"
 
-  - name: "Fruit full injection time"
+  - name: "Compile time (Clang)"
     benchmark_filter:
-      name: "fruit_run_time"
       benchmark_generation_flags: []
       additional_cmake_args: []
-    columns: *num_classes_column
-    rows: *compiler_name_row
-    results:
-      dimension: "Full injection time"
-      unit: "seconds"
-
-  - name: "Fruit component normalization time"
-    benchmark_filter:
-      name: "fruit_run_time"
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns: *num_classes_column
-    rows: *compiler_name_row
-    results:
-      dimension: "componentNormalizationTime"
-      unit: "seconds"
-
-  - name: "Fruit setup time"
-    benchmark_filter:
-      name: "fruit_run_time"
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns: *num_classes_column
-    rows: *compiler_name_row
-    results:
-      dimension: "Total for setup"
-      unit: "seconds"
-
-  - name: "Fruit per-request time"
-    benchmark_filter:
-      name: "fruit_run_time"
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns: *num_classes_column
-    rows: *compiler_name_row
-    results:
-      dimension: "Total per request"
-      unit: "seconds"
-  
-  - name: "New/delete time"
-    benchmark_filter: 
-      name: "new_delete_run_time"
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns: *num_classes_column
-    rows: *compiler_name_row
-    results:
-      dimension: "Total"
-      unit: "seconds"
-    
-  - name: "Compile time (100 classes)"
-    benchmark_filter:
-      num_classes: 100
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns:
+      compiler: "clang++-10"
+      name: [
+        "fruit_compile_time",
+        "boost_di_compile_time",
+        "simple_di_compile_time",
+        "simple_di_with_interfaces_compile_time",
+        "simple_di_with_interfaces_and_new_delete_compile_time",
+      ]
+    rows:
       dimension: "name"
       pretty_printer:
         fixed_map:
           "fruit_compile_time": "Fruit"
           "boost_di_compile_time": "Boost.DI"
-          "simple_di_incremental_compile_time": "Simple DI"
-          "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
+          "simple_di_compile_time": "Simple DI"
+          "simple_di_with_interfaces_compile_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_compile_time": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
     results:
       dimension: "compile_time"
       unit: "seconds"
-  
-  - name: "Incremental compile time (100 classes)"
+
+  - name: "Compile time (GCC)"
     benchmark_filter:
-      num_classes: 100
       benchmark_generation_flags: []
       additional_cmake_args: []
-    columns:
+      compiler: "g++-9"
+      name: [
+        "fruit_compile_time",
+        "boost_di_compile_time",
+        "simple_di_compile_time",
+        "simple_di_with_interfaces_compile_time",
+        "simple_di_with_interfaces_and_new_delete_compile_time",
+      ]
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_compile_time": "Fruit"
+          "boost_di_compile_time": "Boost.DI"
+          "simple_di_compile_time": "Simple DI"
+          "simple_di_with_interfaces_compile_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_compile_time": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "compile_time"
+      unit: "seconds"
+
+  - name: "Incremental compile time (Clang)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+      compiler: "clang++-10"
+      name: [
+        "fruit_incremental_compile_time",
+        "boost_di_incremental_compile_time",
+        "simple_di_incremental_compile_time",
+        "simple_di_with_interfaces_incremental_compile_time",
+        "simple_di_with_interfaces_and_new_delete_incremental_compile_time",
+      ]
+    rows:
       dimension: "name"
       pretty_printer:
         fixed_map:
@@ -138,17 +100,199 @@
           "simple_di_incremental_compile_time": "Simple DI"
           "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces"
           "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
+    columns: *num_classes_column
     results:
-      dimension: "compile_time"
+      dimension: "incremental_compile_time"
       unit: "seconds"
 
-  - name: "Fruit full injection time (100 classes)"
+  - name: "Incremental compile time (GCC)"
     benchmark_filter:
-      num_classes: 100
       benchmark_generation_flags: []
       additional_cmake_args: []
-    columns:
+      compiler: "g++-9"
+      name: [
+        "fruit_incremental_compile_time",
+        "boost_di_incremental_compile_time",
+        "simple_di_incremental_compile_time",
+        "simple_di_with_interfaces_incremental_compile_time",
+        "simple_di_with_interfaces_and_new_delete_incremental_compile_time",
+      ]
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_incremental_compile_time": "Fruit"
+          "boost_di_incremental_compile_time": "Boost.DI"
+          "simple_di_incremental_compile_time": "Simple DI"
+          "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "incremental_compile_time"
+      unit: "seconds"
+
+  - name: "Compile memory (Clang)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+      compiler: "clang++-10"
+      name: [
+        "fruit_compile_memory",
+        "boost_di_compile_memory",
+        "simple_di_compile_memory",
+        "simple_di_with_interfaces_compile_memory",
+        "simple_di_with_interfaces_and_new_delete_compile_memory",
+      ]
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_compile_memory": "Fruit"
+          "boost_di_compile_memory": "Boost.DI"
+          "simple_di_compile_memory": "Simple DI"
+          "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "max_ram_usage"
+      unit: "bytes"
+
+  - name: "Compile memory (GCC)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+      compiler: "g++-9"
+      name: [
+        "fruit_compile_memory",
+        "boost_di_compile_memory",
+        "simple_di_compile_memory",
+        "simple_di_with_interfaces_compile_memory",
+        "simple_di_with_interfaces_and_new_delete_compile_memory",
+      ]
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_compile_memory": "Fruit"
+          "boost_di_compile_memory": "Boost.DI"
+          "simple_di_compile_memory": "Simple DI"
+          "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "max_ram_usage"
+      unit: "bytes"
+
+  - name: "Startup time (Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+      name: [
+        "fruit_startup_time",
+        "boost_di_startup_time",
+        "simple_di_startup_time",
+        "simple_di_with_interfaces_startup_time",
+        "simple_di_with_interfaces_and_new_delete_startup_time",
+      ]
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_startup_time": "Fruit"
+          "boost_di_startup_time": "Boost.DI"
+          "simple_di_startup_time": "Simple DI"
+          "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "startup_time"
+      unit: "seconds"
+
+  - name: "Startup time (GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+      name: [
+        "fruit_startup_time",
+        "boost_di_startup_time",
+        "simple_di_startup_time",
+        "simple_di_with_interfaces_startup_time",
+        "simple_di_with_interfaces_and_new_delete_startup_time",
+      ]
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_startup_time": "Fruit"
+          "boost_di_startup_time": "Boost.DI"
+          "simple_di_startup_time": "Simple DI"
+          "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "startup_time"
+      unit: "seconds"
+
+  - name: "Startup time with normalized component (Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+      name: [
+        "fruit_startup_time_with_normalized_component",
+        "boost_di_startup_time_with_normalized_component",
+        "simple_di_startup_time_with_normalized_component",
+        "simple_di_with_interfaces_startup_time_with_normalized_component",
+        "simple_di_with_interfaces_and_new_delete_startup_time_with_normalized_component",
+      ]
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_startup_time_with_normalized_component": "Fruit"
+          "boost_di_startup_time_with_normalized_component": "Boost.DI"
+          "simple_di_startup_time_with_normalized_component": "Simple DI"
+          "simple_di_with_interfaces_startup_time_with_normalized_component": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_startup_time_with_normalized_component": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "fruit_startup_time_with_normalized_component"
+      unit: "seconds"
+
+  - name: "Startup time with normalized component (GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+      name: [
+        "fruit_startup_time_with_normalized_component",
+        "boost_di_startup_time_with_normalized_component",
+        "simple_di_startup_time_with_normalized_component",
+        "simple_di_with_interfaces_startup_time_with_normalized_component",
+        "simple_di_with_interfaces_and_new_delete_startup_time_with_normalized_component",
+      ]
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_startup_time_with_normalized_component": "Fruit"
+          "boost_di_startup_time_with_normalized_component": "Boost.DI"
+          "simple_di_startup_time_with_normalized_component": "Simple DI"
+          "simple_di_with_interfaces_startup_time_with_normalized_component": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_startup_time_with_normalized_component": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "fruit_startup_time_with_normalized_component"
+      unit: "seconds"
+
+  - name: "Component normalization time (Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+    rows:
       dimension: "name"
       pretty_printer:
         fixed_map:
@@ -157,37 +301,17 @@
           "simple_di_incremental_run_time": "Simple DI"
           "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces"
           "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
-    results:
-      dimension: "Full injection time"
-      unit: "seconds"
-
-  - name: "Fruit component normalization time (100 classes)"
-    benchmark_filter:
-      num_classes: 100
-      benchmark_generation_flags: []
-      additional_cmake_args: []
-    columns:
-      dimension: "name"
-      pretty_printer:
-        fixed_map:
-          "fruit_run_time": "Fruit"
-          "boost_di_run_time": "Boost.DI"
-          "simple_di_incremental_run_time": "Simple DI"
-          "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
+    columns: *num_classes_column
     results:
       dimension: "componentNormalizationTime"
       unit: "seconds"
 
-
-  - name: "Setup time (100 classes)"
+  - name: "Component normalization time (GCC)"
     benchmark_filter:
-      num_classes: 100
+      compiler: "g++-9"
       benchmark_generation_flags: []
       additional_cmake_args: []
-    columns:
+    rows:
       dimension: "name"
       pretty_printer:
         fixed_map:
@@ -196,45 +320,427 @@
           "simple_di_incremental_run_time": "Simple DI"
           "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces"
           "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
+    columns: *num_classes_column
     results:
-      dimension: "Total for setup"
+      dimension: "componentNormalizationTime"
       unit: "seconds"
 
-  - name: "Per-request time (100 classes)"
+  - name: "Per-request time (Clang)"
     benchmark_filter:
-      num_classes: 100
+      compiler: "clang++-10"
       benchmark_generation_flags: []
       additional_cmake_args: []
-    columns:
+    rows:
       dimension: "name"
       pretty_printer:
         fixed_map:
           "fruit_run_time": "Fruit"
           "boost_di_run_time": "Boost.DI"
-          "simple_di_incremental_run_time": "Simple DI"
-          "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
+          "simple_di_run_time": "Simple DI"
+          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
     results:
       dimension: "Total per request"
       unit: "seconds"
-  
-  - name: "Executable size (stripped, 100 classes)"
+
+  - name: "Per-request time (GCC)"
     benchmark_filter:
-      num_classes: 100
+      compiler: "g++-9"
       benchmark_generation_flags: []
       additional_cmake_args: []
-    columns:
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_run_time": "Fruit"
+          "boost_di_run_time": "Boost.DI"
+          "simple_di_run_time": "Simple DI"
+          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "Total per request"
+      unit: "seconds"
+
+  - name: "Executable size (stripped, Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+    rows:
       dimension: "name"
       pretty_printer:
         fixed_map:
           "fruit_executable_size": "Fruit"
           "boost_di_executable_size": "Boost.DI"
-          "simple_di_incremental_run_time": "Simple DI"
-          "simple_di_with_interfaces_incremental_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_incremental_run_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
+          "simple_di_executable_size": "Simple DI"
+          "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Executable size (stripped, GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      additional_cmake_args: []
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_executable_size": "Fruit"
+          "boost_di_executable_size": "Boost.DI"
+          "simple_di_executable_size": "Simple DI"
+          "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Executable size (stripped, no exceptions/RTTI, Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_executable_size_without_exceptions_and_rtti": "Fruit"
+          "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI"
+          "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI"
+          "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Executable size (stripped, no exceptions/RTTI, GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+    rows:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_executable_size_without_exceptions_and_rtti": "Fruit"
+          "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI"
+          "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI"
+          "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete"
+    columns: *num_classes_column
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  # Fruit: performance by default and with various compiler options.
+
+  - name: "Fruit compile time (Clang)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      compiler: "clang++-10"
+      name: "fruit_compile_time"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "compile_time"
+      unit: "seconds"
+
+  - name: "Fruit compile time (GCC)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      compiler: "g++-9"
+      name: "fruit_compile_time"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "compile_time"
+      unit: "seconds"
+
+  - name: "Fruit incremental compile time (Clang)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      compiler: "clang++-10"
+      name: "fruit_incremental_compile_time"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "incremental_compile_time"
+      unit: "seconds"
+
+  - name: "Fruit incremental compile time (GCC)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      compiler: "g++-9"
+      name: "fruit_incremental_compile_time"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "incremental_compile_time"
+      unit: "seconds"
+
+  - name: "Fruit compile memory (Clang)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      compiler: "clang++-10"
+      name: "fruit_compile_memory"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "max_ram_usage"
+      unit: "bytes"
+
+  - name: "Fruit compile memory (GCC)"
+    benchmark_filter:
+      benchmark_generation_flags: []
+      compiler: "g++-9"
+      name: "fruit_compile_memory"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "max_ram_usage"
+      unit: "bytes"
+
+  - name: "Fruit startup time (Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      name: "fruit_startup_time"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "startup_time"
+      unit: "seconds"
+
+  - name: "Fruit startup time (GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      name: "fruit_startup_time"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "startup_time"
+      unit: "seconds"
+
+  - name: "Fruit startup time with normalized component (Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      name: "fruit_startup_time_with_normalized_component"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "startup_time"
+      unit: "seconds"
+
+  - name: "Fruit startup time with normalized component (GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      name: "fruit_startup_time_with_normalized_component"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "startup_time"
+      unit: "seconds"
+
+  - name: "Fruit component normalization time (Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "componentNormalizationTime"
+      unit: "seconds"
+
+  - name: "Fruit component normalization time (GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "componentNormalizationTime"
+      unit: "seconds"
+
+  - name: "Fruit per-request time (Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      name: "fruit_run_time"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "Total per request"
+      unit: "seconds"
+
+  - name: "Fruit per-request time (GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      name: "fruit_run_time"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "Total per request"
+      unit: "seconds"
+
+  - name: "Fruit executable size (stripped, Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      name: "fruit_executable_size"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Fruit executable size (stripped, GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      name: "fruit_executable_size"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple []: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False"]: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False"]: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Fruit executable size (stripped, no exceptions/RTTI, Clang)"
+    benchmark_filter:
+      compiler: "clang++-10"
+      benchmark_generation_flags: []
+      name: "fruit_executable_size_without_exceptions_and_rtti"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "without boost"
+    columns: *num_classes_column
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Fruit executable size (stripped, no exceptions/RTTI, GCC)"
+    benchmark_filter:
+      compiler: "g++-9"
+      benchmark_generation_flags: []
+      name: "fruit_executable_size_without_exceptions_and_rtti"
+    rows:
+      dimension: "additional_cmake_args"
+      pretty_printer:
+        fixed_map:
+          !!python/tuple ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "(defaults)"
+          !!python/tuple ["-DBUILD_SHARED_LIBS=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "statically linked"
+          !!python/tuple ["-DFRUIT_USES_BOOST=False", '-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']: "without boost"
+    columns: *num_classes_column
     results:
       dimension: "num_bytes"
       unit: "bytes"
diff --git a/extras/benchmark/tables/fruit_wiki.yml b/extras/benchmark/tables/fruit_wiki.yml
index 0af3b3e..28bdccf 100644
--- a/extras/benchmark/tables/fruit_wiki.yml
+++ b/extras/benchmark/tables/fruit_wiki.yml
@@ -41,26 +41,15 @@
       dimension: "compile_time"
       unit: "seconds"
 
-  - name: "Fruit full injection time"
+  - name: "Fruit startup time"
     benchmark_filter:
-      name: "fruit_run_time"
+      name: "fruit_startup_time"
       additional_cmake_args: []
       benchmark_generation_flags: []
     columns: *num_classes_column
     rows: *compiler_name_row
     results:
-      dimension: "Full injection time"
-      unit: "seconds"
-
-  - name: "Fruit setup time"
-    benchmark_filter:
-      name: "fruit_run_time"
-      additional_cmake_args: []
-      benchmark_generation_flags: []
-    columns: *num_classes_column
-    rows: *compiler_name_row
-    results:
-      dimension: "Total for setup"
+      dimension: "startup_time"
       unit: "seconds"
 
   - name: "Fruit per-request time"
@@ -92,6 +81,39 @@
       num_classes: 100
       additional_cmake_args: []
       benchmark_generation_flags: []
+      name: [
+        "fruit_compile_time",
+        "boost_di_compile_time",
+        "simple_di_compile_time",
+        "simple_di_with_interfaces_compile_time",
+        "simple_di_with_interfaces_and_new_delete_compile_time",
+      ]
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_compile_time": "Fruit"
+          "boost_di_compile_time": "Boost.DI"
+          "simple_di_compile_time": "Simple DI"
+          "simple_di_with_interfaces_compile_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_compile_time": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "compile_time"
+      unit: "seconds"
+
+  - name: "Compile time (250 classes)"
+    benchmark_filter:
+      num_classes: 250
+      additional_cmake_args: []
+      benchmark_generation_flags: []
+      name: [
+        "fruit_compile_time",
+        "boost_di_compile_time",
+        "simple_di_compile_time",
+        "simple_di_with_interfaces_compile_time",
+        "simple_di_with_interfaces_and_new_delete_compile_time",
+      ]
     columns:
       dimension: "name"
       pretty_printer:
@@ -111,6 +133,13 @@
       num_classes: 1000
       additional_cmake_args: []
       benchmark_generation_flags: []
+      name: [
+        "fruit_compile_time",
+        "boost_di_compile_time",
+        "simple_di_compile_time",
+        "simple_di_with_interfaces_compile_time",
+        "simple_di_with_interfaces_and_new_delete_compile_time",
+      ]
     columns:
       dimension: "name"
       pretty_printer:
@@ -130,6 +159,13 @@
       num_classes: 100
       additional_cmake_args: []
       benchmark_generation_flags: []
+      name: [
+        "fruit_incremental_compile_time",
+        "boost_di_incremental_compile_time",
+        "simple_di_incremental_compile_time",
+        "simple_di_with_interfaces_incremental_compile_time",
+        "simple_di_with_interfaces_and_new_delete_incremental_compile_time",
+      ]
     columns:
       dimension: "name"
       pretty_printer:
@@ -141,7 +177,33 @@
           "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete"
     rows: *compiler_name_row
     results:
-      dimension: "compile_time"
+      dimension: "incremental_compile_time"
+      unit: "seconds"
+
+  - name: "Incremental compile time (250 classes)"
+    benchmark_filter:
+      num_classes: 250
+      additional_cmake_args: []
+      benchmark_generation_flags: []
+      name: [
+        "fruit_incremental_compile_time",
+        "boost_di_incremental_compile_time",
+        "simple_di_incremental_compile_time",
+        "simple_di_with_interfaces_incremental_compile_time",
+        "simple_di_with_interfaces_and_new_delete_incremental_compile_time",
+      ]
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_incremental_compile_time": "Fruit"
+          "boost_di_incremental_compile_time": "Boost.DI"
+          "simple_di_incremental_compile_time": "Simple DI"
+          "simple_di_with_interfaces_incremental_compile_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "incremental_compile_time"
       unit: "seconds"
 
   - name: "Incremental compile time (1000 classes)"
@@ -149,6 +211,13 @@
       num_classes: 1000
       additional_cmake_args: []
       benchmark_generation_flags: []
+      name: [
+        "fruit_incremental_compile_time",
+        "boost_di_incremental_compile_time",
+        "simple_di_incremental_compile_time",
+        "simple_di_with_interfaces_incremental_compile_time",
+        "simple_di_with_interfaces_and_new_delete_incremental_compile_time",
+      ]
     columns:
       dimension: "name"
       pretty_printer:
@@ -160,10 +229,88 @@
           "simple_di_with_interfaces_and_new_delete_incremental_compile_time": "Simple DI w/ interfaces, new/delete"
     rows: *compiler_name_row
     results:
-      dimension: "compile_time"
+      dimension: "incremental_compile_time"
       unit: "seconds"
 
-  - name: "Full injection time (100 classes)"
+  - name: "Compile memory (100 classes)"
+    benchmark_filter:
+      num_classes: 100
+      additional_cmake_args: []
+      benchmark_generation_flags: []
+      name: [
+        "fruit_compile_memory",
+        "boost_di_compile_memory",
+        "simple_di_compile_memory",
+        "simple_di_with_interfaces_compile_memory",
+        "simple_di_with_interfaces_and_new_delete_compile_memory",
+      ]
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_compile_memory": "Fruit"
+          "boost_di_compile_memory": "Boost.DI"
+          "simple_di_compile_memory": "Simple DI"
+          "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "max_ram_usage"
+      unit: "bytes"
+
+  - name: "Compile memory (250 classes)"
+    benchmark_filter:
+      num_classes: 250
+      additional_cmake_args: []
+      benchmark_generation_flags: []
+      name: [
+        "fruit_compile_memory",
+        "boost_di_compile_memory",
+        "simple_di_compile_memory",
+        "simple_di_with_interfaces_compile_memory",
+        "simple_di_with_interfaces_and_new_delete_compile_memory",
+      ]
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_compile_memory": "Fruit"
+          "boost_di_compile_memory": "Boost.DI"
+          "simple_di_compile_memory": "Simple DI"
+          "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "max_ram_usage"
+      unit: "bytes"
+
+  - name: "Compile memory (1000 classes)"
+    benchmark_filter:
+      num_classes: 1000
+      additional_cmake_args: []
+      benchmark_generation_flags: []
+      name: [
+        "fruit_compile_memory",
+        "boost_di_compile_memory",
+        "simple_di_compile_memory",
+        "simple_di_with_interfaces_compile_memory",
+        "simple_di_with_interfaces_and_new_delete_compile_memory",
+      ]
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_compile_memory": "Fruit"
+          "boost_di_compile_memory": "Boost.DI"
+          "simple_di_compile_memory": "Simple DI"
+          "simple_di_with_interfaces_compile_memory": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_compile_memory": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "max_ram_usage"
+      unit: "bytes"
+
+  - name: "Startup time (100 classes)"
     benchmark_filter:
       num_classes: 100
       additional_cmake_args: []
@@ -172,17 +319,38 @@
       dimension: "name"
       pretty_printer:
         fixed_map:
-          "fruit_run_time": "Fruit"
-          "boost_di_run_time": "Boost.DI"
-          "simple_di_run_time": "Simple DI"
-          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
+          "fruit_startup_time": "Fruit"
+          "fruit_startup_time_with_normalized_component": "Fruit (with normalized component)"
+          "boost_di_startup_time": "Boost.DI"
+          "simple_di_startup_time": "Simple DI"
+          "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete"
     rows: *compiler_name_row
     results:
-      dimension: "Full injection time"
+      dimension: "startup_time"
       unit: "seconds"
 
-  - name: "Full injection time (1000 classes)"
+  - name: "Startup time (250 classes)"
+    benchmark_filter:
+      num_classes: 250
+      additional_cmake_args: []
+      benchmark_generation_flags: []
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_startup_time": "Fruit"
+          "fruit_startup_time_with_normalized_component": "Fruit (with normalized component)"
+          "boost_di_startup_time": "Boost.DI"
+          "simple_di_startup_time": "Simple DI"
+          "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "startup_time"
+      unit: "seconds"
+
+  - name: "Startup time (1000 classes)"
     benchmark_filter:
       num_classes: 1000
       additional_cmake_args: []
@@ -191,52 +359,15 @@
       dimension: "name"
       pretty_printer:
         fixed_map:
-          "fruit_run_time": "Fruit"
-          "boost_di_run_time": "Boost.DI"
-          "simple_di_run_time": "Simple DI"
-          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
+          "fruit_startup_time": "Fruit"
+          "fruit_startup_time_with_normalized_component": "Fruit (with normalized component)"
+          "boost_di_startup_time": "Boost.DI"
+          "simple_di_startup_time": "Simple DI"
+          "simple_di_with_interfaces_startup_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_startup_time": "Simple DI w/ interfaces, new/delete"
     rows: *compiler_name_row
     results:
-      dimension: "Full injection time"
-      unit: "seconds"
-
-  - name: "Setup time (100 classes)"
-    benchmark_filter:
-      num_classes: 100
-      additional_cmake_args: []
-      benchmark_generation_flags: []
-    columns:
-      dimension: "name"
-      pretty_printer:
-        fixed_map:
-          "fruit_run_time": "Fruit"
-          "boost_di_run_time": "Boost.DI"
-          "simple_di_run_time": "Simple DI"
-          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
-    results:
-      dimension: "Total for setup"
-      unit: "seconds"
-  
-  - name: "Setup time (1000 classes)"
-    benchmark_filter:
-      num_classes: 1000
-      additional_cmake_args: []
-      benchmark_generation_flags: []
-    columns:
-      dimension: "name"
-      pretty_printer:
-        fixed_map:
-          "fruit_run_time": "Fruit"
-          "boost_di_run_time": "Boost.DI"
-          "simple_di_run_time": "Simple DI"
-          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
-    rows: *compiler_name_row
-    results:
-      dimension: "Total for setup"
+      dimension: "startup_time"
       unit: "seconds"
 
   - name: "Per-request time (100 classes)"
@@ -258,6 +389,25 @@
       dimension: "Total per request"
       unit: "seconds"
 
+  - name: "Per-request time (250 classes)"
+    benchmark_filter:
+      num_classes: 250
+      additional_cmake_args: []
+      benchmark_generation_flags: []
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_run_time": "Fruit"
+          "boost_di_run_time": "Boost.DI"
+          "simple_di_run_time": "Simple DI"
+          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "Total per request"
+      unit: "seconds"
+
   - name: "Per-request time (1000 classes)"
     benchmark_filter:
       num_classes: 1000
@@ -288,9 +438,28 @@
         fixed_map:
           "fruit_executable_size": "Fruit"
           "boost_di_executable_size": "Boost.DI"
-          "simple_di_run_time": "Simple DI"
-          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
+          "simple_di_executable_size": "Simple DI"
+          "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Executable size (stripped, 250 classes)"
+    benchmark_filter:
+      num_classes: 250
+      additional_cmake_args: []
+      benchmark_generation_flags: []
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_executable_size": "Fruit"
+          "boost_di_executable_size": "Boost.DI"
+          "simple_di_executable_size": "Simple DI"
+          "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete"
     rows: *compiler_name_row
     results:
       dimension: "num_bytes"
@@ -307,9 +476,67 @@
         fixed_map:
           "fruit_executable_size": "Fruit"
           "boost_di_executable_size": "Boost.DI"
-          "simple_di_run_time": "Simple DI"
-          "simple_di_with_interfaces_run_time": "Simple DI w/ interfaces"
-          "simple_di_with_interfaces_and_new_delete_run_time": "Simple DI w/ interfaces, new/delete"
+          "simple_di_executable_size": "Simple DI"
+          "simple_di_with_interfaces_executable_size": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+
+  - name: "Executable size (stripped, 100 classes, no exceptions/rtti)"
+    benchmark_filter:
+      num_classes: 100
+      additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+      benchmark_generation_flags: []
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_executable_size_without_exceptions_and_rtti": "Fruit"
+          "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI"
+          "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI"
+          "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Executable size (stripped, 250 classes, no exceptions/rtti)"
+    benchmark_filter:
+      num_classes: 250
+      additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+      benchmark_generation_flags: []
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_executable_size_without_exceptions_and_rtti": "Fruit"
+          "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI"
+          "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI"
+          "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete"
+    rows: *compiler_name_row
+    results:
+      dimension: "num_bytes"
+      unit: "bytes"
+
+  - name: "Executable size (stripped, 1000 classes, no exceptions/rtti)"
+    benchmark_filter:
+      num_classes: 1000
+      additional_cmake_args: ['-DCMAKE_CXX_FLAGS=-fno-exceptions -fno-rtti']
+      benchmark_generation_flags: []
+    columns:
+      dimension: "name"
+      pretty_printer:
+        fixed_map:
+          "fruit_executable_size_without_exceptions_and_rtti": "Fruit"
+          "boost_di_executable_size_without_exceptions_and_rtti": "Boost.DI"
+          "simple_di_executable_size_without_exceptions_and_rtti": "Simple DI"
+          "simple_di_with_interfaces_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces"
+          "simple_di_with_interfaces_and_new_delete_executable_size_without_exceptions_and_rtti": "Simple DI w/ interfaces, new/delete"
     rows: *compiler_name_row
     results:
       dimension: "num_bytes"
@@ -338,10 +565,10 @@
       dimension: "compile_time"
       unit: "seconds"
 
-  - name: "Full injection time (100 classes)"
+  - name: "Startup time (100 classes)"
     benchmark_filter:
       num_classes: 100
-      name: "fruit_run_time"
+      name: "fruit_startup_time"
       benchmark_generation_flags: []
     columns:
       dimension: "additional_cmake_args"
@@ -355,13 +582,13 @@
             to: "Statically-linking with Fruit"
     rows: *compiler_name_row
     results:
-      dimension: "Full injection time"
+      dimension: "startup_time"
       unit: "seconds"
 
-  - name: "Setup time (100 classes)"
+  - name: "Startup time (100 classes)"
     benchmark_filter:
       num_classes: 100
-      name: "fruit_run_time"
+      name: "fruit_startup_time"
       benchmark_generation_flags: []
     columns:
       dimension: "additional_cmake_args"
@@ -375,7 +602,7 @@
             to: "Statically-linking with Fruit"
     rows: *compiler_name_row
     results:
-      dimension: "Total for setup"
+      dimension: "startup_time"
       unit: "seconds"
 
   - name: "Per-request time (100 classes)"
diff --git a/extras/dockerfiles/.dockerignore b/extras/dockerfiles/.dockerignore
new file mode 100644
index 0000000..4e1954c
--- /dev/null
+++ b/extras/dockerfiles/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile.*
+rebuild_all.sh
diff --git a/extras/dockerfiles/Dockerfile.ubuntu-16.04 b/extras/dockerfiles/Dockerfile.ubuntu-16.04
deleted file mode 100644
index b53b883..0000000
--- a/extras/dockerfiles/Dockerfile.ubuntu-16.04
+++ /dev/null
@@ -1,9 +0,0 @@
-FROM ubuntu:16.04
-MAINTAINER Marco Poletti <poletti.marco@gmail.com>
-
-COPY ubuntu-16.04_custom.list /etc/apt/sources.list.d/
-COPY common_install.sh common_cleanup.sh ubuntu-16.04_install.sh /
-
-RUN bash -x /common_install.sh && \
-    bash -x /ubuntu-16.04_install.sh && \
-    bash -x /common_cleanup.sh
diff --git a/extras/dockerfiles/Dockerfile.ubuntu-18.04 b/extras/dockerfiles/Dockerfile.ubuntu-18.04
index ec5d5cb..d458bb4 100644
--- a/extras/dockerfiles/Dockerfile.ubuntu-18.04
+++ b/extras/dockerfiles/Dockerfile.ubuntu-18.04
@@ -1,9 +1,53 @@
 FROM ubuntu:18.04
 MAINTAINER Marco Poletti <poletti.marco@gmail.com>
 
-COPY ubuntu-18.04_custom.list /etc/apt/sources.list.d/
-COPY common_install.sh common_cleanup.sh ubuntu-18.04_install.sh /
+COPY common_install.sh common_cleanup.sh /
 
-RUN bash -x /common_install.sh && \
-    bash -x /ubuntu-18.04_install.sh && \
-    bash -x /common_cleanup.sh
+RUN bash -x /common_install.sh
+RUN apt-get install -y --no-install-recommends curl
+
+# For the Bazel repository
+RUN curl https://bazel.build/bazel-release.pub.gpg | apt-key add -
+
+RUN echo 'deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8' >> /etc/apt/sources.list.d/bazel.list
+
+COPY ubuntu-18.04_custom.list /etc/apt/sources.list.d/
+
+RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys F23C5A6CF475977595C89F51BA6932366A755776
+
+RUN apt-get update -qq
+
+RUN apt-get remove -y python3-pip
+RUN python3 -m easy_install pip
+
+RUN apt-get install -y --allow-unauthenticated --no-install-recommends \
+        g++-8 \
+        g++-7 \
+        g++-6 \
+        g++-5 \
+        clang-3.9 \
+        clang-4.0 \
+        clang-5.0 \
+        clang-6.0 \
+        clang-7 \
+        clang-8 \
+        clang-9 \
+        clang-10 \
+        bazel \
+        git \
+        python3.8 \
+        clang-tidy \
+        clang-format
+
+RUN python3.8 -m easy_install pip
+
+RUN pip3 install absl-py
+RUN pip3 install bidict
+RUN pip3 install pytest
+RUN pip3 install pytest-xdist
+RUN pip3 install sh
+RUN pip3 install setuptools
+RUN pip3 install networkx
+RUN pip3 install wheel
+
+RUN bash -x /common_cleanup.sh
diff --git a/extras/dockerfiles/Dockerfile.ubuntu-19.04 b/extras/dockerfiles/Dockerfile.ubuntu-19.04
deleted file mode 100644
index 7939990..0000000
--- a/extras/dockerfiles/Dockerfile.ubuntu-19.04
+++ /dev/null
@@ -1,9 +0,0 @@
-FROM ubuntu:19.04
-MAINTAINER Marco Poletti <poletti.marco@gmail.com>
-
-COPY ubuntu-19.04_custom.list /etc/apt/sources.list.d/
-COPY common_install.sh common_cleanup.sh ubuntu-19.04_install.sh /
-
-RUN bash -x /common_install.sh && \
-    bash -x /ubuntu-19.04_install.sh && \
-    bash -x /common_cleanup.sh
diff --git a/extras/dockerfiles/Dockerfile.ubuntu-19.10 b/extras/dockerfiles/Dockerfile.ubuntu-19.10
index 5ee6178..ca6be96 100644
--- a/extras/dockerfiles/Dockerfile.ubuntu-19.10
+++ b/extras/dockerfiles/Dockerfile.ubuntu-19.10
@@ -1,9 +1,40 @@
 FROM ubuntu:19.10
 MAINTAINER Marco Poletti <poletti.marco@gmail.com>
 
-COPY ubuntu-19.10_custom.list /etc/apt/sources.list.d/
-COPY common_install.sh common_cleanup.sh ubuntu-19.10_install.sh /
+COPY common_install.sh common_cleanup.sh /
 
-RUN bash -x /common_install.sh && \
-    bash -x /ubuntu-19.10_install.sh && \
-    bash -x /common_cleanup.sh
+RUN bash -x /common_install.sh
+
+COPY ubuntu-19.10_custom.list /etc/apt/sources.list.d/
+
+RUN apt-get update
+
+RUN apt-get install -y --allow-unauthenticated --no-install-recommends \
+        g++-7 \
+        g++-8 \
+        g++-9 \
+        clang-6.0 \
+        clang-7 \
+        clang-8 \
+        clang-9 \
+        clang-10 \
+        python3-sh \
+        python3-typed-ast \
+        python3-pip \
+        python3-setuptools \
+        python3-networkx \
+        clang-tidy \
+        clang-format
+
+RUN pip3 install --upgrade pip
+
+RUN pip3 install absl-py
+RUN pip3 install bidict
+RUN pip3 install pytest
+RUN pip3 install pytest-xdist
+RUN pip3 install sh
+RUN pip3 install setuptools
+RUN pip3 install networkx
+RUN pip3 install wheel
+
+RUN bash -x /common_cleanup.sh
diff --git a/extras/dockerfiles/Dockerfile.ubuntu-20.04 b/extras/dockerfiles/Dockerfile.ubuntu-20.04
new file mode 100644
index 0000000..3ce7d9c
--- /dev/null
+++ b/extras/dockerfiles/Dockerfile.ubuntu-20.04
@@ -0,0 +1,41 @@
+FROM ubuntu:20.04
+MAINTAINER Marco Poletti <poletti.marco@gmail.com>
+
+COPY common_install.sh common_cleanup.sh /
+
+RUN bash -x /common_install.sh
+
+COPY ubuntu-20.04_custom.list /etc/apt/sources.list.d/
+
+RUN apt-get update
+
+RUN apt-get remove -y python3-pip
+RUN python3 -m easy_install pip
+
+RUN apt-get install -y --allow-unauthenticated --no-install-recommends \
+        g++-7 \
+        g++-8 \
+        g++-9 \
+        g++-10 \
+        clang-6.0 \
+        clang-7 \
+        clang-8 \
+        clang-9 \
+        clang-10 \
+        python3.8 \
+        python3.8-distutils \
+        clang-tidy \
+        clang-format
+
+RUN python3.8 -m easy_install pip
+
+RUN pip3 install absl-py
+RUN pip3 install bidict
+RUN pip3 install pytest
+RUN pip3 install pytest-xdist
+RUN pip3 install sh
+RUN pip3 install setuptools
+RUN pip3 install networkx
+RUN pip3 install wheel
+
+RUN bash -x /common_cleanup.sh
diff --git a/extras/dockerfiles/Dockerfile.ubuntu_arm-16.04 b/extras/dockerfiles/Dockerfile.ubuntu_arm-16.04
deleted file mode 100644
index 35342b9..0000000
--- a/extras/dockerfiles/Dockerfile.ubuntu_arm-16.04
+++ /dev/null
@@ -1,9 +0,0 @@
-FROM multiarch/ubuntu-core:arm64-xenial
-MAINTAINER Marco Poletti <poletti.marco@gmail.com>
-
-COPY ubuntu_arm-16.04_custom.list /etc/apt/sources.list.d/
-COPY common_install.sh common_cleanup.sh ubuntu_arm-16.04_install.sh /
-
-RUN bash -x /common_install.sh && \
-    bash -x /ubuntu_arm-16.04_install.sh && \
-    bash -x /common_cleanup.sh
diff --git a/extras/dockerfiles/Dockerfile.ubuntu_arm-18.04 b/extras/dockerfiles/Dockerfile.ubuntu_arm-18.04
index 852abb5..8ecab4d 100644
--- a/extras/dockerfiles/Dockerfile.ubuntu_arm-18.04
+++ b/extras/dockerfiles/Dockerfile.ubuntu_arm-18.04
@@ -1,9 +1,20 @@
 FROM multiarch/ubuntu-core:arm64-bionic
 MAINTAINER Marco Poletti <poletti.marco@gmail.com>
 
-COPY ubuntu_arm-18.04_custom.list /etc/apt/sources.list.d/
-COPY common_install.sh common_cleanup.sh ubuntu_arm-18.04_install.sh /
+COPY common_install.sh common_cleanup.sh /
 
-RUN bash -x /common_install.sh && \
-    bash -x /ubuntu_arm-18.04_install.sh && \
-    bash -x /common_cleanup.sh
+RUN bash -x /common_install.sh
+RUN apt-get install -y --allow-unauthenticated --no-install-recommends \
+    g++-8 \
+    g++-7 \
+    g++-5 \
+    clang-3.9 \
+    clang-4.0 \
+    clang-5.0 \
+    clang-6.0 \
+    python \
+    python3-sh \
+    python3-typed-ast \
+    clang-tidy \
+    clang-format
+RUN bash -x /common_cleanup.sh
diff --git a/extras/dockerfiles/Dockerfile.ubuntu_arm-20.04 b/extras/dockerfiles/Dockerfile.ubuntu_arm-20.04
new file mode 100644
index 0000000..6d84554
--- /dev/null
+++ b/extras/dockerfiles/Dockerfile.ubuntu_arm-20.04
@@ -0,0 +1,22 @@
+FROM multiarch/ubuntu-core:arm64-focal
+MAINTAINER Marco Poletti <poletti.marco@gmail.com>
+
+COPY common_install.sh common_cleanup.sh /
+
+RUN bash -x /common_install.sh
+RUN apt-get install -y --allow-unauthenticated --no-install-recommends \
+    g++-7 \
+    g++-8 \
+    g++-9 \
+    g++-10 \
+    clang-6.0 \
+    clang-7 \
+    clang-8 \
+    clang-9 \
+    clang-10 \
+    python \
+    python3-sh \
+    python3-typed-ast \
+    clang-tidy \
+    clang-format
+RUN bash -x /common_cleanup.sh
diff --git a/extras/dockerfiles/common_install.sh b/extras/dockerfiles/common_install.sh
index 1e0b58b..7eff017 100644
--- a/extras/dockerfiles/common_install.sh
+++ b/extras/dockerfiles/common_install.sh
@@ -24,15 +24,7 @@
     libc++-dev \
     libc++abi1 \
     libc++abi-dev \
-    python3-pip \
-    python3-setuptools \
-    python3-networkx \
-    dirmngr
-
-pip3 install --upgrade pip
-python3 -m pip install absl-py
-python3 -m pip install bidict
-python3 -m pip install pytest
-python3 -m pip install pytest-xdist
-python3 -m pip install sh
-python3 -m pip install wheel
+    dirmngr \
+    python \
+    python3 \
+    python3-setuptools
diff --git a/extras/dockerfiles/rebuild_all.sh b/extras/dockerfiles/rebuild_all.sh
index f84dbbd..77153aa 100755
--- a/extras/dockerfiles/rebuild_all.sh
+++ b/extras/dockerfiles/rebuild_all.sh
@@ -7,15 +7,15 @@
 
 COMMANDS=()
 
-for V in 16.04 18.04 19.04 16.04 19.10
+for V in 18.04 19.10 20.04
 do
-  C="docker build -t polettimarco/fruit-basesystem:ubuntu-$V -f Dockerfile.ubuntu-$V ."
+  C="docker build --squash -t polettimarco/fruit-basesystem:ubuntu-$V -f Dockerfile.ubuntu-$V ."
   COMMANDS+=("$C || { echo; echo FAILED: '$C'; echo; exit 1; }")
 done
 
-for V in 16.04 18.04
+for V in 18.04 20.04
 do
-  C="docker build -t polettimarco/fruit-basesystem:ubuntu_arm-$V -f Dockerfile.ubuntu_arm-$V ."
+  C="docker build --squash -t polettimarco/fruit-basesystem:ubuntu_arm-$V -f Dockerfile.ubuntu_arm-$V ."
   COMMANDS+=("$C || { echo; echo FAILED: '$C'; echo; exit 1; }")
 done
 
@@ -28,10 +28,7 @@
   # This way we get better diagnostics.
   for C in "${COMMANDS[@]}"
   do
-    $C || {
-      echo "Failed: $C"
-      exit 1
-    }
+    bash -c "$C" || exit 1
   done
 }
 
diff --git a/extras/dockerfiles/ubuntu-16.04_custom.list b/extras/dockerfiles/ubuntu-16.04_custom.list
deleted file mode 100644
index e69de29..0000000
--- a/extras/dockerfiles/ubuntu-16.04_custom.list
+++ /dev/null
diff --git a/extras/dockerfiles/ubuntu-16.04_install.sh b/extras/dockerfiles/ubuntu-16.04_install.sh
deleted file mode 100644
index 071fda1..0000000
--- a/extras/dockerfiles/ubuntu-16.04_install.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash
-
-set -e
-
-cat <<EOF >/etc/apt/sources.list.d/custom.list
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-4.0 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-4.0 main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-6.0 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-6.0 main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main
-deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main
-deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main
-EOF
-
-apt-get update -qq
-
-apt-get install -y --allow-unauthenticated --no-install-recommends \
-    clang-3.5 \
-    clang-3.6 \
-    clang-3.7 \
-    clang-3.8 \
-    clang-3.9 \
-    clang-4.0 \
-    clang-5.0 \
-    clang-6.0 \
-    clang-7 \
-    clang-8 \
-    clang-9 \
-    clang-10 \
-    g++-5 \
-    g++-4.9 \
-    g++-6 \
-    python \
-    git \
-    clang-tidy \
-    clang-format
-
-pip3 install typed_ast
diff --git a/extras/dockerfiles/ubuntu-18.04_custom.list b/extras/dockerfiles/ubuntu-18.04_custom.list
index e69de29..171b878 100644
--- a/extras/dockerfiles/ubuntu-18.04_custom.list
+++ b/extras/dockerfiles/ubuntu-18.04_custom.list
@@ -0,0 +1,17 @@
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-5.0 main
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-5.0 main
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-6.0 main
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-6.0 main
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main
+
+deb http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic main
+deb-src http://ppa.launchpad.net/deadsnakes/ppa/ubuntu bionic main
diff --git a/extras/dockerfiles/ubuntu-18.04_install.sh b/extras/dockerfiles/ubuntu-18.04_install.sh
deleted file mode 100644
index 7c1aa3d..0000000
--- a/extras/dockerfiles/ubuntu-18.04_install.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash
-
-set -e
-
-apt-get install -y --no-install-recommends \
-    curl
-
-# For the Bazel repository
-curl https://bazel.build/bazel-release.pub.gpg | apt-key add -
-
-echo 'deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8' >> /etc/apt/sources.list.d/bazel.list
-
-cat <<EOF >/etc/apt/sources.list.d/custom.list
-deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main
-deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main
-deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-5.0 main
-deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-5.0 main
-deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-6.0 main
-deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-6.0 main
-deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main
-deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main
-deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
-deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
-deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
-deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main
-deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main
-deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main
-EOF
-
-apt-get update -qq
-
-apt-get install -y --allow-unauthenticated --no-install-recommends \
-    g++-8 \
-    g++-7 \
-    g++-6 \
-    g++-5 \
-    clang-3.9 \
-    clang-4.0 \
-    clang-5.0 \
-    clang-6.0 \
-    clang-7 \
-    clang-8 \
-    clang-9 \
-    clang-10 \
-    bazel \
-    git \
-    python \
-    python3-sh \
-    python3-typed-ast \
-    clang-tidy \
-    clang-format
diff --git a/extras/dockerfiles/ubuntu-19.04_custom.list b/extras/dockerfiles/ubuntu-19.04_custom.list
deleted file mode 100644
index e69de29..0000000
--- a/extras/dockerfiles/ubuntu-19.04_custom.list
+++ /dev/null
diff --git a/extras/dockerfiles/ubuntu-19.04_install.sh b/extras/dockerfiles/ubuntu-19.04_install.sh
deleted file mode 100644
index 076073c..0000000
--- a/extras/dockerfiles/ubuntu-19.04_install.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-set -e
-
-cat <<EOF >/etc/apt/sources.list.d/ubuntu-19.10_custom.list
-deb http://apt.llvm.org/disco/ llvm-toolchain-disco main
-deb-src http://apt.llvm.org/disco/ llvm-toolchain-disco main
-# 9
-deb http://apt.llvm.org/disco/ llvm-toolchain-disco-9 main
-deb-src http://apt.llvm.org/disco/ llvm-toolchain-disco-9 main
-# 10
-deb http://apt.llvm.org/disco/ llvm-toolchain-disco-10 main
-deb-src http://apt.llvm.org/disco/ llvm-toolchain-disco-10 main
-EOF
-
-apt-get update
-
-apt-get install -y --allow-unauthenticated --no-install-recommends \
-    g++-7 \
-    g++-8 \
-    g++-9 \
-    clang-6.0 \
-    clang-7 \
-    clang-8 \
-    python \
-    python3-sh \
-    python3-typed-ast \
-    clang-tidy \
-    clang-format
diff --git a/extras/dockerfiles/ubuntu-19.10_custom.list b/extras/dockerfiles/ubuntu-19.10_custom.list
index e69de29..ac1b4bd 100644
--- a/extras/dockerfiles/ubuntu-19.10_custom.list
+++ b/extras/dockerfiles/ubuntu-19.10_custom.list
@@ -0,0 +1,6 @@
+deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan main
+deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan main
+deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan-9 main
+deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan-9 main
+deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan-10 main
+deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan-10 main
diff --git a/extras/dockerfiles/ubuntu-19.10_install.sh b/extras/dockerfiles/ubuntu-19.10_install.sh
deleted file mode 100644
index 464c400..0000000
--- a/extras/dockerfiles/ubuntu-19.10_install.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-set -e
-
-cat <<EOF >/etc/apt/sources.list.d/ubuntu-19.10_custom.list
-deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan main
-deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan main
-deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan-9 main
-deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan-9 main
-deb http://apt.llvm.org/eoan/ llvm-toolchain-eoan-10 main
-deb-src http://apt.llvm.org/eoan/ llvm-toolchain-eoan-10 main
-EOF
-
-apt-get update
-
-apt-get install -y --allow-unauthenticated --no-install-recommends \
-    g++-7 \
-    g++-8 \
-    g++-9 \
-    clang-6.0 \
-    clang-7 \
-    clang-8 \
-    clang-9 \
-    clang-10 \
-    python \
-    python3-sh \
-    python3-typed-ast \
-    clang-tidy \
-    clang-format
diff --git a/extras/dockerfiles/ubuntu-20.04_custom.list b/extras/dockerfiles/ubuntu-20.04_custom.list
new file mode 100644
index 0000000..c26e2d9
--- /dev/null
+++ b/extras/dockerfiles/ubuntu-20.04_custom.list
@@ -0,0 +1,4 @@
+deb http://apt.llvm.org/focal/ llvm-toolchain-focal-9 main
+deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-9 main
+deb http://apt.llvm.org/focal/ llvm-toolchain-focal-10 main
+deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-10 main
diff --git a/extras/dockerfiles/ubuntu_arm-16.04_install.sh b/extras/dockerfiles/ubuntu_arm-16.04_install.sh
deleted file mode 100644
index d692fb4..0000000
--- a/extras/dockerfiles/ubuntu_arm-16.04_install.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-
-set -e
-
-apt-get install -y --allow-unauthenticated --no-install-recommends \
-    clang-3.5 \
-    clang-3.6 \
-    clang-3.7 \
-    clang-3.9 \
-    clang-4.0 \
-    g++-5 \
-    g++-4.9 \
-    g++-6 \
-    python \
-    clang-tidy \
-    clang-format
diff --git a/extras/dockerfiles/ubuntu_arm-18.04_custom.list b/extras/dockerfiles/ubuntu_arm-18.04_custom.list
deleted file mode 100644
index e69de29..0000000
--- a/extras/dockerfiles/ubuntu_arm-18.04_custom.list
+++ /dev/null
diff --git a/extras/dockerfiles/ubuntu_arm-18.04_install.sh b/extras/dockerfiles/ubuntu_arm-18.04_install.sh
deleted file mode 100644
index ea2d240..0000000
--- a/extras/dockerfiles/ubuntu_arm-18.04_install.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-set -e
-
-apt-get install -y --allow-unauthenticated --no-install-recommends \
-    g++-8 \
-    g++-7 \
-    g++-5 \
-    clang-3.9 \
-    clang-4.0 \
-    clang-5.0 \
-    clang-6.0 \
-    python \
-    python3-sh \
-    python3-typed-ast \
-    clang-tidy \
-    clang-format
diff --git a/extras/packaging/deploy_to_bintray.bat b/extras/packaging/deploy_to_bintray.bat
index 2473343..1a28914 100644
--- a/extras/packaging/deploy_to_bintray.bat
+++ b/extras/packaging/deploy_to_bintray.bat
@@ -1,4 +1,4 @@
-set FRUIT_VERSION=3.4.0
+set FRUIT_VERSION=354.0
 
 for %%G in (Release Debug) DO CMD /C for %%H in (True False) DO CMD /C for %%I in (True False) DO conan create . google/stable -o fruit:shared=%%H -o fruit:use_boost=%%I -s build_type=%%G
 
diff --git a/extras/packaging/deploy_to_bintray.sh b/extras/packaging/deploy_to_bintray.sh
index 31a80c7..0365a6d 100755
--- a/extras/packaging/deploy_to_bintray.sh
+++ b/extras/packaging/deploy_to_bintray.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-FRUIT_VERSION=3.4.0
+FRUIT_VERSION=3.5.0
 
 # To authenticate:
 # conan user -p <BINTRAY_API_KEY_HERE> -r fruit-bintray polettimarco
diff --git a/extras/scripts/postsubmit-helper.sh b/extras/scripts/postsubmit-helper.sh
index 9b463bc..7be3b88 100755
--- a/extras/scripts/postsubmit-helper.sh
+++ b/extras/scripts/postsubmit-helper.sh
@@ -37,6 +37,11 @@
     export CXX=g++-9
     ;;
 
+gcc-10)
+    export CC=gcc-10
+    export CXX=g++-10
+    ;;
+
 clang-3.5)
     export CC=clang-3.5
     export CXX=clang++-3.5
@@ -151,6 +156,8 @@
     ReleaseValgrindNoPchNoClangTidy) CMAKE_ARGS=(-DCMAKE_BUILD_TYPE=Release -DFRUIT_ENABLE_CLANG_TIDY=FALSE -DCMAKE_CXX_FLAGS="$COMMON_CXX_FLAGS" -DRUN_TESTS_UNDER_VALGRIND=TRUE -DFRUIT_TESTS_USE_PRECOMPILED_HEADERS=OFF) ;;
     *) echo "Error: you need to specify one of the supported postsubmit modes (see postsubmit.sh)."; exit 1 ;;
     esac
+    # Setting compilers only via env vars doesn't work when using recent versions of XCode.
+    CMAKE_ARGS+=(-DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX)
 
     SOURCES_PATH="$PWD"
 
@@ -187,8 +194,12 @@
     make install
 else
     # COMPILER=bazel
-    
-    BAZEL_FLAGS=("--python_path=$(which python3)")
+
+    # In recent versions of Bazel (as of May 2020), --python_path is ignored unless
+    # --noincompatible_use_python_toolchains is also used.
+    # Ignoring --python_path is ok in Ubuntu 20.04 since 3.8 is the default Python there, but causes problems in docker
+    # images with older Ubuntu versions that have both 3.8 and another 3.x version installed.
+    BAZEL_FLAGS=("--python_path=$(which python3.8)" "--noincompatible_use_python_toolchains")
     case "$1" in
     DebugPlain)      ;;
     ReleasePlain)    BAZEL_FLAGS+=("-c" "opt") ;;
diff --git a/extras/scripts/travis_yml_generator.py b/extras/scripts/travis_yml_generator.py
index 82c9388..93a5a1b 100755
--- a/extras/scripts/travis_yml_generator.py
+++ b/extras/scripts/travis_yml_generator.py
@@ -145,19 +145,13 @@
         build_matrix_rows.append(test_environment)
 
 
-# TODO: re-enable ASan/UBSan once they work in Travis CI. ATM (as of 18 November 2017) they fail due to https://github.com/google/sanitizers/issues/837
-add_ubuntu_tests(ubuntu_version='19.10', compiler='gcc-7', asan=False, ubsan=False)
-add_ubuntu_tests(ubuntu_version='19.10', compiler='gcc-9', asan=False, ubsan=False,
+add_ubuntu_tests(ubuntu_version='20.04', compiler='gcc-7')
+add_ubuntu_tests(ubuntu_version='20.04', compiler='gcc-10',
                  smoke_tests=['DebugPlain', 'ReleasePlain'])
-add_ubuntu_tests(ubuntu_version='19.10', compiler='clang-6.0', stl='libstdc++',
+add_ubuntu_tests(ubuntu_version='20.04', compiler='clang-6.0', stl='libstdc++',
                  smoke_tests=['DebugPlain', 'DebugAsanUbsan', 'ReleasePlain'])
-add_ubuntu_tests(ubuntu_version='19.10', compiler='clang-10.0', stl='libstdc++')
-# Using Clang 10 + libc++ doesn't work as of March 2020, it can't find STL headers.
-add_ubuntu_tests(ubuntu_version='19.10', compiler='clang-9.0', stl='libc++',
-                 # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625.
-                 use_precompiled_headers_in_tests=False,
-                 # As of March 2020, Clang tidy segfaults and can't find STL headers (not sure if these issues are related or independent).
-                 clang_tidy=False)
+add_ubuntu_tests(ubuntu_version='20.04', compiler='clang-10.0', stl='libstdc++')
+add_ubuntu_tests(ubuntu_version='20.04', compiler='clang-10.0', stl='libc++')
 
 add_ubuntu_tests(ubuntu_version='18.04', compiler='gcc-5', asan=False, ubsan=False)
 add_ubuntu_tests(ubuntu_version='18.04', compiler='gcc-8', asan=False, ubsan=False)
@@ -192,7 +186,10 @@
               use_precompiled_headers_in_tests=False)
 
 add_osx_tests(compiler='clang-default', xcode_version='9.4', stl='libc++', clang_tidy=False)
-add_osx_tests(compiler='clang-default', xcode_version='11.4', stl='libc++', clang_tidy=False, smoke_tests=['DebugPlain'])
+add_osx_tests(compiler='clang-default', xcode_version='11.3', stl='libc++', clang_tidy=False,
+              # Disabled due to https://bugs.llvm.org/show_bug.cgi?id=41625.
+              use_precompiled_headers_in_tests=False,
+              smoke_tests=['DebugPlain'])
 
 # ** Disabled combinations **
 #
diff --git a/tests/test_component_functions.py b/tests/test_component_functions.py
index ec70bfc..8dc6a76 100755
--- a/tests/test_component_functions.py
+++ b/tests/test_component_functions.py
@@ -187,7 +187,8 @@
             r'error: use of deleted function .Arg::Arg\(Arg&&\).'
             r'|error: call to deleted constructor of .Arg.'
             r'|.Arg::Arg\(Arg &&\).: cannot convert argument 1 from .std::_Tuple_val<Arg>. to .int.'
-            r'|error: copying parameter of type .Arg. invokes deleted constructor',
+            r'|error: copying parameter of type .Arg. invokes deleted constructor'
+            r'|error C2280: .Arg::Arg\(Arg &&\).: attempting to reference a deleted function',
             COMMON_DEFINITIONS,
             source)
 
diff --git a/tests/test_normalized_component.py b/tests/test_normalized_component.py
index ba21242..8888019 100755
--- a/tests/test_normalized_component.py
+++ b/tests/test_normalized_component.py
@@ -175,7 +175,7 @@
         expect_generic_compile_error(
             r'no matching function for call to .fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent\(fruit::Component<XAnnot> \(&\)\(\)\).'
             r'|no matching constructor for initialization of .fruit::NormalizedComponent<ConstXAnnot>.'
-            r'|.fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent.: none of the 2 overloads could convert all the argument types',
+            r'|.fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent.: none of the .* overloads could convert all the argument types',
             COMMON_DEFINITIONS,
             source,
             locals())