From 8a25c826cd6a1f7f66ad45e6d01a0ec2620dc472 Mon Sep 17 00:00:00 2001
From: scott snyder <snyder@bnl.gov>
Date: Thu, 28 Jan 2021 16:17:10 +0100
Subject: [PATCH] GeoModelKernel: Compile GeoXF.cxx with optimization, even in
 debug builds.

GeoXF.cxx makes heavy use of Eigen.  In debug builds it ends up being
much, much slower than in optimized builds, to the point where where it
makes it difficult to run things in dbg.  Tweak the build so that we compile
GeoXF.cxx with optimization, even in dbg builds.  We also need to use the
flatten attribute on the functions that use Eigen, so ensure that the Eigen
operations are completely inlined.

This was motivated by the fact that numerous tests are timing out in the dbg
build.  This change alone reduced the time required by one test from ~600s
to ~400s.
---
 GeoModelCore/GeoModelKernel/CMakeLists.txt | 15 ++++++++++++-
 GeoModelCore/GeoModelKernel/src/GeoXF.cxx  | 26 +++++++++++++++++++++-
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/GeoModelCore/GeoModelKernel/CMakeLists.txt b/GeoModelCore/GeoModelKernel/CMakeLists.txt
index 1a4bc0b1c..d0bbfb565 100644
--- a/GeoModelCore/GeoModelKernel/CMakeLists.txt
+++ b/GeoModelCore/GeoModelKernel/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
 
 # Find the header and source files.
 file( GLOB SOURCES src/*.cxx )
@@ -20,6 +20,19 @@ set_target_properties( GeoModelKernel PROPERTIES
    VERSION ${PROJECT_VERSION}
    SOVERSION ${PROJECT_VERSION_MAJOR} )
 
+# Code in this file makes heavy use of eigen and runs orders of magnitude
+# more slowly without optimization.  So force this to be optimized even
+# in debug builds.  If you need to debug it you might want to change this.
+# Specifying optimization via an attribute on the particular
+# function didn't work, because that still didn't allow inlining.
+if ( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" )
+  set_source_files_properties(
+     ${CMAKE_CURRENT_SOURCE_DIR}/src/GeoXF.cxx
+     PROPERTIES
+     COMPILE_FLAGS "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}"
+     COMPILE_DEFINITIONS "FLATTEN" )
+endif()
+
 # Set up an alias with the same name that you would get by "finding" a pre-built
 # version of the library.
 add_library( GeoModelCore::GeoModelKernel ALIAS GeoModelKernel )
diff --git a/GeoModelCore/GeoModelKernel/src/GeoXF.cxx b/GeoModelCore/GeoModelKernel/src/GeoXF.cxx
index a3038686e..23cac3f88 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoXF.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoXF.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "GeoModelKernel/GeoXF.h"
@@ -134,11 +134,23 @@ namespace GeoXF
     return m_arg2->dimensionality ();
   }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// We compile this package 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
   GeoTrf::Transform3D PreMult::operator        () (double x) const
   {
     return m_arg1 * (*m_arg2) (x);
   }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// See above.
+__attribute__ ((flatten))
+#endif
   GeoTrf::Transform3D PreMult::operator        () (const GeoGenfun::Argument & x) const
   {
     return m_arg1 * (*m_arg2) (x);
@@ -181,11 +193,19 @@ namespace GeoXF
     return m_arg1->dimensionality ();
   }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// See above.
+__attribute__ ((flatten))
+#endif
   GeoTrf::Transform3D PostMult::operator        () (double x) const
   {
     return (*m_arg1) (x) * m_arg2;
   }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// See above.
+__attribute__ ((flatten))
+#endif
   GeoTrf::Transform3D PostMult::operator        () (const GeoGenfun::Argument & x) const
   {
     return (*m_arg1) (x) * m_arg2;
@@ -202,6 +222,10 @@ namespace GeoXF
     delete m_function;
   }
 
+#if defined(FLATTEN) && defined(__GNUC__)
+// See above.
+__attribute__ ((flatten))
+#endif
   GeoTrf::Transform3D Pow::operator() (double x) const
   {
     //
-- 
GitLab