yse / easy_profiler

Lightweight profiler library for c++
MIT License
2.14k stars 184 forks source link

Unable to profile across DLL boundaries on Windows #205

Closed Marwan-imverse closed 1 year ago

Marwan-imverse commented 1 year ago

We have a project with multiple DLLs, each with its own profiling code. But only the code running in the main application is profiled. I suspect this is because the instance of the profiler is not correctly passed between DLL boundaries.

FYI we are using the Visual Studio 2019 Compiler (version 16) with C++17 extensions enabled.

Here is a very simple example of what we are trying to do (eventually the BUILD_WITH_EASY_PROFILER macro will be managed by the build system. This is really just a brute force test).

In the DLL shared header:

#pragma once

#define BUILD_WITH_EASY_PROFILER
#include <easy/profiler.h>

#include "ImGtkAPI.h"

class IMGTK_API ImProfiler
{
public:
  ImProfiler() {};
  ~ImProfiler() {};
  void testProfiling();
};

In the DLL implementation:

void ImProfiler::testProfiling()
{
  EASY_FUNCTION(profiler::colors::Magenta); // Magenta block with name "foo"

  EASY_BLOCK("dll: Calculating sum"); // Begin block with default color == Amber100
  int sum = 0;
  for (int i = 0; i < 10; ++i)
  {
    EASY_BLOCK("dll: Addition", profiler::colors::Red); // Scoped red block (no EASY_END_BLOCK needed)
    sum += i;
  }
  EASY_END_BLOCK; // End of "Calculating sum" block

  EASY_BLOCK("dll: Calculating multiplication", profiler::colors::Blue500); // Blue block
  int mul = 1;
  for (int i = 1; i < 11; ++i)
    mul *= i;
}

In the main exe:

void testExeProfiling()
{
  EASY_FUNCTION(profiler::colors::Magenta); // Magenta block with name "foo"

  EASY_BLOCK("exe: Calculating sum"); // Begin block with default color == Amber100
  int sum = 0;
  for (int i = 0; i < 10; ++i)
  {
    EASY_BLOCK("exe: Addition", profiler::colors::Red); // Scoped red block (no EASY_END_BLOCK needed)
    sum += i;
  }
  EASY_END_BLOCK; // End of "Calculating sum" block

  EASY_BLOCK("exe: Calculating multiplication", profiler::colors::Blue500); // Blue block
  int mul = 1;
  for (int i = 1; i < 11; ++i)
    mul *= i;
}

int main()
{
  EASY_PROFILER_ENABLE;
  ImProfiler profiler;
  profiler.testProfiling();
  testExeProfiling();
  profiler::dumpBlocksToFile("test_profile.prof");
  return 0;
}

As a result, the test_profile.prof file only contains the exe profiling code, and none of the DLL profiling code.

Are we missing something somewhere? A compilation flag or some other option?

[edited for typos]

Marwan-imverse commented 1 year ago

Problem solved.

We are using Conan as a dependency manager, and for some reason it was systematically downloading the static binaries for easy_profiler. By forcing it to use the DLL version, the problem is solved.