Skip to content

Commit 2deb6cf

Browse files
committed
page profile
1 parent c1e1d5c commit 2deb6cf

File tree

6 files changed

+300
-15
lines changed

6 files changed

+300
-15
lines changed

src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ SRCS := \
4444
jltypes gf typemap smallintset ast builtins module interpreter symbol \
4545
dlload sys init task array genericmemory staticdata toplevel jl_uv datatype \
4646
simplevector runtime_intrinsics precompile jloptions mtarraylist \
47-
threading scheduler stackwalk gc gc-debug gc-pages gc-stacks gc-alloc-profiler method \
47+
threading scheduler stackwalk gc gc-debug gc-pages gc-stacks gc-alloc-profiler gc-page-profiler method \
4848
jlapi signal-handling safepoint timing subtype rtutils gc-heap-snapshot \
4949
crc32c APInt-C processor ircode opaque_closure codegen-stubs coverage runtime_ccall
5050

src/gc-page-profiler.c

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
#include "gc-page-profiler.h"
4+
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
// whether page profiling is enabled
10+
int page_profile_enabled;
11+
// number of pages written
12+
size_t page_profile_pages_written;
13+
// stream to write page profile to
14+
ios_t *page_profile_stream;
15+
// mutex for page profile
16+
uv_mutex_t page_profile_lock;
17+
18+
gc_page_profiler_serializer_t gc_page_serializer_create(void) JL_NOTSAFEPOINT
19+
{
20+
gc_page_profiler_serializer_t serializer;
21+
if (__unlikely(page_profile_enabled)) {
22+
arraylist_new(&serializer.typestrs, GC_PAGE_SZ);
23+
}
24+
else {
25+
serializer.typestrs.len = 0;
26+
}
27+
return serializer;
28+
}
29+
30+
void gc_page_serializer_init(gc_page_profiler_serializer_t *serializer,
31+
jl_gc_pagemeta_t *pg) JL_NOTSAFEPOINT
32+
{
33+
if (__unlikely(page_profile_enabled)) {
34+
serializer->typestrs.len = 0;
35+
serializer->data = (char *)pg->data;
36+
serializer->osize = pg->osize;
37+
}
38+
}
39+
40+
void gc_page_serializer_destroy(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT
41+
{
42+
if (__unlikely(page_profile_enabled)) {
43+
arraylist_free(&serializer->typestrs);
44+
}
45+
}
46+
47+
void gc_page_serializer_write(gc_page_profiler_serializer_t *serializer,
48+
const char *str) JL_NOTSAFEPOINT
49+
{
50+
if (__unlikely(page_profile_enabled)) {
51+
arraylist_push(&serializer->typestrs, (void *)str);
52+
}
53+
}
54+
55+
void gc_enable_page_profile(void) JL_NOTSAFEPOINT
56+
{
57+
page_profile_enabled = 1;
58+
}
59+
60+
void gc_disable_page_profile(void) JL_NOTSAFEPOINT
61+
{
62+
page_profile_enabled = 0;
63+
}
64+
65+
int gc_page_profile_is_enabled(void) JL_NOTSAFEPOINT
66+
{
67+
return page_profile_enabled;
68+
}
69+
70+
void gc_page_profile_write_preamble(gc_page_profiler_serializer_t *serializer)
71+
JL_NOTSAFEPOINT
72+
{
73+
if (__unlikely(page_profile_enabled)) {
74+
char str[GC_TYPE_STR_MAXLEN];
75+
snprintf(str, GC_TYPE_STR_MAXLEN,
76+
"{\"address\": \"%p\",\"object_size\": %d,\"objects\": [",
77+
serializer->data, serializer->osize);
78+
ios_write(page_profile_stream, str, strlen(str));
79+
}
80+
}
81+
82+
void gc_page_profile_write_epilogue(gc_page_profiler_serializer_t *serializer)
83+
JL_NOTSAFEPOINT
84+
{
85+
if (__unlikely(page_profile_enabled)) {
86+
char str[GC_TYPE_STR_MAXLEN];
87+
snprintf(str, GC_TYPE_STR_MAXLEN, "]}");
88+
ios_write(page_profile_stream, str, strlen(str));
89+
}
90+
}
91+
92+
void gc_page_profile_write_comma(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT
93+
{
94+
if (__unlikely(page_profile_enabled)) {
95+
// write comma if not first page
96+
if (page_profile_pages_written > 0) {
97+
char str[GC_TYPE_STR_MAXLEN];
98+
snprintf(str, GC_TYPE_STR_MAXLEN, ",");
99+
ios_write(page_profile_stream, str, strlen(str));
100+
}
101+
}
102+
}
103+
104+
void gc_page_profile_write_to_file(gc_page_profiler_serializer_t *serializer)
105+
JL_NOTSAFEPOINT
106+
{
107+
if (__unlikely(page_profile_enabled)) {
108+
// write to file
109+
uv_mutex_lock(&page_profile_lock);
110+
gc_page_profile_write_comma(serializer);
111+
gc_page_profile_write_preamble(serializer);
112+
char str[GC_TYPE_STR_MAXLEN];
113+
for (size_t i = 0; i < serializer->typestrs.len; i++) {
114+
const char *name = (const char *)serializer->typestrs.items[i];
115+
if (name == GC_SERIALIZER_EMPTY) {
116+
snprintf(str, GC_TYPE_STR_MAXLEN, "\"empty\",");
117+
}
118+
else if (name == GC_SERIALIZER_GARBAGE) {
119+
snprintf(str, GC_TYPE_STR_MAXLEN, "\"garbage\",");
120+
}
121+
else {
122+
snprintf(str, GC_TYPE_STR_MAXLEN, "\"%s\",", name);
123+
}
124+
// remove trailing comma for last element
125+
if (i == serializer->typestrs.len - 1) {
126+
str[strlen(str) - 1] = '\0';
127+
}
128+
ios_write(page_profile_stream, str, strlen(str));
129+
}
130+
gc_page_profile_write_epilogue(serializer);
131+
page_profile_pages_written++;
132+
uv_mutex_unlock(&page_profile_lock);
133+
}
134+
}
135+
136+
void gc_page_profile_write_json_preamble(ios_t *stream) JL_NOTSAFEPOINT
137+
{
138+
if (__unlikely(page_profile_enabled)) {
139+
uv_mutex_lock(&page_profile_lock);
140+
char str[GC_TYPE_STR_MAXLEN];
141+
snprintf(str, GC_TYPE_STR_MAXLEN, "{\"pages\": [");
142+
ios_write(stream, str, strlen(str));
143+
uv_mutex_unlock(&page_profile_lock);
144+
}
145+
}
146+
147+
void gc_page_profile_write_json_epilogue(ios_t *stream) JL_NOTSAFEPOINT
148+
{
149+
if (__unlikely(page_profile_enabled)) {
150+
uv_mutex_lock(&page_profile_lock);
151+
char str[GC_TYPE_STR_MAXLEN];
152+
snprintf(str, GC_TYPE_STR_MAXLEN, "]}");
153+
ios_write(stream, str, strlen(str));
154+
uv_mutex_unlock(&page_profile_lock);
155+
}
156+
}
157+
158+
JL_DLLEXPORT void jl_gc_take_page_profile(ios_t *stream)
159+
{
160+
gc_enable_page_profile();
161+
page_profile_pages_written = 0;
162+
page_profile_stream = stream;
163+
gc_page_profile_write_json_preamble(stream);
164+
jl_gc_collect(JL_GC_FULL);
165+
gc_page_profile_write_json_epilogue(stream);
166+
gc_disable_page_profile();
167+
}
168+
169+
#ifdef __cplusplus
170+
}
171+
#endif

src/gc-page-profiler.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// This file is a part of Julia. License is MIT: https://julialang.org/license
2+
3+
#ifndef GC_PAGE_PROFILER_H
4+
#define GC_PAGE_PROFILER_H
5+
6+
#include "gc.h"
7+
8+
#ifdef __cplusplus
9+
extern "C" {
10+
#endif
11+
12+
#define GC_TYPE_STR_MAXLEN (512)
13+
14+
typedef struct {
15+
arraylist_t typestrs;
16+
char *data;
17+
int osize;
18+
} gc_page_profiler_serializer_t;
19+
20+
// mutex for page profile
21+
extern uv_mutex_t page_profile_lock;
22+
23+
// Serializer functions
24+
gc_page_profiler_serializer_t gc_page_serializer_create(void) JL_NOTSAFEPOINT;
25+
void gc_page_serializer_init(gc_page_profiler_serializer_t *serializer, jl_gc_pagemeta_t *pg) JL_NOTSAFEPOINT;
26+
void gc_page_serializer_destroy(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT;
27+
void gc_page_serializer_write(gc_page_profiler_serializer_t *serializer, const char *str) JL_NOTSAFEPOINT;
28+
// Page profile functions
29+
#define GC_SERIALIZER_EMPTY ((const char *)0x1)
30+
#define GC_SERIALIZER_GARBAGE ((const char *)0x2)
31+
STATIC_INLINE void gc_page_profile_write_empty_page(gc_page_profiler_serializer_t *serializer,
32+
int enabled) JL_NOTSAFEPOINT
33+
{
34+
if (__unlikely(enabled)) {
35+
gc_page_serializer_write(serializer, GC_SERIALIZER_EMPTY);
36+
}
37+
}
38+
STATIC_INLINE void gc_page_profile_write_garbage(gc_page_profiler_serializer_t *serializer,
39+
int enabled) JL_NOTSAFEPOINT
40+
{
41+
if (__unlikely(enabled)) {
42+
gc_page_serializer_write(serializer, GC_SERIALIZER_GARBAGE);
43+
}
44+
}
45+
STATIC_INLINE void gc_page_profile_write_live_obj(gc_page_profiler_serializer_t *serializer,
46+
jl_taggedvalue_t *v,
47+
int enabled) JL_NOTSAFEPOINT
48+
{
49+
if (__unlikely(enabled)) {
50+
const char *name = jl_typeof_str(jl_valueof(v));
51+
gc_page_serializer_write(serializer, name);
52+
}
53+
}
54+
void gc_enable_page_profile(void) JL_NOTSAFEPOINT;
55+
void gc_disable_page_profile(void) JL_NOTSAFEPOINT;
56+
int gc_page_profile_is_enabled(void) JL_NOTSAFEPOINT;
57+
void gc_page_profile_write_to_file(gc_page_profiler_serializer_t *serializer) JL_NOTSAFEPOINT;
58+
59+
#ifdef __cplusplus
60+
}
61+
#endif
62+
63+
#endif // GC_PAGE_PROFILER_H

0 commit comments

Comments
 (0)