From 54e473630b78cff43b0d2402eeb6a2df8ef830e6 Mon Sep 17 00:00:00 2001 From: Matthias Maier Date: Thu, 17 Feb 2022 05:25:57 -0600 Subject: [PATCH] Performance tests: add a valgrind wrapper --- tests/performance/valgrind_instrumentation.h | 139 +++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 tests/performance/valgrind_instrumentation.h diff --git a/tests/performance/valgrind_instrumentation.h b/tests/performance/valgrind_instrumentation.h new file mode 100644 index 0000000000..7ee4bce7d6 --- /dev/null +++ b/tests/performance/valgrind_instrumentation.h @@ -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 +#include + +#include +#include +#include + + +/** + * 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 -- 2.39.5