integrate ETW windows event tracing into mimalloc as another track tool

This commit is contained in:
Daan Leijen 2023-03-16 20:08:43 -07:00
parent 072316bd33
commit 1a99efc671
10 changed files with 80 additions and 28 deletions

View File

@ -12,6 +12,7 @@ option(MI_XMALLOC "Enable abort() call on memory allocation failure by
option(MI_SHOW_ERRORS "Show error and warning messages by default (only enabled by default in DEBUG mode)" OFF)
option(MI_TRACK_VALGRIND "Compile with Valgrind support (adds a small overhead)" OFF)
option(MI_TRACK_ASAN "Compile with address sanitizer support (adds a small overhead)" OFF)
option(MI_TRACK_ETW "Compile with Windows event tracing (ETW) support (adds a small overhead)" OFF)
option(MI_USE_CXX "Use the C++ compiler to compile the library (instead of the C compiler)" OFF)
option(MI_SEE_ASM "Generate assembly files" OFF)
option(MI_OSX_INTERPOSE "Use interpose to override standard malloc on macOS" ON)
@ -165,6 +166,21 @@ if(MI_TRACK_ASAN)
endif()
endif()
if(MI_TRACK_ETW)
if NOT WIN32
set(MI_TRACK_ETW OFF)
message(WARNING "Can only enable ETW support on Windows (MI_TRACK_ETW=OFF)")
endif()
if (MI_TRACK_VALGRIND OR MI_TRACK_ASAN)
set(MI_TRACK_ETW OFF)
message(WARNING "Cannot enable ETW support with also Valgrind or ASAN support enabled (MI_TRACK_ETW=OFF)")
endif()
if(MI_TRACK_ETW)
message(STATUS "Compile with Windows event tracing support (MI_TRACK_ETW=ON)")
list(APPEND mi_defines MI_TRACK_ETW=1)
endif()
endif()
if(MI_SEE_ASM)
message(STATUS "Generate assembly listings (MI_SEE_ASM=ON)")
list(APPEND mi_cflags -save-temps)

View File

@ -1,4 +0,0 @@
#pragma once
#include <windows.h>
#include "mimalloc-etw-gen.h"

View File

@ -27,10 +27,12 @@ Optional:
#define mi_track_align(p,alignedp,offset,size)
#define mi_track_resize(p,oldsize,newsize)
#define mi_track_init()
The `mi_track_align` is called right after a `mi_track_malloc` for aligned pointers in a block.
The corresponding `mi_track_free` still uses the block start pointer and original size (corresponding to the `mi_track_malloc`).
The `mi_track_resize` is currently unused but could be called on reallocations within a block.
`mi_track_init` is called at program start.
The following macros are for tools like asan and valgrind to track whether memory is
defined, undefined, or not accessible at all:
@ -42,6 +44,7 @@ defined, undefined, or not accessible at all:
-------------------------------------------------------------------------------------------------------*/
#if MI_TRACK_VALGRIND
// valgrind tool
#define MI_TRACK_ENABLED 1
#define MI_TRACK_HEAP_DESTROY 1 // track free of individual blocks on heap_destroy
@ -58,6 +61,7 @@ defined, undefined, or not accessible at all:
#define mi_track_mem_noaccess(p,size) VALGRIND_MAKE_MEM_NOACCESS(p,size)
#elif MI_TRACK_ASAN
// address sanitizer
#define MI_TRACK_ENABLED 1
#define MI_TRACK_HEAP_DESTROY 0
@ -71,19 +75,23 @@ defined, undefined, or not accessible at all:
#define mi_track_mem_undefined(p,size) ASAN_UNPOISON_MEMORY_REGION(p,size)
#define mi_track_mem_noaccess(p,size) ASAN_POISON_MEMORY_REGION(p,size)
#elif MI_ETW
#define MI_TRACK_ENABLED 1
#define MI_TRACK_TOOL "ETW"
#elif MI_TRACK_ETW
// windows event tracing
#include "mimalloc-etw.h"
#define MI_TRACK_ENABLED 1
#define MI_TRACK_HEAP_DESTROY 0
#define MI_TRACK_TOOL "ETW"
#define mi_track_malloc_size(p,reqsize,size,zero) EventWriteETW_MI_ALLOC((UINT64)p, size)
#define mi_track_free_size(p,size) EventWriteETW_MI_FREE((UINT64)p, size)
#define mi_track_mem_defined(p,size)
#define mi_track_mem_undefined(p,size)
#define mi_track_mem_noaccess(p,size)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "../src/prim/windows/etw.h"
#define mi_track_init() EventRegistermicrosoft_windows_mimalloc();
#define mi_track_malloc_size(p,reqsize,size,zero) EventWriteETW_MI_ALLOC((UINT64)(p), size)
#define mi_track_free_size(p,size) EventWriteETW_MI_FREE((UINT64)(p), size)
#else
// no tracking
#define MI_TRACK_ENABLED 0
#define MI_TRACK_HEAP_DESTROY 0
@ -91,11 +99,6 @@ defined, undefined, or not accessible at all:
#define mi_track_malloc_size(p,reqsize,size,zero)
#define mi_track_free_size(p,_size)
#define mi_track_align(p,alignedp,offset,size)
#define mi_track_resize(p,oldsize,newsize)
#define mi_track_mem_defined(p,size)
#define mi_track_mem_undefined(p,size)
#define mi_track_mem_noaccess(p,size)
#endif
@ -110,6 +113,23 @@ defined, undefined, or not accessible at all:
#define mi_track_align(p,alignedp,offset,size) mi_track_mem_noaccess(p,offset)
#endif
#ifndef mi_track_init
#define mi_track_init()
#endif
#ifndef mi_track_mem_defined
#define mi_track_mem_defined(p,size)
#endif
#ifndef mi_track_mem_undefined
#define mi_track_mem_undefined(p,size)
#endif
#ifndef mi_track_mem_noaccess
#define mi_track_mem_noaccess(p,size)
#endif
#if MI_PADDING
#define mi_track_malloc(p,reqsize,zero) \
if ((p)!=NULL) { \

View File

@ -32,8 +32,7 @@ terms of the MIT license. A copy of the license can be found in the file
// Define MI_TRACK_<tool> to enable tracking support
// #define MI_TRACK_VALGRIND 1
// #define MI_TRACK_ASAN 1
// Define MI_ETW to enable ETW provider
#define MI_ETW 1
#define MI_TRACK_ETW 1
// Define MI_STAT as 1 to maintain statistics; set it to 2 to have detailed statistics (but costs some performance).
// #define MI_STAT 1
@ -62,7 +61,7 @@ terms of the MIT license. A copy of the license can be found in the file
// Reserve extra padding at the end of each block to be more resilient against heap block overflows.
// The padding can detect buffer overflow on free.
#if !defined(MI_PADDING) && (MI_SECURE>=3 || MI_DEBUG>=1 || MI_TRACK_VALGRIND || MI_TRACK_ASAN || MI_ETW)
#if !defined(MI_PADDING) && (MI_SECURE>=3 || MI_DEBUG>=1 || (MI_TRACK_VALGRIND || MI_TRACK_ASAN || MI_TRACK_ETW))
#define MI_PADDING 1
#endif

View File

@ -534,6 +534,7 @@ void mi_process_init(void) mi_attr_noexcept {
#endif
mi_stats_reset(); // only call stat reset *after* thread init (or the heap tld == NULL)
mi_track_init();
if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) {
size_t pages = mi_option_get_clamp(mi_option_reserve_huge_os_pages, 0, 128*1024);
@ -550,10 +551,6 @@ void mi_process_init(void) mi_attr_noexcept {
mi_reserve_os_memory((size_t)ksize*MI_KiB, true, true);
}
}
#ifdef MI_ETW
EventRegistermicrosoft_windows_mimalloc();
#endif
}
// Called when the process is done (through `at_exit`)

View File

@ -1,6 +1,8 @@
## Portability Primitives
This is the portability layer where all primitives needed from the OS are defined.
- `prim.h`: API definition
- `prim.c`: Selects one of `prim-unix.c`, `prim-wasi.c`, or `prim-windows.c` depending on the host platform.
- `prim.c`: Selects one of `unix/prim.c`, `wasi/prim.c`, or `windows/prim.c` depending on the host platform.
Note: still work in progress, there may be other places in the sources that still depend on OS ifdef's.
Note: still work in progress, there may still be places in the sources that still depend on OS ifdef's.

View File

@ -29,7 +29,12 @@
</SystemCollectorId>
<EventCollectorId Value="Mimalloc_Collector">
<EventProviders>
<EventProviderId Value="MimallocEventProvider" />
<EventProviderId Value="MimallocEventProvider" >
<Keywords>
<Keyword Value="100"/>
<Keyword Value="101"/>
</Keywords>
</EventProviderId>
</EventProviders>
</EventCollectorId>
</Collectors>

View File

@ -0,0 +1,17 @@
## Primitives:
- `prim.c` contains Windows primitives for OS allocation.
## Event Tracing for Windows (ETW)
- `etw.h` is generated from `etw.man` which contains the manifest for mimalloc events.
(100 is an allocation, 101 is for a free)
- `mimalloc.wprp` is a profile for the Windows Performance Recorder (WPR).
In an admin prompt, you can use:
```
> wpr -start src\prim\windows\mimalloc.wprp -filemode
> <my mimalloc program>
> wpr -stop test.etl
```
and then open `test.etl` in the Windows Performance Analyzer (WPA).