forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
291 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
// This file is a part of Julia. License is MIT: https://julialang.org/license | ||
|
||
#include "gc-page-profiler.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
// whether page profiling is enabled | ||
int page_profile_enabled; | ||
// number of pages written | ||
size_t page_profile_pages_written; | ||
// stream to write page profile to | ||
ios_t *page_profile_stream; | ||
// mutex for page profile | ||
uv_mutex_t page_profile_lock; | ||
|
||
#define GC_SERIALIZER_EMPTY ((const char *)0x1) | ||
#define GC_SERIALIZER_GARBAGE ((const char *)0x2) | ||
|
||
gc_page_profiler_serializer_t gc_page_serializer_create(void) JL_NOTSAFEPOINT | ||
{ | ||
gc_page_profiler_serializer_t serializer; | ||
serializer.length = 0; | ||
serializer.capacity = GC_PAGE_SZ; | ||
if (__unlikely(page_profile_enabled)) { | ||
serializer.buffer = (char const **)calloc_s(serializer.capacity); | ||
} | ||
else { | ||
serializer.buffer = NULL; | ||
} | ||
return serializer; | ||
} | ||
|
||
void gc_page_serializer_init(gc_page_profiler_serializer_t *serializer, | ||
jl_gc_pagemeta_t *pg) JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
memset(serializer->buffer, 0, serializer->capacity); | ||
serializer->length = 0; | ||
serializer->data = (char *)pg->data; | ||
serializer->osize = pg->osize; | ||
} | ||
} | ||
|
||
void gc_page_serializer_destroy(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT | ||
{ | ||
free(serializer->buffer); | ||
} | ||
|
||
void gc_page_serializer_write(gc_page_profiler_serializer_t *serializer, | ||
const char *str) JL_NOTSAFEPOINT | ||
{ | ||
serializer->buffer[serializer->length++] = str; | ||
} | ||
|
||
void gc_enable_page_profile(void) JL_NOTSAFEPOINT | ||
{ | ||
page_profile_enabled = 1; | ||
} | ||
|
||
void gc_disable_page_profile(void) JL_NOTSAFEPOINT | ||
{ | ||
page_profile_enabled = 0; | ||
} | ||
|
||
void gc_page_profile_write_empty_page(gc_page_profiler_serializer_t *serializer) | ||
JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
gc_page_serializer_write(serializer, GC_SERIALIZER_EMPTY); | ||
} | ||
} | ||
|
||
void gc_page_profile_write_garbage(gc_page_profiler_serializer_t *serializer) | ||
JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
gc_page_serializer_write(serializer, GC_SERIALIZER_GARBAGE); | ||
} | ||
} | ||
|
||
void gc_page_profile_write_live_obj(gc_page_profiler_serializer_t *serializer, | ||
jl_taggedvalue_t *v) JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
const char *name = jl_typeof_str(jl_valueof(v)); | ||
gc_page_serializer_write(serializer, name); | ||
} | ||
} | ||
|
||
void gc_page_profile_write_preamble(gc_page_profiler_serializer_t *serializer) | ||
JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
char str[GC_TYPE_STR_MAXLEN]; | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "{"); | ||
ios_write(page_profile_stream, str, strlen(str)); | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "\"address\": \"%p\",", serializer->data); | ||
ios_write(page_profile_stream, str, strlen(str)); | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "\"object_size\": %d,", serializer->osize); | ||
ios_write(page_profile_stream, str, strlen(str)); | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "\"objects\": ["); | ||
ios_write(page_profile_stream, str, strlen(str)); | ||
} | ||
} | ||
|
||
void gc_page_profile_write_epilogue(gc_page_profiler_serializer_t *serializer) | ||
JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
char str[GC_TYPE_STR_MAXLEN]; | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "]"); | ||
ios_write(page_profile_stream, str, strlen(str)); | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "}"); | ||
ios_write(page_profile_stream, str, strlen(str)); | ||
} | ||
} | ||
|
||
void gc_page_profile_write_comma(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
if (page_profile_pages_written > 0) { | ||
char str[GC_TYPE_STR_MAXLEN]; | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, ","); | ||
ios_write(page_profile_stream, str, strlen(str)); | ||
} | ||
} | ||
} | ||
|
||
void gc_page_profile_write_to_file(gc_page_profiler_serializer_t *serializer) | ||
JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
// write to file | ||
uv_mutex_lock(&page_profile_lock); | ||
gc_page_profile_write_comma(serializer); | ||
gc_page_profile_write_preamble(serializer); | ||
char str[GC_TYPE_STR_MAXLEN]; | ||
for (size_t i = 0; i < serializer->length; i++) { | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
if (serializer->buffer[i] == GC_SERIALIZER_EMPTY) { | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "\"empty\","); | ||
} | ||
else if (serializer->buffer[i] == GC_SERIALIZER_GARBAGE) { | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "\"garbage\","); | ||
} | ||
else { | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "\"%s\",", serializer->buffer[i]); | ||
} | ||
if (i == serializer->length - 1) { | ||
str[strlen(str) - 1] = '\0'; | ||
} | ||
ios_write(page_profile_stream, str, strlen(str)); | ||
} | ||
gc_page_profile_write_epilogue(serializer); | ||
page_profile_pages_written++; | ||
uv_mutex_unlock(&page_profile_lock); | ||
} | ||
} | ||
|
||
void gc_page_profile_write_json_preamble(ios_t *stream) JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
uv_mutex_lock(&page_profile_lock); | ||
char str[GC_TYPE_STR_MAXLEN]; | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "{"); | ||
ios_write(stream, str, strlen(str)); | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "\"pages\": ["); | ||
ios_write(stream, str, strlen(str)); | ||
uv_mutex_unlock(&page_profile_lock); | ||
} | ||
} | ||
|
||
void gc_page_profile_write_json_epilogue(ios_t *stream) JL_NOTSAFEPOINT | ||
{ | ||
if (__unlikely(page_profile_enabled)) { | ||
uv_mutex_lock(&page_profile_lock); | ||
char str[GC_TYPE_STR_MAXLEN]; | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "]"); | ||
ios_write(stream, str, strlen(str)); | ||
memset(str, 0, GC_TYPE_STR_MAXLEN); | ||
snprintf(str, GC_TYPE_STR_MAXLEN, "}"); | ||
ios_write(stream, str, strlen(str)); | ||
uv_mutex_unlock(&page_profile_lock); | ||
} | ||
} | ||
|
||
JL_DLLEXPORT void jl_gc_take_page_profile(ios_t *stream) | ||
{ | ||
gc_enable_page_profile(); | ||
page_profile_stream = stream; | ||
gc_page_profile_write_json_preamble(stream); | ||
jl_gc_collect(JL_GC_FULL); | ||
gc_page_profile_write_json_epilogue(stream); | ||
gc_disable_page_profile(); | ||
} | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// This file is a part of Julia. License is MIT: https://julialang.org/license | ||
|
||
#ifndef GC_PAGE_PROFILER_H | ||
#define GC_PAGE_PROFILER_H | ||
|
||
#include "gc.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#define GC_TYPE_STR_MAXLEN (512) | ||
|
||
typedef struct { | ||
size_t length; | ||
size_t capacity; | ||
char const **buffer; | ||
char *data; | ||
int osize; | ||
} gc_page_profiler_serializer_t; | ||
|
||
// mutex for page profile | ||
extern uv_mutex_t page_profile_lock; | ||
|
||
// Serializer functions | ||
gc_page_profiler_serializer_t gc_page_serializer_create(void) JL_NOTSAFEPOINT; | ||
void gc_page_serializer_init(gc_page_profiler_serializer_t *serializer, jl_gc_pagemeta_t *pg) JL_NOTSAFEPOINT; | ||
void gc_page_serializer_destroy(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT; | ||
void gc_page_serializer_write(gc_page_profiler_serializer_t *serializer, const char *str) JL_NOTSAFEPOINT; | ||
// Page profile functions | ||
void gc_page_profile_write_preamble(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT; | ||
void gc_page_profile_write_epilogue(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT; | ||
void gc_page_profile_write_empty_page(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT; | ||
void gc_page_profile_write_garbage(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT; | ||
void gc_page_profile_write_live_obj(gc_page_profiler_serializer_t *serializer, jl_taggedvalue_t *v) JL_NOTSAFEPOINT; | ||
void gc_enable_page_profile(void) JL_NOTSAFEPOINT; | ||
void gc_disable_page_profile(void) JL_NOTSAFEPOINT; | ||
void gc_page_profile_write_to_file(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT; | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif // GC_PAGE_PROFILER_H |
Oops, something went wrong.