1#ifndef __DUNE_ACFEM_EXPRESSIONS_OPTIMIZATIONPROFILE_HH__
2#define __DUNE_ACFEM_EXPRESSIONS_OPTIMIZATIONPROFILE_HH__
8#include "../common/tostring.hh"
14 namespace Expressions {
16#ifndef DUNE_ACFEM_PROFILE_OPTIMIZATION
17# define DUNE_ACFEM_RECORD_OPTIMIZATION
18# define DUNE_ACFEM_EXPRESSION_RESULT(EXPR, ...) return EXPR
20# define DUNE_ACFEM_RECORD_OPTIMIZATION \
21 Dune::ACFem::Expressions::OptimizationProfiler::recordHit(__LINE__, __FILE__, __PRETTY_FUNCTION__)
23#if DUNE_ACFEM_TRACE_OPTIMIZATION
24# define DUNE_ACFEM_EXPRESSION_RESULT(EXPR, ...) \
26 decltype(auto) result = EXPR; \
27 std::clog << "Expression: " \
30 << std::string(__VA_ARGS__) \
33 return forwardReturnValue<decltype(result)>(result); \
36# define DUNE_ACFEM_EXPRESSION_RESULT(EXPR, ...) return EXPR
39 class OptimizationProfiler
41 using KeyType = std::pair<std::size_t, std::string>;
42 using DataType = std::pair<std::size_t, std::string>;
43 using StorageType = std::map<KeyType, DataType>;
46 static void recordHit(std::size_t line,
const std::string& file,
const std::string& prettyFunction)
48 static OptimizationProfilerDumper dumper;
51 auto key = std::make_pair(line, file);
52 const auto& old = data_.find(key);
53 const auto& fct = old == data_.end() ? parsePrettyFunction(prettyFunction) : old->second.second;
54 data_[key] = std::make_pair(++(data_[key].first), fct);
55#if DUNE_ACFEM_TRACE_OPTIMIZATION
56 std::clog << file <<
":" << line << std::endl
57 << prettyFunction << std::endl
67 static void dump(std::ostream& out)
69 out <<
"COUNT LINE File FUNCTION" << std::endl;
70 for (
auto&& kv : data_) {
71 const auto& key = kv.first;
72 const auto& data = kv.second;
74 out << data.first <<
" "
76 <<
"\"" << key.second <<
"\" "
77 <<
"\"" << parsePrettyFunction(data.second) <<
"\""
82 static void read(std::istream& in)
89 if (getline(in, rest)) {
90 while (getline(in, rest)) {
91 std::istringstream iss(rest);
92 if (iss >> count >> line) {
93 rest = rest.substr(rest.find(
"\"")+1);
94 auto posQuote = rest.find(
"\"");
95 file = rest.substr(0, posQuote);
96 rest = rest.substr(posQuote+3);
97 posQuote = rest.find(
"\"");
98 fct = rest.substr(0, posQuote);
100 auto key = std::make_pair(line, file);
101 const auto& old = data_.find(key);
102 if (old != data_.end()) {
103 if (old->second.second == fct) {
104 count += old->second.first;
107 data_[key] = std::make_pair(count, fct);
113 static std::string parsePrettyFunction(
const std::string& prettyFunction)
115 std::vector<std::string> tokens;
116#if DUNE_ACFEM_IS_GCC(0, 9999)
117 auto fctEnd = prettyFunction.find(
" [with ");
118#elif DUNE_ACFEM_IS_CLANG(0, 9999)
119 auto fctEnd = prettyFunction.find(
" [");
121 auto fct = prettyFunction.substr(0, fctEnd);
122 auto rest = prettyFunction.substr(fctEnd+
sizeof(
" [with ")-1);
124 auto pos = std::string::npos;
125 while ((pos = rest.find(
";")) != std::string::npos) {
126 tokens.push_back(rest.substr(0, pos-1));
127 rest = rest.substr(pos+2);
129 tokens.push_back(rest.substr(0, rest.size()-1));
130 for(
auto&& token : tokens) {
132 if (token.find(
"typename std::enable_if") == 0) {
133 const auto pfxLen =
sizeof(
"typename");
134 fct +=
"; " + token.substr(pfxLen, token.rfind(
"::type ")-pfxLen);
143 struct OptimizationProfilerDumper
145 ~OptimizationProfilerDumper()
147 std::string dumpFileName =
"acfem-expression-profile.dump";
148 std::ifstream oldDumpFile;
149 oldDumpFile.open(dumpFileName);
150 if (oldDumpFile.is_open()) {
151 OptimizationProfiler::read(oldDumpFile);
154 std::ofstream dumpFile;
155 dumpFile.open(dumpFileName);
156 if (dumpFile.is_open()) {
157 OptimizationProfiler::dump(dumpFile);
163 inline static StorageType data_;