aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/trace.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2024-11-25 09:56:23 +0100
committerGitHub Enterprise <[email protected]>2024-11-25 09:56:23 +0100
commit8b8de92e51db4cc4c1727712c736dcba5f79d369 (patch)
tree1f58edaaad389837a7652daebab246125762240e /src/zencore/trace.cpp
parent5.5.13 (diff)
downloadzen-8b8de92e51db4cc4c1727712c736dcba5f79d369.tar.xz
zen-8b8de92e51db4cc4c1727712c736dcba5f79d369.zip
Insights-compatible memory tracking (#214)
This change introduces support for tracing of memory allocation activity. The code is ported from UE5, and Unreal Insights can be used to analyze the output. This is currently only fully supported on Windows, but will be extended to Mac/Linux in the near future. To activate full memory tracking, pass `--trace=memory` on the commandline alongside `--tracehost=<ip>` or `-tracefile=<path>`. For more control over how much detail is traced you can instead pass some combination of `callstack`, `memtag`, `memalloc` instead. In practice, `--trace=memory` is an alias for `--trace=callstack,memtag,memalloc`). For convenience we also support `--trace=memory_light` which omits call stacks. This change also introduces multiple memory allocators, which may be selected via command-line option `--malloc=<allocator>`: * `mimalloc` - mimalloc (default, same as before) * `rpmalloc` - rpmalloc is another high performance allocator for multithreaded applications which may be a better option than mimalloc (to be evaluated). Due to toolchain limitations this is currently only supported on Windows. * `stomp` - an allocator intended to be used during development/debugging to help track down memory issues such as use-after-free or out-of-bounds access. Currently only supported on Windows. * `ansi` - fallback to default system allocator
Diffstat (limited to 'src/zencore/trace.cpp')
-rw-r--r--src/zencore/trace.cpp90
1 files changed, 88 insertions, 2 deletions
diff --git a/src/zencore/trace.cpp b/src/zencore/trace.cpp
index f7e4c4b68..ef7cbf596 100644
--- a/src/zencore/trace.cpp
+++ b/src/zencore/trace.cpp
@@ -4,10 +4,86 @@
# include <zencore/config.h>
# include <zencore/zencore.h>
+# include <zencore/commandline.h>
+# include <zencore/string.h>
+# include <zencore/logging.h>
# define TRACE_IMPLEMENT 1
# include <zencore/trace.h>
+# include <zencore/memory/memorytrace.h>
+
+namespace zen {
+
+void
+TraceConfigure()
+{
+ // Configure channels based on command line options
+
+ using namespace std::literals;
+
+ constexpr std::string_view TraceOption = "--trace="sv;
+
+ std::function<void(const std::string_view&)> ProcessChannelList;
+
+ auto ProcessTraceArg = [&](const std::string_view& Arg) {
+ if (Arg == "default"sv)
+ {
+ ProcessChannelList("cpu,log"sv);
+ }
+ else if (Arg == "memory"sv)
+ {
+ ProcessChannelList("memtag,memalloc,callstack,module"sv);
+ }
+ else if (Arg == "memory_light"sv)
+ {
+ ProcessChannelList("memtag,memalloc"sv);
+ }
+ else if (Arg == "memtag"sv)
+ {
+ // memtag actually traces to the memalloc channel
+ ProcessChannelList("memalloc"sv);
+ }
+ else
+ {
+ // Presume that the argument is a trace channel name
+
+ StringBuilder<128> AnsiChannel;
+ AnsiChannel << Arg;
+
+ const bool IsEnabled = trace::ToggleChannel(AnsiChannel.c_str(), true);
+
+ if (IsEnabled == false)
+ {
+ // Logging here could be iffy, but we might want some other feedback mechanism here
+ // to indicate to users that they're not getting what they might be expecting
+ }
+ }
+ };
+
+ ProcessChannelList = [&](const std::string_view& OptionArgs) { IterateCommaSeparatedValue(OptionArgs, ProcessTraceArg); };
+
+ bool TraceOptionPresent = false;
+
+ std::function<void(const std::string_view&)> ProcessArg = [&](const std::string_view& Arg) {
+ if (Arg.starts_with(TraceOption))
+ {
+ const std::string_view OptionArgs = Arg.substr(TraceOption.size());
+
+ TraceOptionPresent = true;
+
+ ProcessChannelList(OptionArgs);
+ }
+ };
+
+ IterateCommandlineArgs(ProcessArg);
+
+ if (!TraceOptionPresent)
+ {
+ ProcessTraceArg("default"sv);
+ }
+}
+
void
TraceInit(std::string_view ProgramName)
{
@@ -38,6 +114,16 @@ TraceInit(std::string_view ProgramName)
# endif
CommandLineString,
ZEN_CFG_VERSION_BUILD_STRING);
+
+ atexit([] {
+# if ZEN_WITH_MEMTRACK
+ zen::MemoryTrace_Shutdown();
+# endif
+ trace::Update();
+ TraceShutdown();
+ });
+
+ TraceConfigure();
}
void
@@ -70,13 +156,11 @@ TraceStart(std::string_view ProgramName, const char* HostOrPath, TraceType Type)
case TraceType::None:
break;
}
- trace::ToggleChannel("cpu", true);
}
bool
TraceStop()
{
- trace::ToggleChannel("cpu", false);
if (trace::Stop())
{
return true;
@@ -84,4 +168,6 @@ TraceStop()
return false;
}
+} // namespace zen
+
#endif // ZEN_WITH_TRACE