Coder Social home page Coder Social logo

jonasmr / microprofile Goto Github PK

View Code? Open in Web Editor NEW
1.4K 45.0 115.0 40.42 MB

microprofile is an embeddable profiler

License: MIT License

C 42.66% Makefile 0.03% C++ 28.99% Shell 0.08% HTML 27.48% Lua 0.03% Assembly 0.37% CMake 0.13% Meson 0.22% Batchfile 0.02%

microprofile's Introduction

Build Status

microprofile

Microprofile is a embeddable profiler in a few files, written in C++

Microprofile is hosted on

Integration

#include "microprofile.h"
{
	MICROPROFILE_SCOPEI("group","timername", MP_YELLOW);
	... code to be timed
}

And once each frame you should call

MicroProfileFlip(nullptr);

The implementation of microprofile is in microprofile.cpp, which you must include in your project.

The nullpointer is the void* device context passed for gpu timers.

MicroProfile can be used without calling MicroProfileFlip, in which case you should call MicroProfileDumpFileImmediately, to save the profile data as .html/.csv file on disk.

Gpu Timing

Gpu timers work like normal timers, except they are all put in a shared group, "GPU". To use them insert MICROPROFILE_SCOPEGPUI(). Gpu timers also supports multithreaded renderers - Please refer to demo_nouid3d12 for an example of how to use this. Gpu timers are available for the following apis:

  • OpenGL
  • D3D11
  • D3D12
  • Vulkan

Counters

MicroProfile has support for tracking various counters, that will then be shown in the live & capture views.

	MICROPROFILE_COUNTER_ADD("memory/main", 1000);
	MICROPROFILE_COUNTER_SET("fisk/geder/", 42);

Timeline

The Timeline view in a capture is intended to mark longer, unique timers. It can be used to show stuff like a level loading, with the levels name included.

  • They are intended to mark state that last a long timer - Longer than a single frame
  • They do not appear in the aggregation and cannot be viewed from the
  • They are always active, and are all considered unique
  • They can have fancy names with custom formatted strings.

There are two ways to use it. The first one uses unformatted static string literals:

	MICROPROFILE_TIMELINE_ENTER_STATIC(MP_DARKGOLDENROD, "one");
	MICROPROFILE_TIMELINE_LEAVE_STATIC("one");

The second option allows for arbitrary strings, but requires a token is stored, for the profiler to identify when leaving the marker:

	MICROPROFILE_TIMELINE_TOKEN(token);
	MICROPROFILE_TIMELINE_ENTERF(token, MP_YELLOW, "custom %d %6.2f", 10, 42.0f);
	MICROPROFILE_TIMELINE_LEAVE(token);

Live View

To start microprofile in live mode, simply point chrome to host:1338/ The live view can be used to enable different microprofile groups, using the Control menu. If no groups are enabled, no code is timed. Press the capture button to generate a capture. By default the last 30 frames are capture. The capture itself is a fully contained webpage, that can be saved and shared for further reference.

There are a few ways the webserver can be invoked

  • host:1338/100 (capture 100 frames)
  • host:1338/p/foo (start live view, load preset foo)
  • host:1338/b/foo (start live view, load builtin preset foo)

Presets can be loaded and saved directly from the webbrowser. They are saved by the application in a file named mppresets.cfg. builtin presets are presets, that are loaded from mppresets.builtin.cfg. They work like presets, except they only be loaded. This is intended to be used to do predefined, non-overwriteable configurations.

Alt text

Capture view

Capturing in live view provides a complete view of what is recorded in the ring buffers over a set amount of frames. Please be aware if you capture to far behind, the markers you're are looking for might be overwritten, in which case there will be no markers. As the buffers are reused per thread, this is something that will happen on a per thread basis.

Alt text

Comparing captures

Microprofile supports comparing two different captures. Save the first capture to disk, open the second capture and click compare and browse to the first file. Please be aware that:

  • Only the detailed view is supported
  • Captures saved from earlier versions will not work with this feature
  • When context switch trace is enabled, comparing will only compare registered threads.

Dynamic Instrumentation

On Intel x86-64 Microprofile supports dynamically injecting markers into running code. This is supported on windows, osx and linux(tested on ubuntu) To use this feature

  • Make sure MICROPROFILE_DYNAMIC_INSTRUMENT_ENABLE is defined
  • Make sure to link with distorm and add its include folder to the include path
  • Check dynamic_instrument for an example
  • hold down alt to pan the secondary capture without moving the first capture

Please be aware that this is still a bit experimental, and be aware of these limitations:

  • The profiler does not attempt to stop all running threads while instrumenting.
    • This potentially can cause issues, as there is a critical moment when replacing the first 14 bytes of the function being patched. If any thread is executing the code begin replaced, the program behaviour will not be well defined
    • For development this is usually fine
  • The instrumentation does not need the program to be compiled or linked in any specific way
    • But it does not support instrumenting all possible x86-64 code sequences - IE it might fail.
    • It needs at least 14 bytes of instructions to instrument a function
  • On linux you need to link your program with -rdynamic, in order to make the it possible to find the functions using dladdr
    • if you know of any way to query this without linking with -rdynamic I'd love to hear about it.

If compiled and linked with Dynamic Instrumentation, two new menus appear, "modules" and "functions".

The "modules" menu allows you to load debug information from your loaded modules. Select one or more modules to load from. Once its loaded the bar behind the module name is filled, and the debug information is ready.

Modules screenshot

Once the debug symbols are loaded - Indicated by the number in the top of the functions menu - You can start typing to search for functions to instrument.

  • Click on a function to attempt to instrument it
  • If instrumentation fails, you´ll be asked to report the code sequence. Please consider doing this.
  • Click on '>>' next to a function, to attempt to instrument all the functions called by that function
    • Only functions called that also have a name in the debug information will be instrumented

Functions screenshot

Example code

  • noframes: Using microprofile to profile an application without any concept of frames. dumps a capture at the end. No live view.
  • simple: frame based implementation. with live view. No gpu timing
  • d3d11: frame based implementation, with live view and D3D11 gpu timers
  • d3d12: frame based implementation, with live view and D3D12 gpu timers
  • d3d12_multithreading: frame based implementation, with live view and D3D12 gpu timers, with gpu timings generated from multiple threads.
  • gl: frame based implementation, with live view and OpenGL gpu timers
  • vulkan: Copy of the vulkan Hologram sample, fixed to use microprofile cpu and gpu markers. Only tested on windows.
  • dynamic_instrument: Demo for dynamic instrumentation.
  • workbench: Workbench for development. Using all features of microprofile.

Dependencies

  • Microprofile supports generating compressed captures using miniz(http:/code.google.com/miniz).
  • Distorm is used to disassemble x86-64 when using dynamic instrumentation(https://github.com/gdabah/distorm)

Resource usage

MicroProfile uses a few large allocations.

  • One global instance of struct MicroProfile
  • One Large Allocation per thread that its tracking (MICROPROFILE_PER_THREAD_BUFFER_SIZE, default 2mb)
  • One Large Allocation per gpu buffer used (MICROPROFILE_PER_THREAD_GPU_BUFFER_SIZE, default 128k)
  • one thread for sending
  • one thread for handling context switches, when enabled
  • 128kb for context switch data, when context switch tracing is enabled.
  • two small variable size buffers. should not be more than a few kb.
    • A state buffer for receiving websocket packets
    • A state buffer for loading/saving settings.
  • one small allocation for receiving packets from the sender

To change how microprofile allocates memory, define these macros when compiling microprofile implementation

  • MICROPROFILE_ALLOC
  • MICROPROFILE_REALLOC
  • MICROPROFILE_FREE

microprofile.config.h

Microprofile has lots of predefined macros that can be changed. To modify this, make sure MICROPROFILE_USE_CONFIG is defined, and put the changed defines in microprofile.config.h.

Known Issues & Limitations

There are a few minor known issues & Limitations:

  • Currently the relative placement of gpu timings vs the cpu timings tend to slide a bit, and thus the relative position of GPU timestamps and CPU timestamp are not correct.
  • Chrome has an internal limit to how big a page it will cache. if you generate a capture file that is larger than 32mb, chrome will refuse to cache it. This causes the page to redownload when you save it, which is pretty catastrophic, since it will generate a capture. To mitigate this:
    • Use miniz. This drastically reduces the size of captures, to the point where its no longer a problem
    • If you still have issues, increase chromes disk cache size.
  • If you're dynamically creating threads, you must call MicroProfileOnThreadExit when threads exit, to reuse the thread log objects
  • instrumentation is only supported on x86-64

Console support

Microprofile supports the two major consoles - Search for 'microprofile' in the closed platform forums.

Changes

V4

  • Timeline view is now drawn using a hierarchical algorithm that scales better
  • Search in timeline view has been improved
    • you can now search for substrings interactively
    • search result now highlights by changing the color
    • and there is no longer any limit on the amount of search results
  • Added section markers, that allow you to group sections of code indepently of group/timer name.
  • Added CStr markers. This lets you pass in a static CStr, which will appear in the timeline view
    • Note that the caller is responsible for ensuring the CStr stays allocated, as it will be deferenced when generating a capture
    • only works in the timeline view, and is not usable in the various aggregation + live view
  • Fixed thread hide mode to be collapsed(which is what it should've been). Added a shortcut key to toggle it ('c')
  • Switched build to use github actions

License

Licensed using UNLICENSE

microprofile's People

Contributors

awangk avatar crossvr avatar dougbinks avatar jbeich avatar jonasmr avatar jonil avatar julien1619 avatar looki avatar madebr avatar pixelmager avatar richyhbm avatar skylark13 avatar tachi107 avatar tek-nishi avatar uilianries avatar vbieleny avatar xiphon avatar zenoarrows avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

microprofile's Issues

Crash in MicroProfileCreateThreadLog() when (S.nNumLogs > MICROPROFILE_MAX_THREADS)

In this code, it's perfectly possible for pOldest to still be nullptr when it comes to the end (Which I know from observation).

While this condition has an ASSERT, that doesn't stop it immediately trying to reset the null pointer if you're in a release build, with hilarious consequences.

Easy repro case is to set MICROPROFILE_MAX_THREADS to 1 or 2.

This is a pain if you have a variable number of threads being profiled, so there is no safe level to set MICROPROFILE_MAX_THREADS to.

MicroProfileCreateThreadLog()
...
	if(S.nNumLogs == MICROPROFILE_MAX_THREADS && S.nFreeListHead == -1)
	{
		uprintf("recycling thread logs\n");
		//reuse the oldest.
		MicroProfileThreadLog* pOldest = 0;
		uint32_t nIdleFrames = 0;
		for(uint32_t i = 0; i < MICROPROFILE_MAX_THREADS; ++i)
		{
			MicroProfileThreadLog* pLog = S.Pool[i];
			uprintf("tlactive %p, %d.  idle:%d\n", pLog, pLog->nActive, pLog->nIdleFrames); 
			if(pLog->nActive == 2)
			{
				if(pLog->nIdleFrames >= nIdleFrames)
				{
					nIdleFrames = pLog->nIdleFrames;
					pOldest = pLog;
				}
			}
		}
		MP_ASSERT(pOldest);
		MicroProfileLogReset(pOldest);
	}

Possible fix suggestion is to simply fail the function and return nullptr from MicroProfileCreateThreadLog() if it hasn't got any more room. Although this does rather push the problem to the caller.

read access violation in microprofile.cpp:3828

Hey,

this project looks very useful, thanks for making it! :)
I'm trying microprofile for the first time and I'm always getting a read access violation (see title) as soon as I try to capture frames using the capture button in the live view.
I'm testing this with the noui_vulkan demo running with VS2015 on Windows 8.1.
It doesn't crash if I go to 127.0.0.1:1338/30 directly, but it also does not display any data.
I'm not sure how to actually use microprofile yet, but it looks like I can currently not get any capture data out of the demo app...
Am I missing something?

Thank you.

any interest in direct-to-terminal output?

first off, let me say this project looks awesome; very nicely done.

i'm the author of a TUI/character graphics library called Notcurses. it just so happens that i was planning to this weekend start a similarish project from scratch, loosely described here:

dankamongmen/notcurses#381

this was going to involve running perf atop arbitrary binaries rather than being embedded into them, but your approach already has so much of the control end done that i think i'd rather leverage your work on microprofile. so, i'm going to look into making live terminal output an alternative to your webserver+browser approach. is this something that would interest y'all as upstream authors -- i.e. something i ought plan to PR, something that doesn't clash with your vision -- or ought i just plan to keep it as a fork?

thanks for your time evaluating this (admittedly somewhat vague) idea.

Some issues that cppcheck reported

Maybe you are interested in the report. Used cppcheck 1.76.1.

[src/modules/core/trace/microprofile.cpp:935]: (error) Using 'memset' on struct that contains a 'std::atomic'.
[src/modules/core/trace/microprofile.cpp:1089]: (error) Using 'memset' on struct that contains a 'std::atomic'.
[src/modules/core/trace/microprofile.cpp:4262]: (error) Array 'g_MicroProfile.WebSockets[1]' accessed at index 1, which is out of bounds.
[src/modules/core/trace/microprofile.cpp:5934]: (error) Uninitialized struct member: P.nNumProcesses
[src/modules/core/trace/microprofile.cpp:5934]: (error) Uninitialized struct member: P.nNumThreads
[src/modules/core/trace/microprofile.cpp:5934]: (error) Uninitialized struct member: P.nStringOffset
[src/modules/core/trace/microprofile.cpp:5934]: (error) Uninitialized struct member: P.nNumStrings
[src/modules/core/trace/microprofile.cpp:5934]: (error) Uninitialized struct member: P.nNumModules

D3D12 GPU scopes are broken

When I try to profile our game with markers for GPU I get crash on latest microprofile.
I think I managed to trace down this issue.
Problem seems to happen in MicroProfileGpuFlip, when doing ResolveQueryData It's input, nStart points to the first marker added in this frame, but we saturate GPU with a LOT of work, so it just finishes rendering previous frame. So queries from this frame were not yet executed and, thus, timestamps for any queries will be 0.
Eventually when microprofile tries to submit information about markers it takes timestamp (0), does some math on it ends up with negative value and crashes on this assert MP_ASSERT(nTicks < 0x8000000000000000). line 3070.
It works in loading screen, when all we render is just a few sprites, but crashes as soon as we loaded first level.
It looks like this code:

		nCount = S.pGPU->nFrameCount.exchange(0);
		nStart = S.pGPU->nFrameStart;
		S.pGPU->nFrameStart = (S.pGPU->nFrameStart + nCount) % MICROPROFILE_D3D_MAX_QUERIES;
		uint32_t nEnd = MicroProfileMin(nStart + nCount, (uint32_t)MICROPROFILE_D3D_MAX_QUERIES);
		MP_ASSERT(nStart != nEnd);
		uint32_t nSize = nEnd - nStart;
		pCommandList->ResolveQueryData(S.pGPU->NodeState[nNode].pHeap, D3D12_QUERY_TYPE_TIMESTAMP, nStart, nEnd - nStart, S.pGPU->pBuffer, nStart * sizeof(int64_t));

has to be rewritten to query data for previous markers, not current, but I might be wrong.

Deadlock when calling MicroProfileDumpFileImmediately just before MicroProfileShutdown under linux x64

For a while now I noticed this behavior, for current and past revisions of microprofile. My use case consists of profiling a program and then exiting after dumping the profile info. Here's my gdb dump of the behavior:

[New Thread 0x7f4aded35700 (LWP 21069)]              
^C                        
Thread 1 "reaper" received signal SIGINT, Interrupt. 
0x00007f4ae132133d in pthread_join () from /usr/lib/libpthread.so.0                                       
(gdb) info threads        
  Id   Target Id         Frame                       
* 1    Thread 0x7f4ae2bc4740 (LWP 21048) "reaper" 0x00007f4ae132133d in pthread_join ()                   
   from /usr/lib/libpthread.so.0                     
  2    Thread 0x7f4aded35700 (LWP 21069) "reaper" 0x00007f4ae132954c in __lll_lock_wait ()                
   from /usr/lib/libpthread.so.0                     
(gdb) thread apply 1 bt   

Thread 1 (Thread 0x7f4ae2bc4740 (LWP 21048)):        
#0  0x00007f4ae132133d in pthread_join () from /usr/lib/libpthread.so.0                                   
#1  0x00007f4ae200f467 in MicroProfileThreadJoin (pThread=0x7f4ae24f76b0 <g_MicroProfile+2528368>)        
    at /home/ryp/dev/Reaper/external/microprofile/microprofile.cpp:896                                    
#2  0x00007f4ae201b7e3 in MicroProfileWebServerStop ()                                                    
    at /home/ryp/dev/Reaper/external/microprofile/microprofile.cpp:4222                                   
#3  0x00007f4ae200fa69 in MicroProfileShutdown ()    
    at /home/ryp/dev/Reaper/external/microprofile/microprofile.cpp:1129                                   
#4  0x00000001000041b2 in main () at /home/ryp/dev/Reaper/src/main.cpp:55                                 
(gdb) thread apply 2 bt                                                                                   

Thread 2 (Thread 0x7f4aded35700 (LWP 21069)):        
#0  0x00007f4ae132954c in __lll_lock_wait () from /usr/lib/libpthread.so.0                                
#1  0x00007f4ae1322976 in pthread_mutex_lock () from /usr/lib/libpthread.so.0                             
#2  0x00007f4ae200f2a5 in __gthread_mutex_lock (__mutex=0x7f4ae228af60 <MicroProfileMutex()::Mutex>)      
    at /usr/include/c++/7.1.1/x86_64-pc-linux-gnu/bits/gthr-default.h:748                                 
#3  0x00007f4ae200f2f5 in __gthread_recursive_mutex_lock (                                                
    __mutex=0x7f4ae228af60 <MicroProfileMutex()::Mutex>)                                                  
    at /usr/include/c++/7.1.1/x86_64-pc-linux-gnu/bits/gthr-default.h:810                                 
#4  0x00007f4ae2024f6e in std::recursive_mutex::lock (this=0x7f4ae228af60 <MicroProfileMutex()::Mutex>)   
    at /usr/include/c++/7.1.1/mutex:107              
#5  0x00007f4ae2025324 in MicroProfileScopeLock::MicroProfileScopeLock (this=0x7f4aded34dd0, m=...)       
    at /home/ryp/dev/Reaper/external/microprofile/microprofile.cpp:1175                                   
#6  0x00007f4ae200fb55 in MicroProfileCreateThreadLog (                                                   
    pName=0x7f4ae202d090 "MicroProfileSocketSenderThread")                                                
    at /home/ryp/dev/Reaper/external/microprofile/microprofile.cpp:1186                                   
#7  0x00007f4ae200fefd in MicroProfileOnThreadCreate (                                                    
    pThreadName=0x7f4ae202d090 "MicroProfileSocketSenderThread")                                          
    at /home/ryp/dev/Reaper/external/microprofile/microprofile.cpp:1223                                   
#8  0x00007f4ae201e436 in MicroProfileSocketSenderThread ()                                               
    at /home/ryp/dev/Reaper/external/microprofile/microprofile.cpp:4628                                   
#9  0x00007f4ae1320049 in start_thread () from /usr/lib/libpthread.so.0                                   
#10 0x00007f4adfa6cf0f in clone () from /usr/lib/libc.so.6                                                
(gdb)  

I'll provide a minimal repro case if needed, hope this is enough to track down the bug.
The current source that I use to repro this bug can be found here.

Implicit fallthrough

Hey,

I was wondering whether this implicit fallthrough was meant to be here.

microprofile/microprofile.cpp

Lines 5444 to 5449 in bca802b

case 'd':
{
MicroProfileWebSocketClearTimers();
memset(&S.nActiveGroupsWanted, 0, sizeof(S.nActiveGroupsWanted));
S.nWebSocketDirty |= MICROPROFILE_WEBSOCKET_DIRTY_ENABLED;
}

Wrong timing for scopes

While integrating microprofile into our engine I've noticed that some scopes have wrong timing.
For example we synchronize render and update threads with event - update thread waits on render thread to signal after it's done with rendering. After that update thread sends a message to render thread to update profiler and call MicroprofileFlip. It's demonstrated on screenshot. You can clearly see that Flip is displayed at least 0.5ms before it's even called!
While investigating this issue I added a few Sleep(1) here and there and then I've noticed that our jobs were misplaced by roughly 1ms - render thread spawns jobs and then waits on them, however profiler output shows that wait has finished even before worker threads started executing any jobs.
So I suspect Sleep somehow interferes.
Any pointers?

XB1 version is missing from forum

Hi Jonas,

Can you re-upload XB1 version of microprofile to XB1 Dev Forum?
Your 2 years old topic is closed by MS and it has no attachment in it :(

Race condition on shutdown

I'm using microprofile in a dll that can be unloaded before the executable closes. I call MicroProfileShutdown before the dll is unloaded (not in dllmain or anything, I get a function call to shut everything down).

However for the webserver thread this only sets S.nMicroProfileShutdown = 1 and returns, it doesn't synchronise on WebSocketSendThread actually finishing, so there's a gap between MicroProfileShutdown returning and the thread exiting, where my dll can get unloaded and suddenly the thread that's running doesn't have code to execute because the page is gone.

I think it should do something like MicroProfileThreadJoin(&S.WebSocketSendThread); after setting the shutdown flag to 1?

Counters don't pause

When you pause, the timers all remain in place on the timeline, but I notice that counters move along their timelines slowly even when FROZEN[space] is on screen.

Count is incremented extra for timers that overlap calls to MicroProfileFlip

Hello,
I either found an issue where timers report numbers incorrectly, or I'm misunderstanding something.
TL;DR - S.Frame[nTimerIndex].nCount seems wrong for timers that overlap a call to MicroProfileFlip()

--

I have a background thread doing work like this:

{
MicroProfileEnter(token);
StuffThatTakesOneSecond();
MicroProfileLeave();
}

The main thread is calling MicroProfileFlip(nullptr) at 60 FPS.

The main thread is also polling for activity on my token's name via a custom function like MicroProfileGetTime which also returns S.Frame[nTimerIndex].nCount so I know how often the code is called.

The problem I run into is that it looks like the StuffThatTakesOneSecond shows up 61 times in the log, for an average of 16.3 ms per call, while the truth is that it is only called one time, taking 1 second.

This appears to be due to line 3250
S.Frame[nTimerIndex].nCount += 1;
https://github.com/jonasmr/microprofile/blob/master/microprofile.cpp#L3250
Every still-going timer's nCount is incremented when a flip happens, which is throwing off my numbers.

If I comment out that line, then I get the expected results when I poll for data - I get something like time=0.016f, count=0 for sixty frames in a row, then time=something, count=1. My total collected data tells me StuffThatTakesOneSecond ran for a second, and was called once.

This (maybe) bug also has the side-effect of skewing how often code seems to be run, based on how long that instrumented code takes. I found some code with an average time of 9 ms getting called 16,000 times. After optimization it took 2 ms, but was only called 8,000 times. The calling behavior never changed, and the truth was that the code was only running about 7,200 times both before and after the optimization.

--

Question 1 - Does this seem like a bug in MicroProfile, or does it seem like I'm misunderstanding something?
Question 2 - If this is a bug, is line 3255 also unnecessary?
pFrameGroupThread[nGroup].nCount += 1;
https://github.com/jonasmr/microprofile/blob/master/microprofile.cpp#L3255
I couldn't figure out the right way to verify whether the HTML view is affected by this, but it seems like if one line should be removed, the other should be too.

Thanks in advance
-Eric

GPU functions not defined on Linux

Possibly related to #2.

Compiling on Linux gives the following errors at link time:

CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileTickToMsMultiplierGpu':
microprofile.cpp:(.text+0x8f5): undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileCalcAllTimers(float*, float*, float*, float*, float*, float*, float*, float*, float*, unsigned int)':
microprofile.cpp:(.text+0x2fd5): undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileDumpCsv(void (*)(void*, unsigned long, char const*), void*)':
microprofile.cpp:(.text+0x3482): undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileShutdown':
microprofile.cpp:(.text+0x7505): undefined reference to `MicroProfileGpuShutdown'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileGetTime':
microprofile.cpp:(.text+0x8531): undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileDumpHtml(void (*)(void*, unsigned long, char const*), void*, unsigned long, char const*, unsigned long)':
microprofile.cpp:(.text+0x8ff5): undefined reference to `MicroProfileTicksPerSecondGpu'
microprofile.cpp:(.text+0xa14c): undefined reference to `MicroProfileTicksPerSecondGpu'
microprofile.cpp:(.text+0xa166): undefined reference to `MicroProfileGetGpuTickReference'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileWebSocketSendFrame(int)':
microprofile.cpp:(.text+0xc808): undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileFlip_CB':
microprofile.cpp:(.text+0xdbae): undefined reference to `MicroProfileGpuFlip'
microprofile.cpp:(.text+0xe006): undefined reference to `MicroProfileGpuGetTimeStamp'
microprofile.cpp:(.text+0xe023): undefined reference to `MicroProfileTicksPerSecondGpu'
microprofile.cpp:(.text+0xe379): undefined reference to `MicroProfileGpuGetTimeStamp'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileGpuEnterInternal':
microprofile.cpp:(.text+0xf560): undefined reference to `MicroProfileGpuInsertTimeStamp'
CMakeFiles/Training.dir/src/third_party/microprofile.cpp.o: In function `MicroProfileGpuLeaveInternal':
microprofile.cpp:(.text+0xf736): undefined reference to `MicroProfileGpuInsertTimeStamp'

Looking through the code, I don't see any definitions for these functions in the __unix__ sections.

How do I customize microprofile metrics URL

It is a basic question but I am unable to find information on this.

Unlike Spring Actuator, which adds context path to the URL automatically, I dont see this happening with Microprofile. So, I end up with say /metrics url like

https://myserver/metrics

This however is not good enough. I would like to have url like:

https://myserver/myApi/metrics

, where myApi is the context path of myApi application.

Otherwise, if I have 10 application all exposing metrics data on same url (https://myserver/metrics), it is difficult to distinguish between them.

memset will clear std::atomic

On

memset(&S, 0, sizeof(S));

and
memset(pLog, 0, sizeof(*pLog));

An object of MicroProfileThreadLog is cleared.

This operation is unsafe because the std::atomic in there have no trivial copy-assignment.

/home/maarten/programming/openrw/external/microprofile/microprofile/microprofile.cpp:1221: warning: ‘void* memset(void*, int, size_t)’ clearing an object of type ‘struct MicroProfileThreadLog’ with no trivial copy-assignment; use value-initialization instead [-Wclass-memaccess]
         memset(pLog, 0, sizeof(*pLog));
                                      ^

miniz not used in the right place

Currently MICROPROFILE_MINIZ is defined to 1 in the demos and "miniz.c" is included there. However, no one really uses it. I also checked the web server response and found no deflate.

I then moved the MICROPROFILE_MINIZ-related stuff to the beginning of microprofile.cpp (I also needed to copy the miniz.c file). Now I can really see "Content-Encoding: deflate" in the HTTP response header.

So I think the source and demo files should be changed, and miniz.c should have only one copy and be in the same directory as microprofile.cpp.

Can‘t build microprofile with mingw64

My mingw64 is download from WinLibs

when I build this project with

cmake .. -G "Ninja"
ninja

the error is

[1/2] Building CXX object CMakeFiles/microprofile.dir/microprofile.cpp.obj
FAILED: CMakeFiles/microprofile.dir/microprofile.cpp.obj
D:\mingw64\bin\c++.exe -DMICROPROFILE_EXPORT -ID:/C++_proj/microprofile -ID:/C++_proj/microprofile/build  -MD -MT CMakeFiles/microprofile.dir/microprofile.cpp.obj -MF CMakeFiles\microprofile.dir\microprofile.cpp.obj.d -o CMakeFiles/microprofile.dir/microprofile.cpp.obj -c D:/C++_proj/microprofile/microprofile.cpp
D:/C++_proj/microprofile/microprofile.cpp: In function 'void MicroProfileThreadStart(void**, MicroProfileThreadFunc)':
D:/C++_proj/microprofile/microprofile.cpp:1206:53: error: invalid conversion from 'MicroProfileThreadFunc' {aka 'void* (*)(void*)'} to 'LPVOID' {aka 'void*'} [-fpermissive]
 1206 |     *pThread = CreateThread(0, 0, ThreadTrampoline, Func, 0, 0);
      |                                                     ^~~~
      |                                                     |
      |                                                     MicroProfileThreadFunc {aka void* (*)(void*)}
In file included from d:\mingw64\x86_64-w64-mingw32\include\winbase.h:29,
                 from d:\mingw64\x86_64-w64-mingw32\include\windows.h:70,
                 from d:\mingw64\x86_64-w64-mingw32\include\winsock2.h:23,
                 from D:/C++_proj/microprofile/microprofile.cpp:227:
d:\mingw64\x86_64-w64-mingw32\include\processthreadsapi.h:279:150: note:   initializing argument 4 of 'void* CreateThread(LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD)'
  279 |   WINBASEAPI HANDLE WINAPI CreateThread (LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
      |                                                                                                                                               ~~~~~~~^~~~~~~~~~~
D:/C++_proj/microprofile/microprofile.cpp: At global scope:
D:/C++_proj/microprofile/microprofile.cpp:1296:40: warning: 'thread' attribute directive ignored [-Wattributes]
 1296 | MP_THREAD_LOCAL MicroProfileThreadLog* g_MicroProfileThreadLogThreadLocal = 0;
      |                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
D:/C++_proj/microprofile/microprofile.cpp: In function 'bool MicroProfileStartWin32Trace(EventCallback, BufferCallback)':
D:/C++_proj/microprofile/microprofile.cpp:7350:19: warning: passing NULL to non-pointer argument 1 of 'ULONG StopTraceA(TRACEHANDLE, LPCSTR, PEVENT_TRACE_PROPERTIES)' [-Wconversion-null]
 7350 |         StopTrace(NULL, KERNEL_LOGGER_NAME, &sessionProperties);
      |                   ^~~~
In file included from D:/C++_proj/microprofile/microprofile.cpp:7241:
d:\mingw64\x86_64-w64-mingw32\include\evntrace.h:858:49: note:   declared here
  858 |   EXTERN_C ULONG WMIAPI StopTraceA (TRACEHANDLE TraceHandle, LPCSTR InstanceName, PEVENT_TRACE_PROPERTIES Properties);
      |                                     ~~~~~~~~~~~~^~~~~~~~~~~
ninja: build stopped: subcommand failed.

Compilation fails on linux

In file included from src/modules/core/Trace.cpp:24:
src/modules/core/trace/microprofile.cpp:1838:19: warning: comparison of integers of different signs: 'int64_t' (aka 'long') and 'unsigned long' [-Wsign-compare]
        MP_ASSERT(nCount < MICROPROFILE_GPU_BUFFER_SIZE);
        ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/modules/core/trace/microprofile.cpp:199:30: note: expanded from macro 'MP_ASSERT'
#define MP_ASSERT(a) do{if(!(a)){MP_BREAK();} }while(0)
                             ^
src/modules/core/trace/microprofile.cpp:3699:2: error: use of undeclared identifier 'send'
        send(Socket, &S.WebServerBuffer[0], S.WebServerPut, 0);
        ^
src/modules/core/trace/microprofile.cpp:3711:3: error: use of undeclared identifier 'send'
                send(Socket, pData, (int)nSize, 0);
                ^
src/modules/core/trace/microprofile.cpp:3870:28: error: use of undeclared identifier 'PF_INET'
        S.ListenerSocket = socket(PF_INET, SOCK_STREAM, 6);
                                  ^
src/modules/core/trace/microprofile.cpp:3870:37: error: use of undeclared identifier 'SOCK_STREAM'
        S.ListenerSocket = socket(PF_INET, SOCK_STREAM, 6);
                                           ^
src/modules/core/trace/microprofile.cpp:3871:13: error: use of undeclared identifier 'MP_INVALID_SOCKET'
        MP_ASSERT(!MP_INVALID_SOCKET(S.ListenerSocket));
                   ^
src/modules/core/trace/microprofile.cpp:3875:21: error: variable has incomplete type 'struct sockaddr_in'
        struct sockaddr_in Addr; 
                           ^
src/modules/core/trace/microprofile.cpp:3875:9: note: forward declaration of 'sockaddr_in'
        struct sockaddr_in Addr; 
               ^
src/modules/core/trace/microprofile.cpp:3876:20: error: use of undeclared identifier 'AF_INET'
        Addr.sin_family = AF_INET; 
                          ^
src/modules/core/trace/microprofile.cpp:3877:25: error: use of undeclared identifier 'INADDR_ANY'
        Addr.sin_addr.s_addr = INADDR_ANY; 
                               ^
src/modules/core/trace/microprofile.cpp:3880:19: error: use of undeclared identifier 'htons'
                Addr.sin_port = htons(MICROPROFILE_WEBSERVER_PORT+i); 
                                ^
src/modules/core/trace/microprofile.cpp:3881:35: error: use of undeclared identifier 'sockaddr'
                if(0 == bind(S.ListenerSocket, (sockaddr*)&Addr, sizeof(Addr)))
                                                ^
src/modules/core/trace/microprofile.cpp:3881:44: error: expected expression
                if(0 == bind(S.ListenerSocket, (sockaddr*)&Addr, sizeof(Addr)))
                                                         ^
src/modules/core/trace/microprofile.cpp:3887:2: error: use of undeclared identifier 'listen'
        listen(S.ListenerSocket, 8);
        ^
src/modules/core/trace/microprofile.cpp:4996:17: warning: comparison of integers of different signs: 'uint64_t' (aka 'unsigned long') and 'int' [-Wsign-compare]
                if(nSizeBytes != r)
                   ~~~~~~~~~~ ^  ~
src/modules/core/trace/microprofile.cpp:5015:13: warning: comparison of integers of different signs: 'unsigned long' and 'char' [-Wsign-compare]
        if(nSize+1 > BytesAllocated)
           ~~~~~~~ ^ ~~~~~~~~~~~~~~
src/modules/core/trace/microprofile.cpp:5448:33: warning: comparison of integers of different signs: 'int' and 'uint32_t' (aka 'unsigned int') [-Wsign-compare]
                        uint32_t parent = CI.nParent == (uint32_t)-1 ? 0 : MicroProfileWebSocketIdPack(TYPE_COUNTER, CI.nParent);
                                          ~~~~~~~~~~ ^  ~~~~~~~~~~~~
src/modules/core/trace/microprofile.cpp:5474:6: error: use of undeclared identifier 'MP_INVALID_SOCKET'
        if(!MP_INVALID_SOCKET(Connection))
            ^

The error here is a problem with the header inclusion guard in line 845. There is only #if defined(__APPLE__) where it should have been #if defined(__APPLE__) || defined(__linux__)

If you add this, you get a lot of unresolved symbols:


../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileTickToMsMultiplierGpu':
src/modules/core/trace/microprofile.cpp:748: undefined reference to `MicroProfileTicksPerSecondGpu'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileShutdown':
src/modules/core/trace/microprofile.cpp:1026: undefined reference to `MicroProfileGpuShutdown'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileAllocInternal(unsigned long, unsigned long)':
src/modules/core/trace/microprofile.cpp:1932: undefined reference to `MicroProfileAllocAligned(unsigned long, unsigned long)'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileGpuEnterInternal':
src/modules/core/trace/microprofile.cpp:1858: undefined reference to `MicroProfileGpuInsertTimeStamp'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileGpuLeaveInternal':
src/modules/core/trace/microprofile.cpp:1878: undefined reference to `MicroProfileGpuInsertTimeStamp'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileFlip':
src/modules/core/trace/microprofile.cpp:2122: undefined reference to `MicroProfileGpuFlip'
src/modules/core/trace/microprofile.cpp:2163: undefined reference to `MicroProfileGpuGetTimeStamp'
src/modules/core/trace/microprofile.cpp:2164: undefined reference to `MicroProfileTicksPerSecondGpu'
src/modules/core/trace/microprofile.cpp:2272: undefined reference to `MicroProfileGpuGetTimeStamp'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileCalcAllTimers(float*, float*, float*, float*, float*, float*, float*, float*, float*, unsigned int)':
src/modules/core/trace/microprofile.cpp:2650: undefined reference to `MicroProfileTicksPerSecondGpu'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileGetTime':
src/modules/core/trace/microprofile.cpp:2703: undefined reference to `MicroProfileTicksPerSecondGpu'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileDumpCsv(void (*)(void*, unsigned long, char const*), void*)':
src/modules/core/trace/microprofile.cpp:2968: undefined reference to `MicroProfileTicksPerSecondGpu'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileDumpHtml(void (*)(void*, unsigned long, char const*), void*, unsigned long, char const*, unsigned long)':
src/modules/core/trace/microprofile.cpp:3096: undefined reference to `MicroProfileTicksPerSecondGpu'
src/modules/core/trace/microprofile.cpp:3435: undefined reference to `MicroProfileTicksPerSecondGpu'
src/modules/core/trace/microprofile.cpp:3437: undefined reference to `MicroProfileGetGpuTickReference'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `MicroProfileWebSocketSendFrame(int)':
src/modules/core/trace/microprofile.cpp:5180: undefined reference to `MicroProfileTicksPerSecondGpu'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `core::traceGLInit()':
src/modules/core/Trace.cpp:109: undefined reference to `MicroProfileGpuShutdown'
../../../Debug/lib/libcore.a(Trace.cpp.o): In function `core::traceGLShutdown()':
src/modules/core/Trace.cpp:120: undefined reference to `MicroProfileGpuShutdown'

Is there anything i'm missing here?

microprofile embeds non-free code

Hi, microprofile currently contains some non-free JavaScript code embedded in src/microprofile*.html, specifically the HSL to/from RGB functions:

function ConvertRgbToHsl(hexTripletColor) //from https://gist.github.com/mjackson/5311256
{
var color = hexTripletColor;
color = color.substring(1);
color = parseInt(color, 16);
var r = ((color >> 16) % 256)/255.0;
var g = ((color >> 8) % 256)/255.0;
var b = ((color >> 0) % 256)/255.0;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
}
else
{
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max)
{
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [ h, s, l ];
}
function ConvertHslToColor(h, s, l) //from https://gist.github.com/mjackson/5311256
{
var r, g, b;
if (s == 0)
{
r = g = b = l; // achromatic
}
else
{
function hue2rgb(p, q, t)
{
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
var color = ((r*255)<<16) | ((g*255)<<8) | (b*255);
return '#' + ("000000" + color.toString(16)).slice(-6);
}

The code from https://gist.github.com/mjackson/5311256 is not licensed, meaning that it cannot be used for any purpose; on the Gist thread, people asked multiple times for a license, but the author never did so.

On that same thread, user @vahidk linked to an alternative implementation free to use for any purpose: https://gist.github.com/mjackson/5311256?permalink_comment_id=2710361#gistcomment-2710361. I'd suggest using that instead.

This has been originally reported on Debian: https://bugs.debian.org/1023178

Vulkan validation errors

I'm getting the following validation errors when using microprofile with Khronos validation layers enabled:

When enabling the GPU group in the web UI:

VkQueryPool 0xf37618000000003d[] was created with a queryType of VK_QUERY_TYPE_TIMESTAMP but flags contains VK_QUERY_RESULT_PARTIAL_BIT. The Vulkan spec states: If the queryType used to create queryPool was VK_QUERY_TYPE_TIMESTAMP, flags must not contain VK_QUERY_RESULT_PARTIAL_BIT (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkGetQueryPoolResults-queryType-00818)

On application shutdown:

For VkDevice 0x1bd3b004f90[], VkCommandBuffer 0x1bd4036df30[] has not been destroyed. The Vulkan spec states: All child objects created on device must have been destroyed prior to destroying device (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkDestroyDevice-device-00378)

Is this an accepted limitation or am I doing something wrong on my end?

Any short but complete examples?

Hi, it's not very clear for beginners how to use this library. Is there a short and complete example that explains how to use it in actual code, where the instrumentation data is written, how to query/view that data, and how to view these data live in Live View?

From the Readme, it's not so clear how to accomplish most of that.

I get some idea that
MICROPROFILE_SCOPEI is for instrumenting a function scope. But where does the instrumentation data reside, and how do I view it? Also, it says to call MicroProfileFlip(nullptr); - what does it do? And then, MICROPROFILE_TIMELINE_ENTER/LEAVE_STATIC seems to be something that tracks entry/exit points, likely something that can add some data points to the timeline (guessing by the names?), but when I open Live View, I don't see anything.

Use cmake is error.

When I compile the source code use cmake and c++17, I got the error

my cmake code is

INCLUDE_DIRECTORIES(
    ${PROJECT_SOURCE_DIR}/lib/microprofile
)



LINK_DIRECTORIES(
    ${PROJECT_SOURCE_DIR}/lib/microprofile
)
set(SOURCES

    ${PROJECT_SOURCE_DIR}/lib/microprofile/microprofile.cpp
    ${PROJECT_SOURCE_DIR}/main.cc


)

main code is

#define MICROPROFILE_MAX_FRAME_HISTORY (2<<10)
#define MICROPROFILE_IMPL
#include "microprofile.h"

int main(){
    MICROPROFILE_SCOPEI("my test","timername",MP_YELLOW);
    {
    print somthing();
    }
}
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileTickToMsMultiplierGpu':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:1128: undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileShutdown':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:1513: undefined reference to `MicroProfileGpuShutdown'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileGpuEnterInternal':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:2645: undefined reference to `MicroProfileGpuInsertTimeStamp'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileGpuLeaveInternal':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:2666: undefined reference to `MicroProfileGpuInsertTimeStamp'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileFlip_CB':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:2916: undefined reference to `MicroProfileGpuFlip'
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:2961: undefined reference to `MicroProfileGpuGetTimeStamp'
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:2963: undefined reference to `MicroProfileTicksPerSecondGpu'
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:3076: undefined reference to `MicroProfileGpuGetTimeStamp'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileCalcAllTimers(float*, float*, float*, float*, float*, float*, float*, float*, float*, unsigned int)':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:3545: undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileGetTime':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:3598: undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileDumpCsv(void (*)(void*, unsigned long, char const*), void*)':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:3958: undefined reference to `MicroProfileTicksPerSecondGpu'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileDumpHtml(void (*)(void*, unsigned long, char const*), void*, unsigned long, char const*, unsigned long)':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:4087: undefined reference to `MicroProfileTicksPerSecondGpu'
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:4393: undefined reference to `MicroProfileTicksPerSecondGpu'
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:4395: undefined reference to `MicroProfileGetGpuTickReference'
CMakeFiles/main.dir/lib/microprofile/microprofile.cpp.o: In function `MicroProfileWebSocketSendFrame(int)':
/home/xinlnix/project/software/jichuang2021/jichuang2021/lib/microprofile/microprofile.cpp:6622: undefined reference to `MicroProfileTicksPerSecondGpu'
collect2: error: ld returned 1 exit status

Is there any known limitation in frame history length?

I increased MICROPROFILE_MAX_FRAME_HISTORY to 50000 to be able to create longer recordings (few minutes).

  • When I try to capture 1000 frames using http://127.0.0.1:1338/1000 it loads fine and I am able to save such recording. It is then approximately 155MB large.
  • When I try to capture 2000 frames it also loads fine however Chrome fails when I am trying to save it
  • When I try to capture 5000 frames the page is not even loaded

I even tried using MICROPROFILE_MINIZ and there was no visible effect. Is there any known limitation in frame history length or capture size?

OpenGL profiling?

Is OpenGL profiling deprecated? I cannot find a demo that does this.

Tried to build microprofile with -DMICROPROFILE_GPU_TIMERS=1 -DMICROPROFILE_GPU_TIMERS_GL=1 on OS X. After adding the missing gl headers to microprofile.cpp the build fails with a linker error that no _MicroProfileGpuFlip and _MicroProfileGpuShutdown are found.

Any help would be appreciated.

Whether it is possible to add NVIDIA CUDA GPU API profile support.

Hi! Thanks for providing such a super-cool project.
I wonder, if it is possible to add Nvidia Cuda GPU support, especially for the Event timing. (Although using device sync and thus via CPU timing is possible, but it will cause the kernel stalled :-(
Any comment/reply will help a lot.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.