]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Performance tests: add a valgrind wrapper
authorMatthias Maier <tamiko@43-1.org>
Thu, 17 Feb 2022 11:25:57 +0000 (05:25 -0600)
committerMatthias Maier <tamiko@43-1.org>
Fri, 11 Mar 2022 21:46:33 +0000 (15:46 -0600)
tests/performance/valgrind_instrumentation.h [new file with mode: 0644]

diff --git a/tests/performance/valgrind_instrumentation.h b/tests/performance/valgrind_instrumentation.h
new file mode 100644 (file)
index 0000000..7ee4bce
--- /dev/null
@@ -0,0 +1,139 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2016-2022 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+#ifndef dealii_valgrind_instrumentation_h
+#define dealii_valgrind_instrumentation_h
+
+#include <unistd.h>
+#include <valgrind/callgrind.h>
+
+#include <cstdio>
+#include <fstream>
+#include <mutex>
+
+
+/**
+ * A simple wrapper around callgrind to query current instruction counter
+ * values. In order to make use of the functions in this namespace the
+ * executable has to be started with valgrind:
+ * @code
+ *   valgrind --tool=callgrind -q --combine-dumps=yes --instr-atstart=no \
+ *            --callgrind-out-file=callgrind.out ./executable
+ * @endcode
+ */
+namespace callgrind_wrapper
+{
+  /**
+   * Reset the current instruction counter to zero and start callgrind
+   * instrumentation.
+   */
+  DEAL_II_ALWAYS_INLINE
+  inline void
+  start_instrumentation()
+  {
+    /*
+     * Verify that we are running under valgrind and that valgrind is
+     * called with the right parameters.
+     */
+    static bool is_initialized = []() {
+      // Is this executable running under valgrind supervision?
+      if (RUNNING_ON_VALGRIND != 1)
+        return false;
+
+      // Start and stop valgrind instrumentation
+      CALLGRIND_STOP_INSTRUMENTATION;
+      std::remove("callgrind.out");
+      CALLGRIND_ZERO_STATS;
+      CALLGRIND_START_INSTRUMENTATION;
+      const auto my_pid = getpid(); // do something useful
+      CALLGRIND_DUMP_STATS_AT("callgrind-wrapper-token");
+      CALLGRIND_STOP_INSTRUMENTATION;
+
+      std::ifstream      callgrind_output("callgrind.out");
+      std::string        token;
+      unsigned long long cycles      = 0ull;
+      bool               found_token = false;
+      unsigned long      found_pid   = 0;
+
+      while (callgrind_output)
+        {
+          callgrind_output >> token;
+          if (token == "pid:")
+            callgrind_output >> found_pid;
+          if (token == "desc:")
+            {
+              std::string line;
+              std::getline(callgrind_output, line);
+              if (line == " Trigger: Client Request: callgrind-wrapper-token")
+                found_token = true;
+            }
+          if (token == "summary:")
+            callgrind_output >> cycles;
+        }
+
+      if (!found_token)
+        return false;
+
+      if (found_pid != my_pid)
+        return false;
+
+      if (cycles == 0)
+        return false;
+
+      return true;
+    }();
+
+    AssertThrow(
+      is_initialized,
+      dealii::ExcMessage(
+        "callgrind_wrapper::start_instrumentation() can only be called when "
+        "the executable is run via \"valgrind --tool=callgrind -q "
+        "--combine-dumps=yes --instr-atstart=no "
+        "--callgrind-out-file=callgrind.out ./executable\""));
+
+    CALLGRIND_ZERO_STATS;
+    CALLGRIND_START_INSTRUMENTATION;
+  }
+
+
+  /**
+   * Stop callgrind instrumentation and return the number of instructions
+   * executed since the last start_instrumentation() call.
+   */
+  DEAL_II_ALWAYS_INLINE
+  inline unsigned long long
+  stop_instrumentation()
+  {
+    CALLGRIND_DUMP_STATS;
+    CALLGRIND_STOP_INSTRUMENTATION;
+
+    std::ifstream      callgrind_output("callgrind.out");
+    std::string        token;
+    unsigned long long cycles = 0ull;
+
+    while (callgrind_output)
+      {
+        callgrind_output >> token;
+        if (token == "summary:")
+          callgrind_output >> cycles;
+      }
+
+    std::remove("callgrind.out");
+    return cycles;
+  }
+
+} // namespace callgrind_wrapper
+
+#endif

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.