diff --git a/Tracking/TrkDetDescr/TrkSurfaces/CMakeLists.txt b/Tracking/TrkDetDescr/TrkSurfaces/CMakeLists.txt
index c6bb9774573702658140800324aa72bf5d3ede81..fbbd490e5ed2b3479ed2f3937c8c754ff51e56cf 100644
--- a/Tracking/TrkDetDescr/TrkSurfaces/CMakeLists.txt
+++ b/Tracking/TrkDetDescr/TrkSurfaces/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
 
 # Declare the package name: 
 atlas_subdir( TrkSurfaces )
@@ -10,6 +10,21 @@ atlas_add_library( TrkSurfaces
    LINK_LIBRARIES AthenaKernel AthContainers CxxUtils GeoPrimitives Identifier EventPrimitives TrkParametersBase
    GaudiKernel TrkDetDescrUtils TrkDetElementBase TrkEventPrimitives )
 
+# Some functions here make heavy use of Eigen and are thus very slow in debug
+# builds.  Set up to allow forcing them to compile with optimization and
+# inlining, even in debug builds.
+if ( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" )
+  set_source_files_properties(
+     ${CMAKE_CURRENT_SOURCE_DIR}/src/Surface.cxx
+     ${CMAKE_CURRENT_SOURCE_DIR}/src/DiscSurface.cxx
+     ${CMAKE_CURRENT_SOURCE_DIR}/src/PlaneSurface.cxx
+     ${CMAKE_CURRENT_SOURCE_DIR}/src/CylinderSurface.cxx
+     ${CMAKE_CURRENT_SOURCE_DIR}/src/StraightLineSurface.cxx
+     PROPERTIES
+     COMPILE_FLAGS "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}"
+     COMPILE_DEFINITIONS "FLATTEN" )
+endif()
+
 atlas_add_dictionary( TrkSurfacesDict
    TrkSurfaces/TrkSurfacesDict.h
    TrkSurfaces/selection.xml
diff --git a/Tracking/TrkDetDescr/TrkSurfaces/src/CylinderSurface.cxx b/Tracking/TrkDetDescr/TrkSurfaces/src/CylinderSurface.cxx
index dc87085613754b7e3b833177ae5c1b398e86ca5c..bc05750c3379512046ee1425b1929eb35ba6fc77 100644
--- a/Tracking/TrkDetDescr/TrkSurfaces/src/CylinderSurface.cxx
+++ b/Tracking/TrkDetDescr/TrkSurfaces/src/CylinderSurface.cxx
@@ -313,6 +313,14 @@ Trk::CylinderSurface::straightLineIntersection(const Amg::Vector3D& pos,
 
 /** distance to surface */
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// We compile this function with optimization, even in debug builds; otherwise,
+// the heavy use of Eigen makes it too slow.  However, from here we may call
+// to out-of-line Eigen code that is linked from other DSOs; in that case,
+// it would not be optimized.  Avoid this by forcing all Eigen code
+// to be inlined here if possible.
+__attribute__ ((flatten))
+#endif
 Trk::DistanceSolution
 Trk::CylinderSurface::straightLineDistanceEstimate(const Amg::Vector3D& pos, const Amg::Vector3D& dir) const
 {
diff --git a/Tracking/TrkDetDescr/TrkSurfaces/src/DiscSurface.cxx b/Tracking/TrkDetDescr/TrkSurfaces/src/DiscSurface.cxx
index 4662779219029ae70c33a1faf95efa4839f32a16..f0dfa669099cfc78c7535b03fc5fbac414a23b8d 100644
--- a/Tracking/TrkDetDescr/TrkSurfaces/src/DiscSurface.cxx
+++ b/Tracking/TrkDetDescr/TrkSurfaces/src/DiscSurface.cxx
@@ -225,6 +225,14 @@ Trk::DiscSurface::globalToLocalCartesian(const Amg::Vector3D& glopos, double tol
   return new Amg::Vector2D(loc3Dframe.x(), loc3Dframe.y());
 }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// We compile this function with optimization, even in debug builds; otherwise,
+// the heavy use of Eigen makes it too slow.  However, from here we may call
+// to out-of-line Eigen code that is linked from other DSOs; in that case,
+// it would not be optimized.  Avoid this by forcing all Eigen code
+// to be inlined here if possible.
+__attribute__ ((flatten))
+#endif
 bool
 Trk::DiscSurface::isOnSurface(const Amg::Vector3D& glopo, Trk::BoundaryCheck bchk, double tol1, double tol2) const
 {
diff --git a/Tracking/TrkDetDescr/TrkSurfaces/src/PlaneSurface.cxx b/Tracking/TrkDetDescr/TrkSurfaces/src/PlaneSurface.cxx
index a04bf4c8272febc67e63986f34dc764cc1c28732..dff9a96c61b36d693c43919d8b9518b6ba6cc91e 100644
--- a/Tracking/TrkDetDescr/TrkSurfaces/src/PlaneSurface.cxx
+++ b/Tracking/TrkDetDescr/TrkSurfaces/src/PlaneSurface.cxx
@@ -42,6 +42,14 @@ Trk::PlaneSurface::PlaneSurface(const PlaneSurface& psf, const Amg::Transform3D&
   , m_bounds(psf.m_bounds)
 {}
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// We compile this function with optimization, even in debug builds; otherwise,
+// the heavy use of Eigen makes it too slow.  However, from here we may call
+// to out-of-line Eigen code that is linked from other DSOs; in that case,
+// it would not be optimized.  Avoid this by forcing all Eigen code
+// to be inlined here if possible.
+__attribute__ ((flatten))
+#endif
 // constructor from CurvilinearUVT
 Trk::PlaneSurface::PlaneSurface(const Amg::Vector3D& position, const CurvilinearUVT& curvUVT)
   : Trk::Surface()
diff --git a/Tracking/TrkDetDescr/TrkSurfaces/src/StraightLineSurface.cxx b/Tracking/TrkDetDescr/TrkSurfaces/src/StraightLineSurface.cxx
index 6918f043c70bec22ba0efd286b7dfbae6670de73..8c9a45fe5180d5c44d2d9979e131956c56648989 100644
--- a/Tracking/TrkDetDescr/TrkSurfaces/src/StraightLineSurface.cxx
+++ b/Tracking/TrkDetDescr/TrkSurfaces/src/StraightLineSurface.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
 */
 
 ///////////////////////////////////////////////////////////////////
@@ -145,6 +145,14 @@ Trk::StraightLineSurface::globalToLocal(const Amg::Vector3D& glopos,
   return true;
 }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// We compile this function with optimization, even in debug builds; otherwise,
+// the heavy use of Eigen makes it too slow.  However, from here we may call
+// to out-of-line Eigen code that is linked from other DSOs; in that case,
+// it would not be optimized.  Avoid this by forcing all Eigen code
+// to be inlined here if possible.
+__attribute__ ((flatten))
+#endif
 // isOnSurface check
 bool
 Trk::StraightLineSurface::isOnSurface(const Amg::Vector3D& glopo, BoundaryCheck bchk, double tol1, double tol2) const
diff --git a/Tracking/TrkDetDescr/TrkSurfaces/src/Surface.cxx b/Tracking/TrkDetDescr/TrkSurfaces/src/Surface.cxx
index b534cdbaa9895d1eb6b84b7b5d14f1c86c5746f1..520e9ada1e49b8887e2d5543c3a739a5756a79e2 100644
--- a/Tracking/TrkDetDescr/TrkSurfaces/src/Surface.cxx
+++ b/Tracking/TrkDetDescr/TrkSurfaces/src/Surface.cxx
@@ -36,9 +36,18 @@ Trk::Surface::Surface()
 #ifndef NDEBUG
   s_numberOfInstantiations++;     // EDM Monitor
   s_numberOfFreeInstantiations++; // EDM Monitor
+
 #endif
 }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// We compile this function with optimization, even in debug builds; otherwise,
+// the heavy use of Eigen makes it too slow.  However, from here we may call
+// to out-of-line Eigen code that is linked from other DSOs; in that case,
+// it would not be optimized.  Avoid this by forcing all Eigen code
+// to be inlined here if possible.
+__attribute__ ((flatten))
+#endif
 Trk::Surface::Surface(Amg::Transform3D* tform)
   : m_transform(nullptr)
   , m_center(nullptr)
@@ -96,6 +105,14 @@ Trk::Surface::Surface(const Trk::TrkDetElementBase& detelement, const Identifier
 #endif
 }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// We compile this function with optimization, even in debug builds; otherwise,
+// the heavy use of Eigen makes it too slow.  However, from here we may call
+// to out-of-line Eigen code that is linked from other DSOs; in that case,
+// it would not be optimized.  Avoid this by forcing all Eigen code
+// to be inlined here if possible.
+__attribute__ ((flatten))
+#endif
 // copy constructor - Attention! sets the associatedDetElement to 0 and the identifier to invalid
 Trk::Surface::Surface(const Surface& sf)
   : m_transform(nullptr)
@@ -118,7 +135,15 @@ Trk::Surface::Surface(const Surface& sf)
 #endif
 }
 
-// copy constructor with shift - Attention! sets the associatedDetElement to 0 and the identifieer to invalid
+#if defined(FLATTEN) && defined(__GNUC__)
+// We compile this function with optimization, even in debug builds; otherwise,
+// the heavy use of Eigen makes it too slow.  However, from here we may call
+// to out-of-line Eigen code that is linked from other DSOs; in that case,
+// it would not be optimized.  Avoid this by forcing all Eigen code
+// to be inlined here if possible.
+__attribute__ ((flatten))
+#endif
+// copy constructor with shift - Attention! sets the associatedDetElement to 0 and the identifier to invalid
 // also invalidates the material layer
 Trk::Surface::Surface(const Surface& sf, const Amg::Transform3D& shift)
   : m_transform(sf.m_transform ? std::make_unique<Amg::Transform3D>(shift * (*(sf.m_transform)))