microsoft / microsoft/perfview

How to properly use and visualize Start Stop activities in a custom ETW provider

Open
#2,116 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
4.7k
Forks
775
Avg merge
5d 11h
Merged PRs (30d)
9

Description

Context
I'm adding profiling support to an application by emitting ETW events that represent logical function calls.
Currently, after i capture an ETL trace i use a tool to convert it to json for use on speedscope.app, but this produces jsons up to 300MB which does not feel optimal.

The problem
I would like to use something like perfview or Windows Performance Analyzer directly, so i looked into the ETW activity pattern which seems to be meant for this kind of use case, however there is not much documentation.

I tried to follow this reference from ms docs, from what i understand this event pattern should allow perfview to group activities and plot them in a hierarchy view.

Several stackoverflow questions point to the fact that this should be possible, however i couldn't find any working reference code in C.

Repro

I tried writing the following code

#include <stdint.h>
#include <stdbool.h>

#include <windows.h>
#include <winmeta.h>
#include <traceloggingprovider.h>

TRACELOGGING_DEFINE_PROVIDER(
	g_profiler,
	"MyProfiler",
	// Example from https://learn.microsoft.com/it-it/windows/win32/api/traceloggingprovider/nf-traceloggingprovider-tracelogging_define_provider
	// {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5}
	(0xce5fa4ea, 0xab00, 0x5402, 0x8b, 0x76, 0x9f, 0x76, 0xac, 0x85, 0x8f, 0xb5));

void RandomSleep() 
{
	Sleep(10 + rand() % 1000);
}

int main(int argc, char** argv)
{
	if (!SUCCEEDED(TraceLoggingRegister(g_profiler)))
		return -1;
	
	// Expected flamegraph:
	//  inner()         |---------|
	//  outer()  |---------------------| ... repeat

	while (true) {
		GUID outer, inner;
		if (!SUCCEEDED(CoCreateGuid(&outer))) return -2;
		if (!SUCCEEDED(CoCreateGuid(&inner))) return -3;

		printf("> enter outer\n");
		TraceLoggingWriteActivity(
			g_profiler, "Function",
			&outer, NULL,
			TraceLoggingOpcode(WINEVENT_OPCODE_START),
			TraceLoggingString("outer()", "func_name")
		);

		RandomSleep();

		printf(">> enter inner\n");
		TraceLoggingWriteActivity(
			g_profiler, "Function",
			&inner, &outer,
			TraceLoggingOpcode(WINEVENT_OPCODE_START),
			TraceLoggingString("inner()", "func_name")
		);

		RandomSleep();

		printf(">> leave inner\n");
		TraceLoggingWriteActivity(
			g_profiler, "Function",
			&inner, NULL,
			TraceLoggingOpcode(WINEVENT_OPCODE_STOP)
		);

		RandomSleep();

		printf("> leave outer\n");
		TraceLoggingWriteActivity(
			g_profiler, "Function",
			&outer, NULL,
			TraceLoggingOpcode(WINEVENT_OPCODE_STOP)
		);

		RandomSleep();
	}

	return 0;
}

You can build it from Visual Studio or just the command line tools with cl Repro.c Advapi32.lib Ole32.lib (i only tried x64 tools).

Then I start an event collection like this:

And the events are collected properly:

However, when i try to open the stacks view for start-stop activities i get Error: Could not find stack source Any Stacks (with StartStop Activities)

Questions

  • Is there a mistake in the code or have I misunderstood the purpose of start stop activities ?
  • If not activities, is there a way to plot custom function stacks in perfview ?
  • Is there a way to generate flamegraphs from this data ?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the supplied TraceLoggingWriteActivity example and the linked TraceLogging opcode documentation, then compare the collected events with PerfView's StartStop Activities stack view. Determine whether the activity pattern is supported as shown, how custom function stacks or flamegraphs can be produced, and document a working C reference or the relevant limitations.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
performance, tooling
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.