Skip to content

Commit

Permalink
#90, #23: Adding support for startup profiling and automation
Browse files Browse the repository at this point in the history
- Embedding miniz library for capture compression
- Adding support for general application profiling
Optick now can operate without GUI and save captures directly to the provided path.
  • Loading branch information
bombomby committed Aug 11, 2019
1 parent f4d1cb8 commit 8b47259
Show file tree
Hide file tree
Showing 12 changed files with 9,383 additions and 18 deletions.
2 changes: 2 additions & 0 deletions generate_projects.all.bat
@@ -0,0 +1,2 @@
tools\windows\premake5.exe --DX12 --Vulkan --Fibers vs2017
PAUSE
26 changes: 23 additions & 3 deletions gui/Data/Capture.cs
Expand Up @@ -8,15 +8,16 @@

namespace Profiler.Data
{
public class Capture
{
public class Capture
{
public class OptickHeader
{
const UInt32 OPTICK_MAGIC = 0xB50FB50F;
const UInt16 OPTICK_VERSION = 0;
public enum Flags : UInt16
{
IsZip = 1 << 0,
IsMiniz = 1 << 1,
}

public UInt32 Magic { get; set; }
Expand Down Expand Up @@ -48,6 +49,11 @@ public bool IsZip
get { return (Settings & Flags.IsZip) != 0; }
}

public bool IsMiniz
{
get { return (Settings & Flags.IsMiniz) != 0; }
}

public void Write(Stream stream)
{
BinaryWriter writer = new BinaryWriter(stream);
Expand All @@ -65,7 +71,21 @@ public static Stream Open(String path)
OptickHeader header = new OptickHeader(stream);
if (header.IsValid)
{
return (header.IsZip ? (Stream)new GZipStream(stream, CompressionMode.Decompress, false) : stream);
if (header.IsZip)
return new GZipStream(stream, CompressionMode.Decompress, false);

if (header.IsMiniz)
{
// Workaround for RFC 1950 vs RFC 1951 mismatch
// http://george.chiramattel.com/blog/2007/09/deflatestream-block-length-does-not-match.html
stream.ReadByte();
stream.ReadByte();

return new DeflateStream(stream, CompressionMode.Decompress);
}

return stream;

}
else
{
Expand Down
26 changes: 25 additions & 1 deletion samples/ConsoleApp/main.cpp
Expand Up @@ -14,6 +14,25 @@

using namespace std;

// Testing OPTICK_APP macro for startup performance analysis
void TestOptickApp(Test::Engine& engine)
{
OPTICK_APP("ConsoleApp");
for (int i = 0; i < 3; ++i)
engine.Update();
}


// Testing OPTICK_START_CAPTURE/OPTICK_STOP_CAPTURE/OPTICK_SAVE_CAPTURE for performance automation
void TestAutomation(Test::Engine& engine)
{
OPTICK_START_CAPTURE();
for (int i = 0; i < 3; ++i)
engine.Update();
OPTICK_STOP_CAPTURE();
OPTICK_SAVE_CAPTURE("ConsoleApp");
}

#if OPTICK_MSVC
int wmain()
#else
Expand All @@ -27,12 +46,17 @@ int main()

cout << "Starting main loop update." << endl;

// Setting memory allocators
OPTICK_SET_MEMORY_ALLOCATOR(
[](size_t size) -> void* { return operator new(size); },
[](void* p) { operator delete(p); },
[]() { /* Do some TLS initialization here if needed */ }
);



//TestOptickApp(engine);
//TestAutomation(engine);

bool needExit = false;
while( !needExit )
{
Expand Down
69 changes: 69 additions & 0 deletions src/optick.h
Expand Up @@ -327,26 +327,42 @@ struct Mode
{
enum Type
{
// OFF
OFF = 0x0,
// Collect Categories (top-level events)
INSTRUMENTATION_CATEGORIES = (1 << 0),
// Collect Events
INSTRUMENTATION_EVENTS = (1 << 1),
// Collect Events + Categories
INSTRUMENTATION = (INSTRUMENTATION_CATEGORIES | INSTRUMENTATION_EVENTS),
// Legacy (keep for compatibility reasons)
SAMPLING = (1 << 2),
// Collect Data Tags
TAGS = (1 << 3),
// Enable Autosampling Events (automatic callstacks)
AUTOSAMPLING = (1 << 4),
// Enable Switch-Contexts Events
SWITCH_CONTEXT = (1 << 5),
// Collect I/O Events
IO = (1 << 6),
// Collect GPU Events
GPU = (1 << 7),
END_SCREENSHOT = (1 << 8),
RESERVED_0 = (1 << 9),
RESERVED_1 = (1 << 10),
// Collect HW Events
HW_COUNTERS = (1 << 11),
// Collect Events in Live mode
LIVE = (1 << 12),
RESERVED_2 = (1 << 13),
RESERVED_3 = (1 << 14),
RESERVED_4 = (1 << 15),
// Collect System Calls
SYS_CALLS = (1 << 16),
// Collect Events from Other Processes
OTHER_PROCESSES = (1 << 17),
// Automation
NOGUI = (1 << 18),

TRACER = AUTOSAMPLING | SWITCH_CONTEXT | SYS_CALLS,
DEFAULT = INSTRUMENTATION | TAGS | AUTOSAMPLING | SWITCH_CONTEXT | IO | GPU | SYS_CALLS | OTHER_PROCESSES,
Expand Down Expand Up @@ -666,6 +682,20 @@ typedef void (*InitThreadCb)(void);
OPTICK_API void SetAllocator(AllocateFn allocateFn, DeallocateFn deallocateFn, InitThreadCb initThreadCb);
OPTICK_API void Shutdown();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef void(*CaptureSaveChunkCb)(const char*,size_t);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
OPTICK_API bool StartCapture(Mode::Type mode = Mode::DEFAULT, int samplingFrequency = 1000, bool force = true);
OPTICK_API bool StopCapture(bool force = true);
OPTICK_API bool SaveCapture(CaptureSaveChunkCb dataCb, bool force = true);
OPTICK_API bool SaveCapture(const char* path, bool force = true);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct OptickApp
{
const char* m_Name;
OptickApp(const char* name) : m_Name(name) { StartCapture(); }
~OptickApp() { StopCapture(); SaveCapture(m_Name); }
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

#define OPTICK_UNUSED(x) (void)(x)
Expand Down Expand Up @@ -876,6 +906,41 @@ OPTICK_API void Shutdown();

#define OPTICK_GPU_FLIP(SWAP_CHAIN) ::Optick::GpuFlip(SWAP_CHAIN);

/////////////////////////////////////////////////////////////////////////////////
// [Automation][Startup]
/////////////////////////////////////////////////////////////////////////////////

// Starts a new capture
// Params:
// [Optional] Mode::Type mode /*= Mode::DEFAULT*/
// [Optional] int samplingFrequency /*= 1000*/
#define OPTICK_START_CAPTURE(...) ::Optick::StartCapture(__VA_ARGS__);

// Stops a new capture (Keeps data intact in the local buffers)
#define OPTICK_STOP_CAPTURE(...) ::Optick::StopCapture(__VA_ARGS__);

// Saves capture
// Params:
// const char* FilePath - path to the capture
// or
// CaptureSaveChunkCb dataCb - callback for saving chunks of data
// Example:
// OPTICK_SAVE_CAPTURE("ConsoleApp.opt");
#define OPTICK_SAVE_CAPTURE(...) ::Optick::SaveCapture(__VA_ARGS__);

// Generate a capture for the whole scope
// Params:
// NAME - name of the application
// Examples:
// int main() {
// OPTICK_APP("MyGame"); //Optick will automatically save a capture in the working directory with the name "MyGame(2019-09-08.14-30-19).opt"
// ...
// }
#define OPTICK_APP(NAME) OPTICK_THREAD(NAME); \
::Optick::OptickApp _optickApp(NAME); \
OPTICK_UNUSED(_optickApp);


#else
#define OPTICK_EVENT(...)
#define OPTICK_CATEGORY(NAME, CATEGORY)
Expand Down Expand Up @@ -903,4 +968,8 @@ OPTICK_API void Shutdown();
#define OPTICK_GPU_FLIP(SWAP_CHAIN)
#define OPTICK_UPDATE()
#define OPTICK_FRAME_FLIP(...)
#define OPTICK_START_CAPTURE(...)
#define OPTICK_STOP_CAPTURE()
#define OPTICK_SAVE_CAPTURE(...)
#define OPTICK_APP(NAME)
#endif

0 comments on commit 8b47259

Please sign in to comment.